【发布时间】:2015-12-15 21:59:15
【问题描述】:
在解密过程中,我得到了“错误的密钥大小”或“未正确填充的最终块”的混合,这取决于我正在运行的操作系统。
在 Win7 上,使用 IBMJCE 或 SUNJCE(均为 Java8),25% 的时间解密失败:
javax.crypto.BadPaddingException:给定最终块未正确填充 在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811) 在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676) 在 com.sun.crypto.provider.DESedeCipher.engineDoFinal(DESedeCipher.java:294) 在 javax.crypto.Cipher.doFinal(Cipher.java:2087)
在 mac 上,使用 SUNJCE,100% 的时间解密失败:
java.security.InvalidKeyException:错误的密钥大小 在 com.sun.crypto.provider.DESedeCrypt.init(DESedeCrypt.java:69) 在 com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91) 在 com.sun.crypto.provider.CipherCore.init(CipherCore.java:469) 在 com.sun.crypto.provider.DESedeCipher.engineInit(DESedeCipher.java:197) 在 javax.crypto.Cipher.implInit(Cipher.java:791) 在 javax.crypto.Cipher.chooseProvider(Cipher.java:849) 在 javax.crypto.Cipher.init(Cipher.java:1348)
使用DESEde,我认为密钥大小需要为24,我可以看到在windows上,解密后总是24字节,而在mac上,它永远不是24字节。
这里是起点。在 decryptWithSymmetricKey 期间总是抛出异常。请注意,我对大部分代码(特定于 DESede)进行了短周期处理,无法进一步缩小范围(对于安全领域来说非常新)。
public static void runtest() throws Exception {
String symmPad = "DESede/CBC/PKCS5Padding";
String asymmPad = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
String pubKeyFp = "somekey";
String stringToEncrypt = "abcdefg";
KeyGenerator kgen = KeyGenerator.getInstance(DESEDE);
kgen.init(112);
SecretKey secKey = kgen.generateKey();
String encryptedKey = encryptSymmetricKey(secKey, asymmPad);
String encryptedData = encryptDataWithSymmetricKey(stringToEncrypt, secKey, symmPad);
String decryptedKey = decryptWithPrivateKey(encryptedKey, pubKeyFp, asymmPad);
String decryptedData = decryptWithSymmetricKey(encryptedData, decryptedKey, symmPad);
}
这里我们加密对称密钥,两种环境下的密钥长度都是24
private static String encryptSymmetricKey(SecretKey secKey, String asymmPadding) throws Exception {
KeyPair keyPair = getKeyPair("self4");
Cipher cipher = Cipher.getInstance(asymmPadding);
OAEPParameterSpec ospec = new OAEPParameterSpec(SHA256, MGF1, MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic(), ospec);
String secKeyEncoded = new String(secKey.getEncoded());
byte[] encrypted = cipher.doFinal(secKeyEncoded.getBytes());
char[] encoded = Hex.encodeHex(encrypted);
return new String(encoded);
}
这里我们用对称密钥加密我们的字符串
private static String encryptDataWithSymmetricKey(String data, SecretKey secretKey, String symmPadding) throws Exception {
Cipher cipher = Cipher.getInstance(symmPadding);
IvParameterSpec iv = new IvParameterSpec(new byte[8]);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] encrypted = cipher.doFinal(data.getBytes());
char[] encoded = Hex.encodeHex(encrypted);
return new String(encoded);
}
解密和解码对称密钥是我第一次在 mac 上看到可变长度密钥的时候。
public String decryptWithPrivateKey(String encryptedData, String pubKeyFp, String asymmPadding) throws Exception {
loadKeystores();
String alias = fingerPrintAliasMap.get(pubKeyFp);
KeyPair keyPair = getKeyPair(alias);
Cipher cipher = Cipher.getInstance(asymmPadding);
OAEPParameterSpec oParamSpec = new OAEPParameterSpec(SHA256, MGF1, MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate(), oParamSpec);
byte[] decoded = Hex.decodeHex(encryptedData.toCharArray());
byte[] decrypted = cipher.doFinal(decoded);
System.out.println("decoded and decrypted key length: " + decrypted.length); // 24 on windows, random on mac
return new String(Hex.encodeHex(decrypted));
}
故障发生在这里 - 在 Windows 上,25% 的时间在 cipher.doFinal 期间失败,在 Mac 上,100% 的时间在 cipher.init 期间失败。
public String decryptWithSymmetricKey(String encryptedHexData, String symmKey, String symmPadding) throws Exception {
byte[] key = Hex.decodeHex(symmKey.toCharArray());
SecretKey skeySpec = new SecretKeySpec(key, DESEDE);
IvParameterSpec iv = new IvParameterSpec(new byte[8]);
Cipher cipher = Cipher.getInstance(symmPadding);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); // mac: Wrong key size
byte[] decoded = Hex.decodeHex(encryptedHexData.toCharArray());
byte[] deciphered = cipher.doFinal(decoded); // windows: Given final block not properly padded
return new String(deciphered);
}
我假设如果我在 mac 上解决这个问题,它也应该在 windows 上解决它。
【问题讨论】:
标签: java encryption cryptography java-8