从字符串生成Rsa公钥

戴夫:

这是我的服务器公钥:

UlNBMQAIAAADAAAAAAEAAAAAAAAAAAAAAQABupDgHg710Jh4QwJriIdrY+6yyZme0e0FSQ1EFO3JEmiT+DXRLgU7CcgqGqLhosqYV7Rm1/H0I0ugFBk4zisPbgIb3epyMCcjnTgknRYddtIl9jNS8Z91/1SJ5bY0FkIRFJLHSCEcu1Un09w+gpWRoeAhSc87EMGngUZixAcyoDeYsW0mM1IlH44flo76wXERadmtAd9KFN0nYTjMwkIDyc5B9I2zvSjOQ+p54+6dl6o6nOalCWJg8V137ZMwQCk/4Tmp4C52d0AzYjEeU9gQowkrm7DgjLthd4ew/kY5a/8JfsWMJhajDPgzBV5fFJMbNL1h0fmtG8QpH5OtWukDhQ==

和加密代码:

 byte[] publicBytes = Base64.decode(PUBLIC_KEY, Base64.DEFAULT);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            Cipher cipher = Cipher.getInstance("RSA"); //or try with "RSA"
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            encrypted = cipher.doFinal(txt.getBytes());
            encoded = Base64.encodeToString(encrypted, Base64.DEFAULT);

尝试加密时出现此错误:

java.security.spec.InvalidKeySpecException:java.lang.RuntimeException:错误:0D0680A8:asn1编码例程:ASN1_CHECK_TLEN:错误的标记

这是怎么了?

黄玉:

如前所述,这是公用RSA密钥的专有Microsoft格式BCRYPT_RSAPUBLIC_BLOB

BCRYPT_RSAKEY_BLOB
PublicExponent[cbPublicExp]          // Big-endian.
Modulus[cbModulus]                   // Big-endian.

typedef struct _BCRYPT_RSAKEY_BLOB {
    ULONG Magic;                      // identifies the type, e.g. BCRYPT_RSAPUBLIC_MAGIC for an RSA public key
    ULONG BitLength;                  // size, in bits, of the key
    ULONG cbPublicExp;                // size, in bytes, of the exponent of the key
    ULONG cbModulus;                  // size, in bytes, of the modulus of the key
    ULONG cbPrime1;                   // size, in bytes, of the first prime number of the key. This is only used for private key BLOBs
    ULONG cbPrime2;                   // size, in bytes, of the second prime number of the key. This is only used for private key BLOBs
} BCRYPT_RSAKEY_BLOB;

中的值BCRYPT_RSAKEY_BLOB具有小端格式,指数和模数为大端格式。BCRYPT_RSAPUBLIC_MAGIC具有8263647540x31415352大端和0x52534131小端的值。后者对应于字符串RSA1的ASCII编码

发布的密钥是在Base64解码后以十六进制格式进行的:

525341310008000003000000000100000000000000000000010001ba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

或分为各个部分:

little endian   big endian
52534131        0x31415352 
00080000        0x0800     = 2048 bits
03000000        0x  03     =    3 bytes 
00010000        0x0100     =  256 bytes
00000000    
00000000

big endian
010001
ba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

最后两部分是指数:

0x010001 = 65537

和模数

0xba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

在Java中,可以使用类创建公共密钥RSAPublicKeySpec此类具有一个期望指数和模数的构造函数,请参见此处此处

更新:

如@Maarten Bodewes的评论中所述,创建模数和指数时必须考虑以下内容BigInteger:模数和指数为正值。但是,Java使用2的补码表示整数,因此第一个字节还包含有关符号的信息(即,如果最左边的字节大于0x79,则该值为负)。考虑到这一点,0x00如果最左边的字节大于则可以添加一个字节0x79或者,有相应的构造函数,例如BigInteger(String val, int radix),如果数据以十六进制字符串形式可用(在string-parameter 中将符号考虑为可选的+/ -),或者BigInteger(int signum, byte[] magnitude),如果数据可作为字节数组使用(- int参数中考虑了符号)。由于在当前情况下,数据可能以十六进制字符串形式提供,因此以下内容适用(例如,模数):

BigInteger modulus = new BigInteger("ba90e01e...5ae90385", 16);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章