繁体   English   中英

Java:RSA 加密问题

[英]Java: RSA Encryption issue

关于 RSA 的 Java 代码的小问题。

我有一段非常简单的 Java 代码。


import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class RSA {

    public static void main(String[] args) throws Exception {
        String privateKeyString = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER+iccdhb474gKs6QE9c3JNS3BMlPTyFD2EOP3/NSrBlZtvVpKyQdHxYZ0W6a/IixWc0WjDqqcVAtrwCILmHU7Q==";
        String publicKeyString = "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCyp0Sx3AgDhXYN3ecGaFYt51dnlrbgJJoRnYMh52QmDg=";

        String              secretMessage = "My TOP SECRET Message";

        byte[]              buffer1       = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec1      = new PKCS8EncodedKeySpec(buffer1);
        KeyFactory          keyFactory1   = KeyFactory.getInstance("RSA");
        PrivateKey          privateKey    = (RSAPrivateKey) keyFactory1.generatePrivate(keySpec1);

        byte[]             buffer2     = Base64.getDecoder().decode(publicKeyString);
        KeyFactory         keyFactory2 = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec2      = new PKCS8EncodedKeySpec(buffer2);
        PublicKey          publicKey   = (RSAPublicKey) keyFactory2.generatePublic(keySpec2);

        Cipher encryptCipher = Cipher.getInstance("RSA");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] secretMessageBytes    = secretMessage.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
        String encodedMessage        = Base64.getEncoder().encodeToString(encryptedMessageBytes);

        Cipher decryptCipher = Cipher.getInstance("RSA");
        decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
        String decryptedMessage      = new String(decryptedMessageBytes, StandardCharsets.UTF_8);

        System.out.println("Step 1" + secretMessage);
        System.out.println("Step 2" + encodedMessage);
        System.out.println("Step 3" + decryptedMessage);
    }
    
}

我本以为这会起作用,并且能够看到“第 2 步”的一些乱码

但是相反,我看到了这个:

Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DER input, Integer tag error
    at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:251)
    at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)

请问这段代码有什么问题吗?

谢谢

代码中存在以下问题:

  • 导入私钥和公钥 EC(另外,交换两个密钥)。 由于要执行 RSA 加密,因此要使用 RSA 密钥。
  • 公钥是用PKCS8EncodedKeySpec导入的。 但是, PKCS8EncodedKeySpec用于导入私有 PKCS#8 密钥。 由于要导入公共 X.509/SPKI 密钥,因此必须X509EncodedKeySpec
  • 实例化Cipher object 时,仅指定算法 ( RSA ),而不指定填充。 因此,提供者相关的默认值用于填充。 为避免无意中使用不正确的填充和跨平台问题,还应明确指定填充(例如RSA/ECB/PKCS1Padding )。

固定代码如下:

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class MyClass {
    public static void main(String args[]) throws Exception {
        
        // Fix 1: Use RSA keys: The private RSA key is a 2048 bit DER encoded PKCS#8 key (Base64 encoded). The public RSA key is the associated 2048 bit DER encoded X.509/SPKI key (Base64 encoded). Check the RSA keys with an ASN.1 parser, e.g. https://lapo.it/asn1js/.  
        String privateKeyString = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6cXloNrocJ8swwj8xktPmEOTfTgJT7KkUwWIGOjBB1QxApgdn5+SUHsakvEJq3Fgn+FnuuN8cfcqWrbT9jURtgNGinJNJ+StPM/PCxfhSv+XbkK11CV2EcJMyDB/8S/9u4E2ht/N1kT4OF2/mVDAq2MjjeUMq8CLmQR63ZMXB8lwmsGJEl4Rwt9WBZNcZFCfuCeBYrKRS7mtLzd4BTXEf0UuiNB/KJrz38TKSI47v/dRbB34wBNn0cuNLHb8t/eDaOvzV6J8SZgOWuL85mng6Fm77QGjUteWgJN76+YhDZgJfsRq1Q67JAy3ZXDHi5X538DcM/o+0wYEqkXxK3iIbAgMBAAECggEASlJj0ExIomKmmBhG8q8SM1s2sWG6gdQMjs6MEeluRT/1c2v79cq2Dum5y/+UBl8x8TUKPKSLpCLs+GXkiVKgHXrFlqoN+OYQArG2EUWzuODwczdYPhhupBXwR3oX4g41k/BsYfQfZBVzBFEJdWrIDLyAUFWNlfdGIj2BTiAoySfyqmamvmW8bsvc8coiGlZ28UC85/Xqx9wOzjeGoRkCH7PcTMlc9F7SxSthwX/k1VBXmNOHa+HzGOgO/W3k1LDqJbq2wKjZTW3iVEg2VodjxgBLMm0MueSGoI6IuaZSPMyFEM3gGvC2+cDBI2SL/amhiTUa/VDlTVw/IKbSuar9uQKBgQDd76M0Po5Lqh8ZhQ3obhFqkfO5EBXy7HUL15cw51kVtwF6Gf/J2HNHjwsg9Nb0eJETTS6bbuVd9bn884JoRS986nVTFNZ4dnjEgKjjQ8GjfzdkpbUxsRLWiIxuOQSpIUZGdMi2ctTTtspvMsDsjRRYdYIQCe/SDsdHGT3vcUCybwKBgQDXDz6iVnY84Fh5iDDVrQOR4lYoxCL/ikCDJjC6y1mjR0eVFdBPQ4j1dDSPU9lahBLby0VyagQCDp/kxQOl0z2zBLRI4I8jUtz9/9KW6ze7U7dQJ7OTfumd5I97OyQOG9XZwKUkRgfyb/PAMBSUSLgosi38f+OC3IN3qlvHFzvxFQKBgQCITpUDEmSczih5qQGIvolN1cRF5j5Ey7t7gXbnXz+Umah7kJpMIvdyfMVOAXJABgi8PQwiBLM0ySXo2LpARjXLV8ilNUggBktYDNktc8DrJMgltayaj3HNd2IglD5rjfc2cKWRgOd7/GlKcHaTEnbreYhfR2sWrWLxJOyoMfuVWwKBgFalCbMV6qU0LfEo8aPlBN8ttVDPVNpntP4h0NgxPXgPK8Pg+gA1UWSy4MouGg/hzkdHaj9ifyLlCX598a5JoT4S0x/ZeVHd/LNI8mtjcRzD6cMde7gdFbpLb5NSjIAyrsIAX4hxvpnqiOYRePkVIz0iLGziiaMbfMwlkrxvm/LRAoGBALPRbtSbE2pPgvOHKHTGPr7gKbmsWVbOcQA8rG801T38W/UPe1XtynMEjzzQ29OaVeQwvUN9+DxFXJ6Yvwj6ih4Wdq109i7Oo1fDnMczOQN9DKch2eNAHrNSOMyLDCBm++wbyHAsS2T0VO8+gzLABviZm5AFCQWfke4LZo5mOS10";
        String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunF5aDa6HCfLMMI/MZLT5hDk304CU+ypFMFiBjowQdUMQKYHZ+fklB7GpLxCatxYJ/hZ7rjfHH3Klq20/Y1EbYDRopyTSfkrTzPzwsX4Ur/l25CtdQldhHCTMgwf/Ev/buBNobfzdZE+Dhdv5lQwKtjI43lDKvAi5kEet2TFwfJcJrBiRJeEcLfVgWTXGRQn7gngWKykUu5rS83eAU1xH9FLojQfyia89/EykiOO7/3UWwd+MATZ9HLjSx2/Lf3g2jr81eifEmYDlri/OZp4OhZu+0Bo1LXloCTe+vmIQ2YCX7EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4iGwIDAQAB";

        String              secretMessage = "My TOP SECRET Message";

        byte[]              buffer1       = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec1      = new PKCS8EncodedKeySpec(buffer1);
        KeyFactory          keyFactory1   = KeyFactory.getInstance("RSA");
        PrivateKey          privateKey    = (RSAPrivateKey) keyFactory1.generatePrivate(keySpec1);

        byte[]             buffer2     = Base64.getDecoder().decode(publicKeyString);
        KeyFactory         keyFactory2 = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec2      = new X509EncodedKeySpec(buffer2); // Fix 2: Apply X509EncodedKeySpec for the import of the public key
        PublicKey          publicKey   = (RSAPublicKey) keyFactory2.generatePublic(keySpec2);

        Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // Fix 3: Specify algorithm and padding when instantiating the Cipher object
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] secretMessageBytes    = secretMessage.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
        String encodedMessage        = Base64.getEncoder().encodeToString(encryptedMessageBytes);

        Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // Fix 3: Specify algorithm and padding when instantiating the Cipher object
        decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
        String decryptedMessage      = new String(decryptedMessageBytes, StandardCharsets.UTF_8);

        System.out.println("Step 1" + secretMessage);
        System.out.println("Step 2" + encodedMessage);
        System.out.println("Step 3" + decryptedMessage);
    }
}

通过这些更改,加密和解密工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM