Android AES加解密

工具类

/**
 * AES加解密工具类, 使用Base64进行编解码
 *     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;
  /**默认填充位数*/
  private static final String DEFAULT_VALUE = "0";
  /**
   * 加密
   * @param key 密钥
   * @param src 加密文本
   * @return 加密后的文本
   * @throws Exception
   */
  public static String encrypt(String key, String src) throws Exception {
    // 对源数据进行Base64编码
    src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    // 补全KEY为16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 获取加密后的字节数组
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"), Cipher.ENCRYPT_MODE);
    // 对加密后的字节数组进行Base64编码
    result = Base64.encode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, Charset.defaultCharset());
  }
  
  /**
   * 解密
   * @param key 密钥
   * @param encrypted 待解密文本
   * @return 返回解密后的数据
   * @throws Exception
   */
  public static String decrypt(String key, String encrypted) throws Exception {
    // 补全KEY为16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 获取加密后的二进制字节数组
    byte[] enc = encrypted.getBytes(Charset.defaultCharset());
    // 对二进制数组进行Base64解码
    enc = Base64.decode(enc, Base64.DEFAULT);
    // 获取解密后的二进制字节数组
    byte[] result = getBytes(rawKey, enc, Cipher.DECRYPT_MODE);
    // 对解密后的二进制数组进行Base64解码
    result = Base64.decode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, "utf-8");
  }
  
  /**
   * 密钥key ,默认补的数字,补全16位数,以保证安全补全至少16位长度,android和ios对接通过
   * @param key 密钥key
   * @param length 密钥应有的长度
   * @param text 默认补的文本
   * @return 密钥
   */
  private static String toMakeKey(String key, int length, String text) {
    // 获取密钥长度
    int strLen = key.length();
    // 判断长度是否小于应有的长度
    if (strLen < length) {
      // 补全位数
      StringBuilder builder = new StringBuilder();
      // 将key添加至builder中
      builder.append(key);
      // 遍历添加默认文本
      for (int i = 0; i < length - strLen; i++) {
        builder.append(text);
      }
      // 赋值
      key = builder.toString();
    }
    return key;
  }
  
  /**
   * 加解密过程
   * 1. 通过密钥得到一个密钥专用的对象SecretKeySpec
   * 2. Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES");
   * @param key 二进制密钥数组
   * @param src 加解密的源二进制数据
   * @param mode 模式,加密为:Cipher.ENCRYPT_MODE;解密为:Cipher.DECRYPT_MODE
   * @return 加解密后的二进制数组
   * @throws NoSuchAlgorithmException 无效算法
   * @throws NoSuchPaddingException 无效填充
   * @throws InvalidKeyException 无效KEY
   * @throws InvalidAlgorithmParameterException 无效密钥
   * @throws IllegalBlockSizeException 非法块字节
   * @throws BadPaddingException 坏数据
   */
  private static byte[] getBytes(byte[] key, byte[] src, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    // 密钥规格
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    // 密钥实例
    Cipher cipher = Cipher.getInstance("AES");
    // 初始化密钥模式
    cipher.init(mode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    // 加密数据
    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进制数*/
  private final static String HEX = "0123456789ABCDEF";
  /**密钥长度*/
  private static final int KEY_LENGTH = 16;
  /**默认填充位数*/
  private static final String DEFAULT_VALUE = "0";
  
  /**
   * 加密
   * @param key 密钥
   * @param src 加密文本
   * @return 加密后的文本
   * @throws Exception
   */
  public static String encrypt(String key, String src) throws Exception {
    // 对源数据进行Base64编码
    src = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
    // 补全KEY为16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 获取加密后的字节数组
    byte[] result = getBytes(rawKey, src.getBytes("utf-8"),"AES", Cipher.ENCRYPT_MODE);
    // 对加密后的字节数组进行Base64编码
    result = Base64.encode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, Charset.defaultCharset());
  }
  
  /**
   * 解密
   * @param key 密钥
   * @param encrypted 待解密文本
   * @return 返回解密后的数据
   * @throws Exception
   */
  public static String decrypt(String key, String encrypted) throws Exception {
    // 补全KEY为16位
    byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
    // 获取加密后的二进制字节数组
    byte[] enc = encrypted.getBytes(Charset.defaultCharset());
    // 对二进制数组进行Base64解码
    enc = Base64.decode(enc, Base64.DEFAULT);
    // 获取解密后的二进制字节数组
    byte[] result = getBytes(rawKey, enc,"AES", Cipher.DECRYPT_MODE);
    // 对解密后的二进制数组进行Base64解码
    result = Base64.decode(result, Base64.DEFAULT);
    // 返回字符串
    return new String(result, "utf-8");
  }
  
  /**
   * 加密
   * @param key 密钥
   * @param src 加密文本
   * @return 加密后的数据
   * @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 加密后的数据
   * @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 ,默认补的数字,补全16位数,以保证安全补全至少16位长度,android和ios对接通过
   * @param key 密钥key
   * @param length 密钥应有的长度
   * @param text 默认补的文本
   * @return 密钥
   */
  private static String toMakeKey(String key, int length, String text) {
    // 获取密钥长度
    int strLen = key.length();
    // 判断长度是否小于应有的长度
    if (strLen < length) {
      // 补全位数
      StringBuilder builder = new StringBuilder();
      // 将key添加至builder中
      builder.append(key);
      // 遍历添加默认文本
      for (int i = 0; i < length - strLen; i++) {
        builder.append(text);
      }
      // 赋值
      key = builder.toString();
    }
    return key;
  }
  
  /**
   * 加解密过程
   * 1. 通过密钥得到一个密钥专用的对象SecretKeySpec
   * 2. Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES");
   * @param key 二进制密钥数组
   * @param src 加解密的源二进制数据
   * @param mode 模式,加密为:Cipher.ENCRYPT_MODE;解密为:Cipher.DECRYPT_MODE
   * @return 加解密后的二进制数组
   * @throws NoSuchAlgorithmException 无效算法
   * @throws NoSuchPaddingException 无效填充
   * @throws InvalidKeyException 无效KEY
   * @throws InvalidAlgorithmParameterException 无效密钥
   * @throws IllegalBlockSizeException 非法块字节
   * @throws BadPaddingException 坏数据
   */
  private static byte[] getBytes(byte[] key, byte[] src,String transformation, int mode) throws
          NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
          InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    // 密钥规格
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    // 密钥实例
    Cipher cipher = Cipher.getInstance(transformation);
    // 初始化密钥模式
    cipher.init(mode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    // 加密数据
    return cipher.doFinal(src);
  }
  
  /**获取16进制字符串*/
  public static String toHex(String txt) {
    return toHex(txt.getBytes());
  }
  /**将16进制字符串转换为未编码后的数据*/
  public static String fromHex(String hex) {
    return new String(toByte(hex));
  }
  
  /**
   * 把16进制转化为字节数组
   * @param hexString 16进制字符串
   * @return 加密后的字节数组
   */
  private static byte[] toByte(String hexString) {
    // 获取源数据长度
    int len = hexString.length() / 2;
    // 创建字节数组
    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();
    // 返回二进制字节数组
    return result;
  }
  
  /**
   * 二进制转字符,转成了16进制
   * 0123456789abcdef
   * @param bytes 字节组数
   * @return 16进制编码的字符串
   */
  private static String toHex(byte[] bytes) {
    // 判断二进制数组长度是否小于0
    if (bytes.length <= 0) return "";
    // 创建字符串连接对象
    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();
  }
    
  /**
   * 对文件进行AES加密
   * @param sourceFile 待加密文件
   * @param toFile 加密后的文件
   * @param dir 文件存储路径
   * @param key 密钥
   * @return 加密后的文件
   */
  public static File encryptFile(File sourceFile, String toFile, String dir, String key) {
    // 新建临时加密文件
    File encryptFile = null;
    // 输入流
    InputStream inputStream = null;
    // 输出流
    OutputStream outputStream = null;
    try {
      // 读取源文件,创建文件输入流
      inputStream = new FileInputStream(sourceFile);
      // 创建加密后的文件
      encryptFile = new File(dir + toFile);
      // 根据文件创建输出流
      outputStream = new FileOutputStream(encryptFile);
      // 初始化 Cipher
      Cipher cipher = initAESCipher(key, Cipher.ENCRYPT_MODE);
      // 以加密流写入文件
      CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
      // 创建缓存字节数组
      byte[] cache = new byte[1024];
      // 读取
      int len;
      // 读取加密并写入文件
      while ((len = cipherInputStream.read(cache)) != -1) {
        outputStream.write(cache, 0, len);
        outputStream.flush();
      }
      // 关闭加密输入流
      cipherInputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      closeStream(inputStream);
      closeStream(outputStream);
    }
    return encryptFile;
  }
  
  /**
   * AES方式解密文件
   * @param sourceFile 源文件
   * @param toFile 目标文件
   * @param dir 文件存储路径
   * @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 {
      // 创建解密文件
      decryptFile = new File(dir + toFile);
      // 初始化Cipher
      Cipher cipher = initAESCipher(key, Cipher.DECRYPT_MODE);
      // 根据源文件创建输入流
      inputStream = new FileInputStream(sourceFile);
      // 创建输出流
      outputStream = new FileOutputStream(decryptFile);
      // 获取解密输出流
      CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
      // 创建缓冲字节数组
      byte[] buffer = new byte[1024];
      int len;
      // 读取解密并写入
      while ((len = inputStream.read(buffer)) >= 0) {
        cipherOutputStream.write(buffer, 0, len);
        cipherOutputStream.flush();
      }
      // 关闭流
      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进行修正
      byte[] rawKey = toMakeKey(key, KEY_LENGTH, DEFAULT_VALUE).getBytes();
      // 创建密钥规格
      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;
  }
  
  /**
   * 关闭流
   * @param closeable 实现Closeable接口
   */
  private static void closeStream(Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容