三重DES解密无效密钥,16字节

我有一个Android项目,我从我的Web服务获得一个Triple DES加密文本。 我需要Triple DES解密。

但是,我收到无效的密钥exception。 我的密钥转换为HEX格式,我收到一个错误: W/System.err﹕ java.security.InvalidKeyException: DES key too long - should be 8 bytes我在这里找到一个论坛解释说hex可能会导致问题

“DES密钥是56位,通常以8个字节打包,所以他们给你的16个字节/字符很可能是密钥的hex编码字节。你可以得到一个hex解码器”

所以我使用了将hex字符串转换为字节数组

  private static byte[] hexStringtoByteArray(String hex){ int len = hex.length(); byte [] data = new byte[len/2]; for(int i=0; i<len;i+=2){ data[i/2] = (byte)((Character.digit(hex.charAt(i), 16)<<4) + Character.digit(hex.charAt(i+1),16)); } return data; } 

并将其传递给密码,我收到一个错误:

 W/System.err﹕ java.security.InvalidKeyException W/System.err﹕ at javax.crypto.spec.DESedeKeySpec. 

这是我的解密方法。 如果有人可以对我可能出错的地方有所了解,我将不胜感激。

  public String DesDecryptPin(String pin, String encryptKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { String UNICODE_FORMAT = "UTF8"; String decryptedPinText = null; byte[] hexConvert = hexStringtoByteArray(encryptKey); SecretKey desKey = null; KeySpec desKeySpec = new DESedeKeySpec(hexConvert); // Exception HERE Cipher desCipher; SecretKeyFactory skf = SecretKeyFactory.getInstance("DESede"); desCipher = Cipher.getInstance("DES/ECB/NoPadding"); try { desKey = skf.generateSecret(desKeySpec); } catch (InvalidKeySpecException e) { e.printStackTrace(); } desCipher.init(Cipher.DECRYPT_MODE, desKey); byte[] decryptPin = desCipher.doFinal(pin.getBytes()); decryptedPinText = new String(decryptPin, "UTF-8"); return decryptedPinText; } 

我的关键是C9AF269DF8A78A06D1216BFFF8F0536A。

我已经检查过客户端并且密钥是正确的,因此使用相同的密钥进行加密。

加密代码

  public string TripleDESEncrypt(string strClearText, string strKey) { byte[] bytClearText; byte[] bytClearTextChunk = new byte[8]; byte[] bytEncryptedChunk = new byte[8]; int BytesCount = 0; int nArrayPosition = 0; string strEncryptedChar; string strEncryptedText = ""; ArrayList Input = new ArrayList(); ArrayList Output = new ArrayList(); TripleDESCryptoServiceProvider tdes = (TripleDESCryptoServiceProvider)TripleDESCryptoServiceProvider.Create(); tdes.Key = HexToByteArray(strKey); tdes.Mode = CipherMode.ECB; ICryptoTransform tdesEncrypt = tdes.CreateEncryptor(); bytClearText = ASCIIEncoding.ASCII.GetBytes(strClearText); BytesCount = bytClearText.Length; for (int i = 0; i < BytesCount; i++) { if (nArrayPosition == 8) { Input.Add(bytClearTextChunk); bytClearTextChunk = new byte[8]; nArrayPosition = 0; } bytClearTextChunk[nArrayPosition] = bytClearText[i]; nArrayPosition++; } if (nArrayPosition != 0) Input.Add(bytClearTextChunk); foreach (byte[] Cbyte in Input) { tdesEncrypt.TransformBlock(Cbyte, 0, 8, bytEncryptedChunk, 0); Output.Add(bytEncryptedChunk); bytEncryptedChunk = null; bytEncryptedChunk = new byte[8]; } foreach (byte[] Cbyte in Output) { foreach (byte BByte in Cbyte) { strEncryptedChar = BByte.ToString("X"); strEncryptedChar = strEncryptedChar.PadLeft(2, Convert.ToChar("0")); strEncryptedText += strEncryptedChar; } } return strEncryptedText; } 

以下是具有14个字符的解密文本的示例:12345678901234

DES会期望一个8字节的密钥(带有奇偶校验)。 所以Triple DES需要24字节密钥(带奇偶校验)。 由于您只有一个16字节的密钥,因此必须复制其中一些密钥才能获得最终密钥。 通常,第一个和最后8个字节是相同的。 您可以尝试两种变体:

 byte[] tdesKey = new byte[24]; System.arraycopy(hexConvert, 0, tdesKey, 0, 16); System.arraycopy(hexConvert, 0, tdesKey, 16, 8); // tdesKey := K1 || K2 || K1 

要么

 byte[] tdesKey = new byte[24]; System.arraycopy(hexConvert, 8, tdesKey, 0, 8); System.arraycopy(hexConvert, 0, tdesKey, 8, 16); // tdesKey := K2 || K1 || K2 

什么时候

 hexConvert := K1 || K2 

也许你必须使用这个密码:

 public byte[] encTripleDes (String txt, byte [] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidKeySpecException{ DESedeKeySpec keySpec = new DESedeKeySpec(key); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede"); SecretKey ky = keyfactory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, ky); return cipher.doFinal(txt.getBytes("UTF-8")); } 

并解密:

 public byte[] uncTripleDes (byte [] encryptedTextBytes, byte [] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidKeySpecException{ DESedeKeySpec keySpec = new DESedeKeySpec(key); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede"); SecretKey ky = keyfactory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, ky); return cipher.doFinal(encryptedTextBytes); } 

看看我在密码的实例中使用了“PKCS5Padding”。

请注意,填充用于在所有块中给出相同的大小(例如,如果最后一个块是788而不是1024)。

为了创建密钥,在我的解决方案中(它不是唯一的),我计算一个sha-256哈希,然后我得到Des键的必要字节:

计算哈希值:

 public byte[] sumCalc (){ String key = "anyKey"; byte[] hashedKey = null; try { byte [] byteKey = key.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("SHA-256"); hashedKey = md.digest(byteKey); }catch (Exception ex){ System.err.println("Error generant clau" + ex); } return hashedKey; } 

最后只得到Des键所需的128个字节:

 bytedKey = Arrays.copyOf(bytedKey, 16 ); // 16 use only first 128 bit. if 32 use only 256 

这是我的解决方案,但不是唯一的解决方案!

您将Cipher实例化为(singel)DES密码:

 desCipher = Cipher.getInstance("DES/ECB/NoPadding"); 

但是你的密钥是一个16字节的 3Des密钥,你可以得到错误

 DES key too long - should be 8 bytes 

尝试将您的密码实例化为3DES密码:

 desCipher = Cipher.getInstance("DESede/ECB/NoPadding");