在Java8中使用公私密钥组合进行对称加密
我试图使用非对称私钥和公钥组合来生成用于加密和解密某些文本的对称密钥,但是,我无法使用生成的密钥,因为它的大小为128字节,这对于AES加密是不可接受的。我想只使用JRE(没有外部库)来解决这个问题。你有解决办法吗 我在下面包含了我的示例代码,其中有一条注释指示引发异常的行 (在Java8中使用公私密钥组合进行对称加密,java,encryption,aes,Java,Encryption,Aes,我试图使用非对称私钥和公钥组合来生成用于加密和解密某些文本的对称密钥,但是,我无法使用生成的密钥,因为它的大小为128字节,这对于AES加密是不可接受的。我想只使用JRE(没有外部库)来解决这个问题。你有解决办法吗 我在下面包含了我的示例代码,其中有一条注释指示引发异常的行 (encryptCipher.init(Cipher.ENCRYPT_模式,tomSecretKeySpec,iv);) 我读过KDF散列,但Java似乎没有一种明显的方式在我的128字节密钥上调用它。另外,我不确定这是不是
encryptCipher.init(Cipher.ENCRYPT_模式,tomSecretKeySpec,iv);
)
我读过KDF散列,但Java似乎没有一种明显的方式在我的128字节密钥上调用它。另外,我不确定这是不是正确的答案,因为我的理解是,密钥越长,加密就越安全(对于给定的算法)。也许我需要从使用AES/CBC/PKCS5Padding转换过来,但是JDK作为标准提供的其他算法似乎都不支持128字节的密钥
public void demoSymmetricEncryption() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
String keyAlgorithm = "DiffieHellman";
String keyAgreementAlgorithm = "DiffieHellman";
String keySpecAlgorithm = "AES";
String cipherAlgorithm = "AES/CBC/PKCS5Padding";
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
keyGenerator.initialize(1024, new SecureRandom());
KeyPair tomKeyPair = keyGenerator.generateKeyPair();
PrivateKey tomPrivateKey = tomKeyPair.getPrivate();
PublicKey tomPublicKey = tomKeyPair.getPublic();
KeyPair steveKeyPair = keyGenerator.generateKeyPair();
PrivateKey stevePrivateKey = steveKeyPair.getPrivate();
PublicKey stevePublicKey = steveKeyPair.getPublic();
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("Limited encryption policy files installed : " + (maxKeyLen == 128)); // returns false
KeyAgreement tomKeyAgreement = KeyAgreement.getInstance(keyAgreementAlgorithm);
keyGenerator.initialize(1024, new SecureRandom());
tomKeyAgreement.init(tomPrivateKey);
tomKeyAgreement.doPhase(stevePublicKey, true);
byte[] tomSecret = tomKeyAgreement.generateSecret();
SecretKeySpec tomSecretKeySpec = new SecretKeySpec(tomSecret, keySpecAlgorithm);
KeyAgreement steveKeyAgreement = KeyAgreement.getInstance(keyAgreementAlgorithm);
steveKeyAgreement.init(stevePrivateKey);
steveKeyAgreement.doPhase(tomPublicKey, true);
byte[] steveSecret = steveKeyAgreement.generateSecret();
SecretKeySpec steveSecretKeySpec = new SecretKeySpec(steveSecret, keySpecAlgorithm);
System.out.println("Secret Keys are identical : " + steveSecretKeySpec.equals(tomSecretKeySpec)); // returns true
String initVector = "RandomInitVector";
Cipher encryptCipher = Cipher.getInstance(cipherAlgorithm);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
// fails because AES key is 128 bytes not 128 bits in length - think I need to use KDF hash to shrink it appropriately.
encryptCipher.init(Cipher.ENCRYPT_MODE, tomSecretKeySpec, iv);
// Attempt to use the cipher
byte[] encryptedData = encryptCipher.doFinal("Hello".getBytes());
Cipher decryptCipher = Cipher.getInstance(cipherAlgorithm);
iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
decryptCipher.init(Cipher.DECRYPT_MODE, steveSecretKeySpec, iv);
byte[] decryptedData = decryptCipher.doFinal(encryptedData);
System.out.println("Decrypted Data : " + new String(decryptedData));
}
程序的输出如下所示:
Limited encryption policy files installed : false
Secret Keys are identical : true
Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 128 bytes
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:582)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:339)
at javax.crypto.Cipher.implInit(Cipher.java:806)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at crypto.SymetricEncryptionTest.demoSymmetricEncryption(SymetricEncryptionTest.java:76)
at crypto.SymetricEncryptionTest.main(SymetricEncryptionTest.java:29)
错误为:*无效的AES密钥长度:128字节* 有效的AES密钥大小为128位、192位和256位,或以字节为单位:16字节、24字节和32字节 使用有效的AES密钥大小 生成对称密钥的一般方法只是从加密PRNG中获取字节。有关Java,请参阅 有关密钥派生使用PBKDF2,请参阅和“PBKDF2WithHmacSHA1”(使用基于密码的密钥派生函数构造密钥)。
有关示例,请参见但使用“PBKDF2WithHmacSHA1”作为算法。代码不起作用的原因是我使用了不兼容的算法。更正如下: 更换线路:
String keyAlgorithm = "DiffieHellman";
String keyAgreementAlgorithm = "DiffieHellman";
与
并更换线路
keyGenerator.initialize(1024, new SecureRandom());
与
程序现在生成输出:
Limited encryption policy files installed : false
Secret Keys are identical : true
Decrypted Data : Hello
从技术上讲,您可能还希望对加密输出进行Base64编码,然后在解码之前再次解码,如下所示:
String encryptedData = Base64.encode(encryptCipher.doFinal("Hello".getBytes()));
byte[] decryptedData = decryptCipher.doFinal(Base64.decode(encryptedData));
参见示例1。什么是stacktrace?2.不确定,但我认为我们不能定义那样大小的密钥(它有1024位)你真的需要吗?128位就足够了?请参阅:我已将应用程序输出添加到问题中。我真的不介意密钥大小是多少,但在使用DiffieHellman算法时,您似乎无法将密钥大小限制到足以使其正常工作的程度。当我尝试使用RSA算法时,这不起作用,但原因不同。谢谢你的评论。我将研究这些页面,如果我得到一些工作代码,这些代码将使用我目前正在使用的公钥-私钥组合的散列来工作,我将发回。
Limited encryption policy files installed : false
Secret Keys are identical : true
Decrypted Data : Hello
String encryptedData = Base64.encode(encryptCipher.doFinal("Hello".getBytes()));
byte[] decryptedData = decryptCipher.doFinal(Base64.decode(encryptedData));