密码学 09 AES

AES 表一:

算法 秘钥长度 秘钥长度默认值 工作模式 填充模式 备注
AES 128,192,256 128 ECB,CBC,PCBC,CTR,CTS,CFB,CFB8至CFB128,OFB,OFB8至OFB128 NoPadding,PKCS5Padding,ISO10126Padding Java6实现若使用256位秘钥需要获得无政策限制权限文件(Unlimited Strength Jurisdiction Policy Files)
AES 同上 同上 同上 PKCS7Padding,ZeroBytePadding Bouncy Castle实现
表二:
AES 秘钥长度(比特) 分组长度(比特) 向量长度(比特) 加密轮数
AES-128 128 128 128 10
AES-192 192 128 128 12
AES-256 256 128 128 14
  • 1
    根据密钥长度不同,分为AES128、AES192、AES256
  • 1.特点
  1. ECB模式和CBC模式的区别
  2. 对称加密算法里,使用NOPadding,加密的明文必须等于分组长度倍数,否则报错
  3. 如果使用PKCS5Padding,会对加密的明文填充1字节-1个分组的长度
  4. 没有指明加密模式和填充方式,表示使用默认的AES/ECB/PKCS5Padding
  5. 加密后的字节数组可以编码成Hex、Base64
  6. AES算法明文按128位进行分组加密,可以调用cipher.getBlockSize()来获取
  7. 要复现一个对称加密算法,需要得到明文、key、iv、mode、padding
  8. 明文、key、iv需要注意解析方式,而且不一定是字符串形式
  9. 如果加密模式是ECB,则不需要加iv,加了的话会报错
  10. 如果明文中有两个分组的内容相同,ECB会得到完全一样的密文,CBC不会
  11. 加密算法的结果通常与明文等长或者更长,如果变短了,那可能是gzip、protobuf
  • 【密码学 09 AES】2.代码实现
    public static String encryptAES(String plaintext) throws Exception { //初始化秘钥 和加密算法秘钥为16位 SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); //得到Cipher的实例026fcbe02f76529d0a5bb3904aa6efdcC5sV2ktEoPUVHc/EwB811b8xuRnjiS3cO1khLWp7EeY= Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 对Cipher 实例进行初始化, des.init(Cipher.ENCRYPT_MODE,keySpec,ivParameterSpec); // update并不会每次都增加要加密的字符串的长度,并不可靠。理想中的状态是xiaojianbang +hengdi 解密发现只有banghengdi //des.update("xiaojianbang".getBytes(StandardCharsets.UTF_8)); // 加密 由字符串 得到的byte[] byte[] res=des.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); Log.d("hengdi","AESbyte test" + Arrays.toString(res)); // 将 byte[] 实例化为 ByteString 对象 ByteString bty=ByteString.of(res); // hex 编码 String str_hex= bty.hex(); // base64 编码 String str_base64 = bty.base64(); return str_hex + "||" + str_base64; }public static String decryptAES(String cipherText) throws Exception { // 将加密后base64编码的字符串 解码,并还原成 byte[] //byte[] cipherTextBytes = ByteString.decodeHex(cipherText).toByteArray(); byte[] cipherTextBytes = ByteString.decodeBase64(cipherText).toByteArray(); SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); //得到Cipher的实例026fcbe02f76529d0a5bb3904aa6efdcAm/L4C92Up0KW7OQSqbv3A== Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); des.init(Cipher.DECRYPT_MODE,keySpec,ivParameterSpec); byte[] res=des.doFinal(cipherTextBytes); return new String(res); }

    推荐阅读