0

我需要编写一个 java 代码,使用客户提供的私钥/公钥来加密/解密消息。这是我所做的:

  • 我从客户那里得到了 PKCS#1 格式的私钥(它以 -----BEGIN RSA PRIVATE KEY----- 开头)

  • 我使用以下命令将其转换为 PKCS#8:

    openssl pkcs8 -topk8 -nocrypt -in private_pkcs1.key -out private_pkcs8.key
    
  • 现在我有了 PKCS#8 格式的私钥(以 -----BEGIN PRIVATE KEY----- 开头)

  • 我已经使用以下命令从私钥中提取了公钥(尝试了两种格式,并且我得到了相同的公钥):

    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也会崩溃,这很奇怪。

  • 当我替换了私钥/公钥并改用 KeyPairGenerator 时,一切正常。这使我得出结论,密钥、读取密钥的方式或用于加密/解密的算法有问题。(我尝试过使用“RSA”、“RSA/ECB/PKCS1Padding” - 没有运气)

我在这个问题上花了超过 2 天的时间。我确保我使用相同的公钥/私钥对,我没有尝试将 byte[] 转换为 String。我已经“按部就班”做了一切

对此问题的任何帮助将不胜感激。我可以向客户询问有关钥匙的一些问题,这将帮助我解开这个谜吗?为什么JVM也会崩溃?

谢谢盖伊·胡达拉

4

2 回答 2

0

在非对称密码中,使用公钥加密并使用私钥解密。这样可以确保任何人都可以用众所周知的公钥加密消息,但只有私钥的持有者才能解密它。

byte[] encryptedBytes = encrypt(originalBytes, publicKey);
byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
于 2014-03-14T21:05:02.520 回答
0

我有同样的问题。通过重新生成公钥来解决。

于 2018-01-30T07:09:39.400 回答