如前所述,这是一种用于公共 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 的值 826364754 或 0x31415352 为大端,0x52534131 为小端。后者对应字符串RSA1的ASCII编码。
贴出的key是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 创建公钥。这个类有一个期望指数和模数的构造函数,参见例如here 和 here。
更新:
正如@Maarten Bodewes 的评论中提到的,在将模数和指数创建为BigInteger 时必须考虑以下几点:模数和指数是正值。然而,Java 使用2's complement 来表示整数,因此第一个字节还包含有关符号的信息(即,如果最左边的字节大于0x79,则值为负)。考虑到这一点,如果最左边的字节大于0x79,则可以添加0x00 字节。或者,有相应的构造函数,例如BigInteger(String val, int radix),如果数据以十六进制字符串形式提供(符号在 string 参数中被考虑为可选 +/-),或者BigInteger(int signum, byte[] magnitude),如果数据以字节形式提供数组(int 参数中考虑了符号)。由于在当前情况下,数据可能以十六进制字符串的形式提供,因此以下是合适的(例如,对于模数):
BigInteger modulus = new BigInteger("ba90e01e...5ae90385", 16);