AES学习小结
来源:互联网 发布:apache json 配置 编辑:程序博客网 时间:2024/05/30 02:53
AES是基于数据块的加密方式,即每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。
jce中实现了三种补码方式:NoPadding,PKCS5Padding,ISO10126Padding;不支持SSL3Padding,不支持“NONE”模式。
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。
算法/模式/填充16字节加密后数据长度不满16字节加密后长度
AES/CBC/NoPadding16不支持
AES/CBC/PKCS5Padding3216
AES/CBC/ISO10126Padding3216
AES/CFB/NoPadding16原始数据长度
AES/CFB/PKCS5Padding3216
AES/CFB/ISO10126Padding3216
AES/ECB/NoPadding16不支持
AES/ECB/PKCS5Padding3216
AES/ECB/ISO10126Padding3216
AES/OFB/NoPadding16原始数据长度
AES/OFB/PKCS5Padding3216
AES/OFB/ISO10126Padding3216
AES/PCBC/NoPadding16不支持
AES/PCBC/PKCS5Padding3216
AES/PCBC/ISO10126Padding3216
AES-128-CBC方式与AES-128方式不同的地方:
AES-128-CBC可以自己定义“密钥”和“偏移量“,AES-128是jdk自动生成的“密钥”,所以AES-128-CBC更灵活。
代码实例:
package com.client;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;/**AES 是一种可逆加密算法,对用户的敏感信息加密处理* 对原始数据进行AES加密后,在进行Base64编码转化;*/public class AesCBC { /* * 加密用的Key 可以用26个字母和数字组成 * 此处使用AES-128-CBC加密模式,key需要为16位。 */ private static String sKey = "sklhdflsjfsdgdeg"; private static String ivParameter = "cfbsdfgsdfxccvd1"; private static AesCBC instance = null; private AesCBC() { } public static AesCBC getInstance() { if (instance == null) { instance = new AesCBC(); } return instance; } // 加密 public String encrypt(String sSrc, String encodingFormat, String sKey, String ivParameter) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] raw = sKey.getBytes(); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); //使用CBC模式,需要一个向量iv,可增加加密算法的强度 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); byte[] encrypted = cipher.doFinal(sSrc.getBytes(encodingFormat)); return new BASE64Encoder().encode(encrypted); //此处使用BASE64做转码。 } // 解密 public String decrypt(String sSrc, String encodingFormat, String sKey, String ivParameter) throws Exception { try { byte[] raw = sKey.getBytes("ASCII"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc); //先用base64解密 byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original, encodingFormat); return originalString; } catch (Exception ex) { return null; } } public static void main(String[] args) throws Exception { // 需要加密的字串 String cSrc = "我来自中国"; System.out.println(cSrc); // 加密 long lStart = System.currentTimeMillis(); String enString = AesCBC.getInstance() .encrypt(cSrc, "utf-8", sKey, ivParameter); System.out.println("加密后的字串是:" + enString); long lUseTime = System.currentTimeMillis() - lStart; System.out.println("加密耗时:" + lUseTime + "毫秒"); // 解密 lStart = System.currentTimeMillis(); String DeString = AesCBC.getInstance() .decrypt(enString, "utf-8", sKey, ivParameter); System.out.println("解密后的字串是:" + DeString); lUseTime = System.currentTimeMillis() - lStart; System.out.println("解密耗时:" + lUseTime + "毫秒"); }}
java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别,PKCS5Padding的blocksize为8字节,而PKCS7Padding的blocksize可以为1到255字节。
要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现。
bcprov-jdk16-146.jar
加密代码如下:
/** * * @author ngh * AES128 算法 * * CBC 模式 * * PKCS7Padding 填充模式 * * CBC模式需要添加一个参数iv * * 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别 * 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现 */public class AES { // 算法名称 final String KEY_ALGORITHM = "AES"; // 加解密算法/模式/填充方式 final String algorithmStr = "AES/CBC/PKCS7Padding"; // private Key key; private Cipher cipher; boolean isInited = false; byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 }; public void init(byte[] keyBytes) { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if ((keyBytes.length % base) != 0) { int groups = (keyBytes.length / base) + (((keyBytes.length % base) != 0) ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length); keyBytes = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); // 转化成JAVA的密钥格式 key = new SecretKeySpec(keyBytes, KEY_ALGORITHM); try { // 初始化cipher cipher = Cipher.getInstance(algorithmStr, "BC"); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 加密方法 * * @param content * 要加密的字符串 * @param keyBytes * 加密密钥 * @return */ public byte[] encrypt(byte[] content, byte[] keyBytes) { byte[] encryptedText = null; init(keyBytes); System.out.println("IV:" + new String(iv)); try { cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); encryptedText = cipher.doFinal(content); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return encryptedText; } /** * 解密方法 * * @param encryptedData * 要解密的字符串 * @param keyBytes * 解密密钥 * @return */ public byte[] decrypt(byte[] encryptedData, byte[] keyBytes) { byte[] encryptedText = null; init(keyBytes); System.out.println("IV:" + new String(iv)); try { cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); encryptedText = cipher.doFinal(encryptedData); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return encryptedText; }}
测试代码如下:
public class Test { public static void main(String[] args) { AES aes = new AES(); // 加解密 密钥 byte[] keybytes = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 }; String content = "1"; // 加密字符串 System.out.println("加密前的:" + content); System.out.println("加密密钥:" + new String(keybytes)); // 加密方法 byte[] enc = aes.encrypt(content.getBytes(), keybytes); System.out.println("加密后的内容:" + new String(Hex.encode(enc))); // 解密方法 byte[] dec = aes.decrypt(enc, keybytes); System.out.println("解密后的内容:" + new String(dec)); }}
阅读全文
0 0
- AES学习小结
- aes算法小结
- AES学习总结
- 学习AES加密类
- Crypto++学习总结---AES
- Crypto++学习总结---AES
- AES算法学习总结
- PHP AES加密学习笔记
- AES加密学习笔记(一)
- PHP AES加密解密学习
- ios 学习登陆密码AES 加密
- ios 学习登陆密码AES 加密
- 学习笔记:openssl , AES, vs2015
- AES
- AES
- AES
- AES
- aes
- CSU
- 解决weka API读取Oracle10g数据库中date型数据出错问题
- STM32启动代码解析
- java线程类Thread中的方法
- Eclipse反编译插件JadClipse安装(用于打开.class文件)
- AES学习小结
- 如何转义emoji表情,让它可以存入utf8的数据库?
- Linux pid tid说明
- zyUpload多图上传插件的使用(基于php jquery)
- python基础学习六:python生成器
- Glide框架高斯模糊图片处理
- RabbitMQ安装和使用(一)
- vue项目遇到的坑(vue项目中的某个组件调用外部js)
- echo $PATH