本文字数为 7223 字, 预计读完大约需要 21 分钟
对称加密算法
[TOC]
java对称加密算法:
-
初等的加密算法
- 常用的对称算法:
- DES
- 3DES(3重DES)
- AES(为替代DES算法)
- PBE
- IDEA
对称加密算法:DES
(Data Encryption Standard)数据加密标准 实际上DES已经不具备安全性
密钥长度 | 默认 | 工作模式 | 填充方式 | 实现方 |
---|---|---|---|---|
56 | 56 | ECB、CBC、PCBC NoPadding、CTR、CTS、CFB、 CFB8、到128、OFB、OFB8、到128 | PKCS5Padding,ISO10126Padding | JDK |
64 | 56 | 同上 | PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding | BC |
不同的工作模式和填充方式决定了破解的难度
对称加密算法使用场景
发送者–构建密钥–公布密钥–使用密钥对数据进行加密–发送加密数据–根据密钥对数据进行解密
例子:
要进行加密的字符串
private static final String src = "I'm Learing DES";
jdk
/**
* jdk实现DES加密
*/
public static void jdkDES() {
try {
//生成密钥
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");//获取DES的密钥
keyGenerator.init(56);//设定keySize
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
DESKeySpec desKeySpec = new DESKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//设置工作方式和填充方式
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[] jdkDESBytes = cipher.doFinal(src.getBytes());
System.out.println("jdkEncodeDESStr:" + Hex.encodeHexString(jdkDESBytes));
//解密操作
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
byte[] decodeJdkDESBytes = cipher.doFinal(jdkDESBytes);
System.out.println("jdkDecodeDESStr:" + new String(decodeJdkDESBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
BC
/**
* 两种方式:
* 1、通过添加Provider
* 2、通过调用BC的API
*/
public static void bcDES() {
Security.addProvider(new BouncyCastleProvider());//添加Provider
try {
//生成密钥
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");//获取DES的密钥,指定使用BC的
keyGenerator.init(56);//设定keySize
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
DESKeySpec desKeySpec = new DESKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key factory.generateSecret(desKeySpec);
//加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//设置工作方式和填充方式
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
byte[] bcDESBytes = cipher.doFinal(src.getBytes());
System.out.println("bcEncodeDESStr:" + Hex.encodeHexString(bcDESBytes));
//揭秘操作
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
byte[] decodeBcDESBytes = cipher.doFinal(bcDESBytes);
System.out.println("bcDecodeDESStr:" + new String(decodeBcDESBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
对称加密算法–3重DES
- 应用比较广泛
- DES算法被很多密码机构质疑
- 1、违反科科霍夫原则
- 2、安全问题
- 好处:
- 1、密钥长度增强
- 2、迭代次数提高
|密钥长度 |默认 |工作模式 |填充方式 |实现方 | |———-|—–|———|———-|——–| |112、168| 56 |ECB、CBC、PCBC、CTR、CTS、CFB、CFB8、到128、OFB、OFB8、到128| NoPadding、PKCS5Padding、ISO10126Padding|JDK| |168、192|56 |同上|PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding |BC|
例子:
jdk
/**
* jdk实现3DES加密解密
*/
public static void jdk3DES() {
try {
// 生成密钥
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");// 获取DES的密钥
keyGenerator.init(168);// 设定keySize
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = factory.generateSecret(desKeySpec);
// 加密
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");// 设置工作方式和填充方式
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);// 加密模式
byte[] jdkDESBytes = cipher.doFinal(src.getBytes());
System.out.println("jdkEncode3DESStr:" + Hex.encodeHexString(jdkDESBytes));
// 揭秘操作
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);// 解密模式
byte[] decodeJdkDESBytes = cipher.doFinal(jdkDESBytes);
System.out.println("jdkDecode3DESStr:" + new String(decodeJdkDESBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
事实上和DES加密的方式是一样的,只不过在上面所有使用DES的地方都是用DESede替换了
bc
通过上面DES使用BounceCstle实现可以看出其实就是给jdk动态添加了bc的实现,3DES的实现和上面的类似。这里也就不写了
对称加密算法–AES
- DES算法的替代者
- AES是目前使用最多的对称加密算法
- 是至今尚未被破解
- 通常用于移动通信系统加密以及基于SSH协议的软件
- SSH Client 、 secureCRT(会使用到)
密钥长度 | 默认 | 工作模式 | 填充方式 | 实现方 |
---|---|---|---|---|
128、192、256 | 128 | ECB、CBC、PCBC、CTR、CTS、CFB、CFB8、到128、OFB、OFB8、到128 | NoPadding、ISO10126Padding | JDK(256位密钥需要获得无政策限制权限文件) |
同上 | 128 | 同上 | PKCS7Padding、ZeroBytePadding | BC |
无政策限制权限文件是指:因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制
使用方式:
发送者 – 构建密钥 – 公布密钥 – 使用密钥对数据进行加密 – 发送加密数据 – 接收者 – 使用密钥对数据进行解析
例子
jdk
public static void jdkAES() {
try {
//生成Key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);//设置keySize
// keyGenerator.init(new SecureRandom());//生成默认的长度
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();//生成Key的内容,这里就要求进行加密和解密的keyBytes内容一定要一致,否则就解密不了
//Key的转换
Key key = new SecretKeySpec(keyBytes, "AES");
//加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//设置加解密模式(加解密模式,工作模式,填充方式)
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] jdkAESBytes = cipher.doFinal(src.getBytes());//得到加密后的结果
System.out.println("jdkEncodeAESStr:" + Hex.encodeHexString(jdkAESBytes));
//进行解密
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] jdkDecodeAESBytes = cipher.doFinal(jdkAESBytes);
System.out.println("jdkDecodeAESStr:" + new String(jdkDecodeAESBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
PBE算法(基于口令的加密)
- 综合了消息摘要算法和对称加密算法的优点
- 对已有算法的包装
- 实现方:jdk,bc
-
盐(口令)
算法 密钥长度 默认 工作模式 填充方式 实现 PBEWithMD5AndDES 64 64 CBC PKCS5Padding、PKCS7Padding、ISO10126Padding、ZeroBytePadding BC PBEWithMD5AndRC2 112 112 CBC 同上 BC PBEWithSHA1AndDES 64 64 CBC 同上 BC PBEWithSHA1AndRC2 128 128 CBC 同上 BC PBEWithSHAAndIDEA-CBC 128 128 CBC 同上 BC PBEWithSHAAnd2-KeyTripleDES-CBC 128 128 CBC 同上 BC PBEWithSHAAnd3-KeyTripleDES-CBC 192 192 CBC 同上 BC
PBE加密算法应用:
发送者 -- 构建口令 -- 公布口令 -- 构建盐 -- 使用口令和盐对数据进行加密 -- 发送盐、加密数据 -- 使用口令、盐对数据进行解密
例子:
jdk
public static void jdkPBE() {
try {
// 初始化盐
SecureRandom random = new SecureRandom();
byte[] salt = random.generateSeed(8);
// 口令与密钥
String password = "imooc";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
Key key = factory.generateSecret(pbeKeySpec);
//加密
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);//需要迭代的次数
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
byte[] jdkPBEBytes = cipher.doFinal(src.getBytes());
System.out.println("jdkEncodePBEStr" + Hex.encodeHexString(jdkPBEBytes));
//解密
cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
byte[] jdkDecodePBEBytes = cipher.doFinal(jdkPBEBytes);
System.out.println("jdkDecodePBEStr:" + new String(jdkDecodePBEBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
另:
其实上面的那么多例子我们可以看到生成Key的方式都是这样
KeyGenerator keyGenerator = KeyGenerator.getInstance("***");// 获取DES的密钥
keyGenerator.init(***);// 设定keySize
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("***");
Key convertSecretKey = factory.generateSecret(desKeySpec);
在这些例子里面我们的加密和解密都是在同一个方法里面进行的 使用的都是上面生成的同一个key 而生成key的byte数组是由数组动态生成的 因此如果涉及到在不同位置进行加解密的话 就得考虑我应该如何让加解密的key保持一致 是通过网络传输将key和加密好的内容一起传输呢(这样同样存在被破解的风险) 还是双方约定好一个密钥进行加解密呢? 这就需要我们自己考虑了 而上面定义的key都是用程序自动生成的,我们应该怎么来自定义key呢? ** 其实Key的生成主要依赖上面生成的byte数组,我们只要获取一个byte数组就可以了(但要注意不同算法对byte数组的要求**) 例如我们知道md5对字符摘要后可以得到一个byte数组,因此我们可以这样来自定义key
String miyao = "我是密钥";
byte[] miyaoBytes = DigestUtils.md5(miyao.getBytes());
Key key = new SecretKeySpec(miyaoBytes, "AES");
...加密...解密
对称加密算法小结:
- DES
- 3DES
- AES
- PBE
- 加密和解密不再同一方: 将密钥发送给另一方 或者两方协议密钥
本文由 MengFly 创作,采用
知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:2016-11-25 00:00:00
相关文章推荐: