具有 2 个不同密钥的 Java 三重 DES 加密
Posted
技术标签:
【中文标题】具有 2 个不同密钥的 Java 三重 DES 加密【英文标题】:Java Triple DES encryption with 2 different keys 【发布时间】:2013-10-26 18:31:34 【问题描述】:我正在尝试使用具有两个不同密钥的三重 DES 加密数据,因此给定两个密钥 k1 和 k2,密文将是 Ek1(Dk2(Ek1(plaintext))),其中 E 是加密,D 是解密。我正在尝试使用 java 中的 DES 算法来模拟这一点。代码如下:
public static void main(String[] args)
SecretKey k1 = generateDESkey();
SecretKey k2 = generateDESkey();
String firstEncryption = desEncryption("plaintext", k1);
String decryption = desDecryption(firstEncryption, k2);
String secondEncryption = desEncryption(decryption, k1);
public static SecretKey generateDESkey()
KeyGenerator keyGen = null;
try
keyGen = KeyGenerator.getInstance("DES");
catch (NoSuchAlgorithmException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
keyGen.init(56); // key length 56
SecretKey secretKey = keyGen.generateKey();
return secretKey;
public static String desEncryption(String strToEncrypt, SecretKey desKey)
try
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, desKey);
String encryptedString = Base64.encode(cipher.doFinal(strToEncrypt.getBytes()));
return encryptedString;
catch (NoSuchAlgorithmException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (NoSuchPaddingException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (IllegalBlockSizeException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (BadPaddingException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (InvalidKeyException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
return null;
public static String desDecryption(String strToDecrypt, SecretKey desKey)
try
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, desKey);
String decryptedString = new String(cipher.doFinal(Base64.decode(strToDecrypt)));
return decryptedString;
catch (NoSuchAlgorithmException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (NoSuchPaddingException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (InvalidKeyException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (IllegalBlockSizeException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (BadPaddingException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
catch (Base64DecodingException ex)
Logger.getLogger(Test.class
.getName()).log(Level.SEVERE, null, ex);
return null;
我有这个错误:javax.crypto.BadPaddingException:在这行代码尝试解密时,给定的最终块没有正确填充:
String decryptedString = new String(cipher.doFinal(Base64.decode(strToDecrypt)));
你能帮我解决这个问题吗?或者你知道使用三重 DES 加密数据的直接方法吗?两个不同的密钥总长度为 128 位?我没有找到任何算法,所以我尝试使用简单的 DES 来模拟它。
【问题讨论】:
【参考方案1】:您正在将任意字节转换为字符串,这会破坏它们。完全使用字节。如果需要将加密后的数据转成String,则使用Base64编码。
【讨论】:
但当前代码中不要使用 base64。使用字节。仅在最后使用 base64。 @andrewcooke 我也有同样的问题,我不想用DESede
,我的项目是用DES
实现TripleDES
,你有什么想法关于如何在不使用DESede
的情况下解决此问题?【参考方案2】:
为什么不直接使用包含的 DESede 算法?
将您的所有 DES 代码实例更改为 DESede,并将您的密钥生成方法更改为:
public static SecretKey generateDESkey()
KeyGenerator keyGen = null;
try
keyGen = KeyGenerator.getInstance("DESede");
catch (NoSuchAlgorithmException ex)
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
keyGen.init(112); // key length 112 for two keys, 168 for three keys
SecretKey secretKey = keyGen.generateKey();
return secretKey;
注意 getInstance() 方法现在是如何随 DESede 提供的,并且密钥大小已增加到 112(三个密钥为 168)。
从以下位置更改您的密码实例:
Cipher.getInstance("DES/ECB/PKCS5Padding");
到
Cipher.getInstance("DESede/ECB/PKCS5Padding");
你已经准备好了。
【讨论】:
【参考方案3】:只是想指出,具有 112 位密钥的 DES 实际上是双 DES,而不是具有 168 位密钥 (3*56) 的三重 DES。由于meet-in-the-middle attack (MITM)https://en.wikipedia.org/wiki/Meet-in-the-middle_attack
总的来说,单 DES(56 位)、双 DES(112 位)和三重 DES(168 位)不应再使用,因为它们不提供 128 位的安全性。
【讨论】:
以上是关于具有 2 个不同密钥的 Java 三重 DES 加密的主要内容,如果未能解决你的问题,请参考以下文章