Android AES加解密

工具類

/**
 * AES加解密工具類, 使用Base64進(jìn)行編解碼
 *     String value = AESUtil.encrypt("mazaiting", "123456789");
       Log.e("MainActivity", value);
       Log.e("MainActivity", AESUtil.decrypt("mazaiting", value));
 * Created by mazaiting on 2018/6/22.
 */

public class AESUtil {
  /**密鑰長度*/
  private static final int KEY_LENGTH = 16;
  /**默認(rèn)填充位數(shù)*/
  private static final String DEFAULT_VALUE = "0";
  /**
   * 加密
   * @param key 密鑰
   * @param src 加密文本
   * @return 加密后的文本
   * @throws Exception
   */
  public static String encrypt(String key, String src) throws Exception {
    // 對源數(shù)據(jù)進(jìn)行Base64編碼
    src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    // 補(bǔ)全KEY為16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 獲取加密后的字節(jié)數(shù)組
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"), Cipher.ENCRYPT_MODE);
    // 對加密后的字節(jié)數(shù)組進(jìn)行Base64編碼
    result = Base64.encode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, Charset.defaultCharset());
  }
  
  /**
   * 解密
   * @param key 密鑰
   * @param encrypted 待解密文本
   * @return 返回解密后的數(shù)據(jù)
   * @throws Exception
   */
  public static String decrypt(String key, String encrypted) throws Exception {
    // 補(bǔ)全KEY為16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 獲取加密后的二進(jìn)制字節(jié)數(shù)組
    byte[] enc = encrypted.getBytes(Charset.defaultCharset());
    // 對二進(jìn)制數(shù)組進(jìn)行Base64解碼
    enc = Base64.decode(enc, Base64.DEFAULT);
    // 獲取解密后的二進(jìn)制字節(jié)數(shù)組
    byte[] result = getBytes(rawKey, enc, Cipher.DECRYPT_MODE);
    // 對解密后的二進(jìn)制數(shù)組進(jìn)行Base64解碼
    result = Base64.decode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, "utf-8");
  }
  
  /**
   * 密鑰key ,默認(rèn)補(bǔ)的數(shù)字,補(bǔ)全16位數(shù),以保證安全補(bǔ)全至少16位長度,android和ios對接通過
   * @param key 密鑰key
   * @param length 密鑰應(yīng)有的長度
   * @param text 默認(rèn)補(bǔ)的文本
   * @return 密鑰
   */
  private static String toMakeKey(String key, int length, String text) {
    // 獲取密鑰長度
    int strLen = key.length();
    // 判斷長度是否小于應(yīng)有的長度
    if (strLen < length) {
      // 補(bǔ)全位數(shù)
      StringBuilder builder = new StringBuilder();
      // 將key添加至builder中
      builder.append(key);
      // 遍歷添加默認(rèn)文本
      for (int i = 0; i < length - strLen; i++) {
        builder.append(text);
      }
      // 賦值
      key = builder.toString();
    }
    return key;
  }
  
  /**
   * 加解密過程
   * 1. 通過密鑰得到一個(gè)密鑰專用的對象SecretKeySpec
   * 2. Cipher 加密算法钻心,加密模式和填充方式三部分或指定加密算 (可以只用寫算法然后用默認(rèn)的其他方式)Cipher.getInstance("AES");
   * @param key 二進(jìn)制密鑰數(shù)組
   * @param src 加解密的源二進(jìn)制數(shù)據(jù)
   * @param mode 模式笨触,加密為:Cipher.ENCRYPT_MODE;解密為:Cipher.DECRYPT_MODE
   * @return 加解密后的二進(jìn)制數(shù)組
   * @throws NoSuchAlgorithmException 無效算法
   * @throws NoSuchPaddingException 無效填充
   * @throws InvalidKeyException 無效KEY
   * @throws InvalidAlgorithmParameterException 無效密鑰
   * @throws IllegalBlockSizeException 非法塊字節(jié)
   * @throws BadPaddingException 壞數(shù)據(jù)
   */
  private static byte[] getBytes(byte[] key, byte[] src, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    // 密鑰規(guī)格
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    // 密鑰實(shí)例
    Cipher cipher = Cipher.getInstance("AES");
    // 初始化密鑰模式
    cipher.init(mode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    // 加密數(shù)據(jù)
    return cipher.doFinal(src);
  }
}

使用

      String value = AESUtil.encrypt("mazaiting", "123456789");
       Log.e("MainActivity", value);
       Log.e("MainActivity", AESUtil.decrypt("mazaiting", value));

加密文件及字符串工具類

/**
 * Aes加密工具類
 * 使用:
 *          val value = AESUtil.encrypt("mazaiting", "123456789")
            Log.e("MainActivity", value)
            Log.e("MainActivity", AESUtil.decrypt("mazaiting", value))
 *
 * Created by mazaiting on 2018/6/21.
 */

public class AESUtil {
  /**16進(jìn)制數(shù)*/
  private final static String HEX = "0123456789ABCDEF";
  /**密鑰長度*/
  private static final int KEY_LENGTH = 16;
  /**默認(rèn)填充位數(shù)*/
  private static final String DEFAULT_VALUE = "0";
  
  /**
   * 加密
   * @param key 密鑰
   * @param src 加密文本
   * @return 加密后的文本
   * @throws Exception
   */
  public static String encrypt(String key, String src) throws Exception {
    // 對源數(shù)據(jù)進(jìn)行Base64編碼
    src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    // 補(bǔ)全KEY為16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 獲取加密后的字節(jié)數(shù)組
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"),"AES", Cipher.ENCRYPT_MODE);
    // 對加密后的字節(jié)數(shù)組進(jìn)行Base64編碼
    result = Base64.encode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, Charset.defaultCharset());
  }
  
  /**
   * 解密
   * @param key 密鑰
   * @param encrypted 待解密文本
   * @return 返回解密后的數(shù)據(jù)
   * @throws Exception
   */
  public static String decrypt(String key, String encrypted) throws Exception {
    // 補(bǔ)全KEY為16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 獲取加密后的二進(jìn)制字節(jié)數(shù)組
    byte[] enc = encrypted.getBytes(Charset.defaultCharset());
    // 對二進(jìn)制數(shù)組進(jìn)行Base64解碼
    enc = Base64.decode(enc, Base64.DEFAULT);
    // 獲取解密后的二進(jìn)制字節(jié)數(shù)組
    byte[] result = getBytes(rawKey, enc,"AES", Cipher.DECRYPT_MODE);
    // 對解密后的二進(jìn)制數(shù)組進(jìn)行Base64解碼
    result = Base64.decode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, "utf-8");
  }
  
  /**
   * 加密
   * @param key 密鑰
   * @param src 加密文本
   * @return 加密后的數(shù)據(jù)
   * @throws Exception
   */
  public static String encrypt2Java(String key, String src) throws Exception {
    // /src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();// key.getBytes();
//    byte[] result = encrypt2Java(rawKey, src.getBytes("utf-8"));
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"), "AES/CBC/PKCS5Padding", Cipher.ENCRYPT_MODE);
    // result = Base64.encode(result, Base64.DEFAULT);
    return toHex(result);
  }
  
  /**
   * 加密
   * @param key 密鑰
   * @param src 加密文本
   * @return 加密后的數(shù)據(jù)
   * @throws Exception
   */
  public static String decrypt2Java(String key, String src) throws Exception {
    // /src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();// key.getBytes();
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"), "AES/CBC/PKCS5Padding", Cipher.DECRYPT_MODE);
    // result = Base64.encode(result, Base64.DEFAULT);
    return toHex(result);
  }
  
  /**
   * 密鑰key ,默認(rèn)補(bǔ)的數(shù)字,補(bǔ)全16位數(shù)姿染,以保證安全補(bǔ)全至少16位長度,android和ios對接通過
   * @param key 密鑰key
   * @param length 密鑰應(yīng)有的長度
   * @param text 默認(rèn)補(bǔ)的文本
   * @return 密鑰
   */
  private static String toMakeKey(String key, int length, String text) {
    // 獲取密鑰長度
    int strLen = key.length();
    // 判斷長度是否小于應(yīng)有的長度
    if (strLen < length) {
      // 補(bǔ)全位數(shù)
      StringBuilder builder = new StringBuilder();
      // 將key添加至builder中
      builder.append(key);
      // 遍歷添加默認(rèn)文本
      for (int i = 0; i < length - strLen; i++) {
        builder.append(text);
      }
      // 賦值
      key = builder.toString();
    }
    return key;
  }
  
  /**
   * 加解密過程
   * 1. 通過密鑰得到一個(gè)密鑰專用的對象SecretKeySpec
   * 2. Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用寫算法然后用默認(rèn)的其他方式)Cipher.getInstance("AES");
   * @param key 二進(jìn)制密鑰數(shù)組
   * @param src 加解密的源二進(jìn)制數(shù)據(jù)
   * @param mode 模式,加密為:Cipher.ENCRYPT_MODE;解密為:Cipher.DECRYPT_MODE
   * @return 加解密后的二進(jìn)制數(shù)組
   * @throws NoSuchAlgorithmException 無效算法
   * @throws NoSuchPaddingException 無效填充
   * @throws InvalidKeyException 無效KEY
   * @throws InvalidAlgorithmParameterException 無效密鑰
   * @throws IllegalBlockSizeException 非法塊字節(jié)
   * @throws BadPaddingException 壞數(shù)據(jù)
   */
  private static byte[] getBytes(byte[] key, byte[] src,String transformation, int mode) throws
          NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
          InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    // 密鑰規(guī)格
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    // 密鑰實(shí)例
    Cipher cipher = Cipher.getInstance(transformation);
    // 初始化密鑰模式
    cipher.init(mode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    // 加密數(shù)據(jù)
    return cipher.doFinal(src);
  }
  
  /**獲取16進(jìn)制字符串*/
  public static String toHex(String txt) {
    return toHex(txt.getBytes());
  }
  /**將16進(jìn)制字符串轉(zhuǎn)換為未編碼后的數(shù)據(jù)*/
  public static String fromHex(String hex) {
    return new String(toByte(hex));
  }
  
  /**
   * 把16進(jìn)制轉(zhuǎn)化為字節(jié)數(shù)組
   * @param hexString 16進(jìn)制字符串
   * @return 加密后的字節(jié)數(shù)組
   */
  private static byte[] toByte(String hexString) {
    // 獲取源數(shù)據(jù)長度
    int len = hexString.length() / 2;
    // 創(chuàng)建字節(jié)數(shù)組
    byte[] result = new byte[len];
    // 遍歷
    for (int i = 0; i < len; i++)
      result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
    // 返回二進(jìn)制字節(jié)數(shù)組
    return result;
  }
  
  /**
   * 二進(jìn)制轉(zhuǎn)字符,轉(zhuǎn)成了16進(jìn)制
   * 0123456789abcdef
   * @param bytes 字節(jié)組數(shù)
   * @return 16進(jìn)制編碼的字符串
   */
  private static String toHex(byte[] bytes) {
    // 判斷二進(jìn)制數(shù)組長度是否小于0
    if (bytes.length <= 0) return "";
    // 創(chuàng)建字符串連接對象
    StringBuilder builder = new StringBuilder(2 * bytes.length);
    for (byte b : bytes) {
      // 拼接字符
      builder.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
    // 返回字符串
    return builder.toString();
  }
    
  /**
   * 對文件進(jìn)行AES加密
   * @param sourceFile 待加密文件
   * @param toFile 加密后的文件
   * @param dir 文件存儲(chǔ)路徑
   * @param key 密鑰
   * @return 加密后的文件
   */
  public static File encryptFile(File sourceFile, String toFile, String dir, String key) {
    // 新建臨時(shí)加密文件
    File encryptFile = null;
    // 輸入流
    InputStream inputStream = null;
    // 輸出流
    OutputStream outputStream = null;
    try {
      // 讀取源文件芹扭,創(chuàng)建文件輸入流
      inputStream = new FileInputStream(sourceFile);
      // 創(chuàng)建加密后的文件
      encryptFile = new File(dir + toFile);
      // 根據(jù)文件創(chuàng)建輸出流
      outputStream = new FileOutputStream(encryptFile);
      // 初始化 Cipher
      Cipher cipher = initAESCipher(key, Cipher.ENCRYPT_MODE);
      // 以加密流寫入文件
      CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
      // 創(chuàng)建緩存字節(jié)數(shù)組
      byte[] cache = new byte[1024];
      // 讀取
      int len;
      // 讀取加密并寫入文件
      while ((len = cipherInputStream.read(cache)) != -1) {
        outputStream.write(cache, 0, len);
        outputStream.flush();
      }
      // 關(guān)閉加密輸入流
      cipherInputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      closeStream(inputStream);
      closeStream(outputStream);
    }
    return encryptFile;
  }
  
  /**
   * AES方式解密文件
   * @param sourceFile 源文件
   * @param toFile 目標(biāo)文件
   * @param dir 文件存儲(chǔ)路徑
   * @param key 密鑰
   * @return
   */
  public static File decryptFile(File sourceFile, String toFile, String dir, String key) {
    // 解密文件
    File decryptFile = null;
    // 文件輸入流
    InputStream inputStream = null;
    // 文件輸出流
    OutputStream outputStream = null;
    try {
      // 創(chuàng)建解密文件
      decryptFile = new File(dir + toFile);
      // 初始化Cipher
      Cipher cipher = initAESCipher(key, Cipher.DECRYPT_MODE);
      // 根據(jù)源文件創(chuàng)建輸入流
      inputStream = new FileInputStream(sourceFile);
      // 創(chuàng)建輸出流
      outputStream = new FileOutputStream(decryptFile);
      // 獲取解密輸出流
      CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
      // 創(chuàng)建緩沖字節(jié)數(shù)組
      byte[] buffer = new byte[1024];
      int len;
      // 讀取解密并寫入
      while ((len = inputStream.read(buffer)) >= 0) {
        cipherOutputStream.write(buffer, 0, len);
        cipherOutputStream.flush();
      }
      // 關(guān)閉流
      cipherOutputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      closeStream(inputStream);
      closeStream(outputStream);
    }
    return decryptFile;
  }
  
  /**
   * 初始化 AES Cipher
   * @param key 密鑰
   * @param cipherMode 加密模式
   * @return 密鑰
   */
  private static Cipher initAESCipher(String key, int cipherMode) {
    Cipher cipher = null;
    try {
      // 將KEY進(jìn)行修正
      byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
      // 創(chuàng)建密鑰規(guī)格
      SecretKeySpec secretKeySpec = new SecretKeySpec(rawKey, "AES");
      // 獲取密鑰
      cipher = Cipher.getInstance("AES");
      // 初始化
      cipher.init(cipherMode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException e) {
      e.printStackTrace();
    }
    return cipher;
  }
  
  /**
   * 關(guān)閉流
   * @param closeable 實(shí)現(xiàn)Closeable接口
   */
  private static void closeStream(Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赦抖,隨后出現(xiàn)的幾起案子舱卡,更是在濱河造成了極大的恐慌,老刑警劉巖队萤,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轮锥,死亡現(xiàn)場離奇詭異,居然都是意外死亡要尔,警方通過查閱死者的電腦和手機(jī)舍杜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赵辕,“玉大人蝴簇,你說我怎么就攤上這事〈抑悖” “怎么了熬词?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吸重。 經(jīng)常有香客問我互拾,道長,這世上最難降的妖魔是什么嚎幸? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任颜矿,我火速辦了婚禮,結(jié)果婚禮上嫉晶,老公的妹妹穿的比我還像新娘骑疆。我一直安慰自己,他們只是感情好替废,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布箍铭。 她就那樣靜靜地躺著,像睡著了一般椎镣。 火紅的嫁衣襯著肌膚如雪诈火。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音霉涨,去河邊找鬼。 笑死棚饵,一個(gè)胖子當(dāng)著我的面吹牛拍摇,可吹牛的內(nèi)容都是我干的亮钦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼充活,長吁一口氣:“原來是場噩夢啊……” “哼或悲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起堪唐,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翎蹈,沒想到半個(gè)月后淮菠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荤堪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年合陵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澄阳。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拥知,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碎赢,到底是詐尸還是另有隱情低剔,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布肮塞,位于F島的核電站襟齿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏枕赵。R本人自食惡果不足惜猜欺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拷窜。 院中可真熱鬧开皿,春花似錦、人聲如沸篮昧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懊昨。三九已至糠睡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疚颊,已是汗流浹背狈孔。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工信认, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人均抽。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓嫁赏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親油挥。 傳聞我的和親對象是個(gè)殘疾皇子潦蝇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容