1. java 实现
蕴含了三种生成加密 key 的形式
public static String encryptDESede(String plaintext) throws Exception {
// 初始化秘钥 和加密算法 秘钥必须大于 8 位
// ------------------------ 1 应用 DESedeKeySpec 来生成 ------------------------------
DESedeKeySpec desedekey = new DESedeKeySpec("123456781234567812345678".getBytes(StandardCharsets.UTF_8));
SecretKeyFactory key = SecretKeyFactory.getInstance("DESede");
SecretKey keySpec = key.generateSecret(desedekey);
// -----------------------2 间接应用字节 来生成 key ---------------------------------
// byte[] keySpec_bytes= new byte[]{1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8};
// SecretKeySpec keySpec = new SecretKeySpec(keySpec_bytes,"DESede");
// ------------------------3 应用 字符串转 byte 数组 来生成 -----------------------------
// SecretKeySpec keySpec = new SecretKeySpec("123456781234567812345678".getBytes(StandardCharsets.UTF_8),"DESede");
IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes(StandardCharsets.UTF_8));
// 失去 Cipher 的实例 026fcbe02f76529d0a5bb3904aa6efdc Am/L4C92Up0KW7OQSqbv3A==
Cipher desede = Cipher.getInstance("DESede/CBC/PKCS5Padding");
// 对 Cipher 实例进行初始化,desede.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
// update 并不会每次都减少要加密的字符串的长度,并不牢靠。现实中的状态是 xiaojianbang +hengdi 解密发现只有 banghengdi
// des.update("xiaojianbang".getBytes(StandardCharsets.UTF_8));
// 加密 由字符串 失去的 byte[]
byte[] res = desede.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
Log.d("hengdi", "DESede byte test" + Arrays.toString(res));
// 将 byte[] 实例化为 ByteString 对象 byte test
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 decryptDESede(String cipherText) throws Exception {// 将加密后 base64 编码的字符串 解码,并还原成 byte[]
byte[] cipherTextBytes = ByteString.decodeBase64(cipherText).toByteArray();
SecretKeySpec keySpec = new SecretKeySpec("123456781234567812345678".getBytes(StandardCharsets.UTF_8), "DES");
IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes(StandardCharsets.UTF_8));
Cipher desede = Cipher.getInstance("DESede/CBC/PKCS5Padding");
// des.init(Cipher.DECRYPT_MODE, keySpec);
desede.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
byte[] res = desede.doFinal(cipherTextBytes);
Log.d("hengdi", "DESede decryptDESede byte test" + Arrays.toString(res));
return new String(res);
}
2. 特点:
算法 | 秘钥长度 | 秘钥长度默认值 | 工作模式 | 填充模式 | 备注 |
---|---|---|---|---|---|
DESede(TripleDES,3DES) | 112,168 | 168 | ECB,CBC,PCBC,CTR,CTS,CFB,CFB8 至 CFB128,OFB,OFB8 至 OFB128 | NOPadding,PKCS5Padding,ISO10126Padding | JAVA6 实现 |
DESede(TripleDES,3DES) | 128,192 | 同上 | 同上 | PKCS7Padding,ISO10126d2Padding,X932Padding,ISO7816d4Padding,ZeroBytePadding | Bouncy Castle |
- ECB 模式和 CBC 模式的区别
- 对称加密算法里,应用 NOPadding,加密的明文必须等于分组长度倍数,否则报错
- 如果应用 PKCS5Padding,会对加密的明文填充 1 字节 - 1 个分组的长度
- 没有指明加密模式和填充形式,示意应用默认的 DESede/ECB/PKCS5Padding
- 加密后的字节数组能够编码成 Hex、Base64
- DESede 算法明文按 64 位进行分组加密,能够调用 cipher.getBlockSize() 来获取
- 要复现一个对称加密算法,须要失去明文、key、iv、mode、padding
- 明文、key、iv 须要留神解析形式,而且不肯定是字符串模式
- 如果加密模式是 ECB,则不须要加 iv,加了的话会报错
- 如果明文中有两个分组的内容雷同,ECB 会失去齐全一样的密文,CBC 不会
- 加密算法的后果通常与明文等长或者更长,如果变短了,那可能是 gzip、protobuf