问一个 Java 的 RSA 解密的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
linuxchild
V2EX    Java

问一个 Java 的 RSA 解密的问题

  •  
  •   linuxchild Sep 4, 2017 5272 views
    This topic created in 3157 days ago, the information mentioned may be changed or developed.

    在安卓上使用 RSA 算法加密了一个字符串,然后 Base64 了一下;

    在 Mac 上使用 Java 先转码再解密这个加密后转码的字符串,遇到了如下错误:

    javax.crypto.BadPaddingException: Decryption error at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380) at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291) at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363) at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389) at javax.crypto.Cipher.doFinal(Cipher.java:2165) at RSAUtils.decryptData(RSAUtils.java:97) at Decrypt.main(Decrypt.java:62) 

    其中,加密使用的模块如下:

     public static byte[] encryptData(byte[] data, PublicKey ublicKey) { try { Cipher cipher = Cipher.getInstance(RSA); // 编码前设定编码方式及密钥 cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 传入编码数据并返回编码结果 return cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } } 

    解密使用的模块如下:

     public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(RSA); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encryptedData); } catch (Exception e) { e.printStackTrace(); //System.out.println(e.printStackTrace()); return null; } } 

    解密过程使用了 BC 模块来读取 pem 格式( pkcs8 )的私钥文件(加解密过程中均使用了同一模块进行 Base64 操作),调用解密的代码如下:

     KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); PrivateKey privateKey = generatePrivateKey(factory, "private_key.pem"); String encryptCOntent= "xxxxx"; byte[] decryptByte = RSAUtils.decryptData(Base64Utils.decode(encryptContent), privateKey); String decryptStr = new String(decryptByte); System.out.println(decryptStr); 

    已经谷歌了一下,但是没有找到合适的办法,不知哪位有接触过这个,希望不吝赐教,感谢。

    9 replies    2017-09-08 17:00:23 +08:00
    ipeony
        1
    ipeony  
       Sep 4, 2017   1
    试了下这样可以的,看有没有帮助

    <script src="https://gist.github.com/dongfg/cba825a96a416924698b6be02b34c054.js"></script>
    linuxchild
        2
    linuxchild  
    OP
       Sep 6, 2017
    @ipeony 先感谢,回头试一下看看行不行
    linuxchild
        3
    linuxchild  
    OP
       Sep 7, 2017
    @ipeony 仔细看了看代码,加解密模块都一样,只是解密时私钥都读取不一样;

    我使用都是 BC 提供去读取都 pem 格式的私钥,是不是我的读取过程有问题?
    ipeony
        4
    ipeony  
       Sep 7, 2017
    @linuxchild #3 我试了下用 BC 读也是可以的,你的密钥对怎么生成的
    linuxchild
        5
    linuxchild  
    OP
       Sep 7, 2017
    @ipeony 同事给的,相同的密钥和文本使用 Python 直接解出来了…

    帮忙看看使用 bc 去读私钥我贴的那段代码有问题么? pkcs8 格式的私钥
    ipeony /td>
        6
    ipeony  
       Sep 7, 2017
    @linuxchild #5 我没看出问题~感觉跟 BC 那个关系不大,可能是公钥私钥格式上的问题,我理解也不深
    这是我生成密钥对的命令
    ----
    openssl genrsa -out key_private.pem 4096
    openssl rsa -pubout -in key_private.pem -out key_public.pem
    openssl pkcs8 -topk8 -in key_private.pem -inform pem -outform pem -out key_private_pkcs8.pem -nocrypt
    ----
    String privateKeyStr = FileUtils.readFileToString(new File("key_private_pkcs8.pem"), UTF_8);
    String publicKeyStr = FileUtils.readFileToString(new File("key_public.pem"), UTF_8);

    privateKeyStr = privateKeyStr.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
    publicKeyStr = publicKeyStr.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");

    if (Security.getProvider("BC") == null) {
    Security.addProvider(new BouncyCastleProvider());
    }

    KeyFactory kf = KeyFactory.getInstance("RSA","BC");


    PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr));
    PrivateKey privateKey = kf.generatePrivate(keySpecPKCS8);

    X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
    RSAPublicKey publicKey = (RSAPublicKey) kf.generatePublic(keySpecX509);

    System.out.println(publicKey.getFormat());
    System.out.println(privateKey.getFormat());

    String rawString = "aaa";
    byte[] encryptData = encryptData(rawString.getBytes(), publicKey);

    byte[] decryptData = decryptData(encryptData, privateKey);
    Assert.assertNotNull(decryptData);


    String decryptString = new String(decryptData);

    Assert.assertEquals(rawString, decryptString);
    linuxchild
        7
    linuxchild  
    OP
       Sep 8, 2017
    @ipeony

    感谢给这么详细耐心的回复。

    试了一下这段代码,用的自己的私钥和公钥,一串明文进行加解密没问题。

    但是如果用这段代码去解密之前的密文就出现所述的问题了…

    另外,我之前用 Python 试过,同样的密文,同样的密钥,就可以解出来,擦

    我看看再找个人问一下,等解决了告诉你一下。

    再次感谢
    linuxchild
        8
    linuxchild  
    OP
       Sep 8, 2017
    @ipeony

    hello,问题解决了,是将解密的代码改动了一行:

    ```
    public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) {

    try {
    Cipher cipher = Cipher.getInstance(RSA, new org.bouncycastle.jce.provider.BouncyCastleProvider());
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return cipher.doFinal(encryptedData);
    } catch (Exception e) {
    e.printStackTrace();
    //System.out.println(e.printStackTrace());
    return null;
    }
    }
    ```

    前提是把 bc 包引入,我使用动办法是

    > 1. edit jre\lib\security\java.security

    > add security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

    > 2. copy bc*.jar to jre\lib\ext

    摘自:
    https://stackoverflow.com/questions/13721579/jce-cannot-authenticate-the-provider-bc-in-java-swing-application

    然后再进行解密就可以了。


    至于原因,我猜测在加密动时候可能就使用了这个模块。
    ipeony
        9
    ipeony  
       Sep 8, 2017
    @linuxchild #8 学习了
    About     Help     Advertise     Blog     API     FAQ     Solana     4494 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 45ms UTC 10:12 PVG 18:12 LAX 03:12 JFK 06:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86