我需要编写一个Java代码,该代码使用客户给出的私有/公钥加密/解密消息。这是我所做的:
-
我从客户那里获得了PKCS#1格式的私钥(它以------开始RSA私有密钥------)
-
我使用以下命令将其转换为PKCS#8:
openssl pkcs8 -topk8 -nocrypt -in private_pkcs1.key -out private_pkcs8.key
-
现在,我有PKCS#8格式中的私钥(以------开始私有键-----)
-
我使用以下命令从私钥中提取了公钥(以两种格式尝试,我得到了相同的公钥):
openssl rsa -in private_pkcs8.key -pubout > public.key
-
我已经写了以下方法来读取私钥private_pkcs8.key文件:
private static PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { File file = new File(filename); FileInputStream in = new FileInputStream(file); byte[] keyBytes = new byte[ new Long(file.length()).intValue() ]; in.read(keyBytes); in.close(); String strPrivateKey = new String(keyBytes, "UTF-8").replaceAll("(-+BEGIN PRIVATE KEY-+\r?\n|-+END PRIVATE KEY-+\r?\n?)", ""); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(DatatypeConverter.parseBase64Binary(strPrivateKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); }
-
我已经写了以下方法来读取public.key文件的公共密钥
private static PublicKey readPublicKey(String filename) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { File file = new File(filename); FileInputStream in = new FileInputStream(file); byte[] keyBytes = new byte[ new Long(file.length()).intValue() ]; in.read(keyBytes); in.close(); String strPublicKey = new String(keyBytes, "UTF-8").replaceAll("(-+BEGIN PUBLIC KEY-+\r?\n|-+END PUBLIC KEY-+\r?\n?)", ""); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(strPublicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); }
-
我写了以下加密方法
private static byte[] encrypt(byte[] message, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidAlgorithmParameterException { Cipher cipher = Cipher.getInstance(ALGORITHEM); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(message); }
-
我写了以下解密方法
private static byte[] decrypt(byte[] message, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidAlgorithmParameterException { Cipher cipher = Cipher.getInstance(ALGORITHEM); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(message); }
-
我编写了以下主测试应用程序,该应用程序试图加密简单的字符串并将其解密。
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, SignatureException, NoSuchProviderException, InvalidAlgorithmParameterException { readKeys(); String messageToEncrypt = "This is the string I want to test"; log("Original Message: " + messageToEncrypt); byte[] originalBytes = messageToEncrypt.getBytes("UTF-8"); byte[] encriptedBytes = encrypt(originalBytes, privateKey); byte[] decriptedMessage = decrypt(encriptedBytes, publicKey); log("Decripted Message: " + new String(decriptedMessage)); }
-
加密还可以,但是当我尝试将其解密到原始消息时,我得到了以下例外:
Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero at sun.security.rsa.RSAPadding.unpadV15(Unknown Source) at sun.security.rsa.RSAPadding.unpad(Unknown Source) at com.sun.crypto.provider.RSACipher.a(DashoA13*..) at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..) at javax.crypto.Cipher.doFinal(DashoA13*..) at com.company.encryption.utils.RsaUtils.decrypt(RsaUtils.java:95) at com.company.encryption.utils.RsaUtils.main(RsaUtils.java:108) ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
请注意,JVM也崩溃了,这很奇怪。
- 当我更换私人/公共钥匙并使用按键器时,一切都可以。这使我得出这样的结论,即钥匙或阅读键的方式或我用来加密/解密的算法有些问题。(我尝试使用" RSA"," RSA/ECB/PKCS1PADDING" - 没有运气)
我在这个问题上花费了2天以上的时间。我确保使用相同的公共/私人键,我没有尝试将字节[]转换为字符串。我已经完成了所有"书"
在此问题上的任何帮助将不胜感激。我能问一下客户有关钥匙的问题,这将帮助我解决这个谜团吗?为什么JVM也崩溃?
谢谢Guy Hudara
在非对称密码中,一个用公钥加密和用私钥加密。这样,它可以确保任何人都可以用通常已知的公共密钥对消息进行加密,但是只有私钥的持有人才能解密它。
byte[] encryptedBytes = encrypt(originalBytes, publicKey);
byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
i存在相同的问题。通过再生公钥解决。