我使用 pycrypto 在 python 中生成了一个密钥对
key=RSA.generate(bit_size,os.urandom)
exportedPrivateKey = key.exportKey('PEM', None, pkcs=1).decode("utf-8")
exportedPublicKey = key.publickey().exportKey('PEM', None, pkcs=1).decode("utf-8")
我写了一个小实用程序,它获取消息的散列并签署散列......
hash = MD5.new(json_info.encode("utf-8")).digest()
privateKey = RSA.importKey(USER_TOKEN_PRIVATE_KEY)
signature = privateKey.sign(hash,'')
然后我写了一些东西,使用公钥来验证它是否验证正常......我的令牌中的签名工作正常......
hash = MD5.new(packet.encode("utf-8")).digest()
publicKey = RSA.importKey(tokenPublicKey)
if publicKey.verify(hash, signature):
return json.loads(packet)
else:
return None
现在,因为我需要在 Java 和 python 中使用它,我正在将一个类似的库移植到 java,但我开始遇到问题。也就是说,我的验证总是会失败......
我首先从导出的 PEM 创建 PublicKey 对象...
byte[] encoded = Base64.decodeBase64(USER_TOKEN_PUBLIC_KEY);
//decode the encoded RSA public key
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = kf.generatePublic(keySpec);
我能够获得签名,它是完全相同的签名,并且值哈希到完全相同的值(嗯,类似;java 将字节表示为有符号整数,而 python 将它们表示为无符号,但它们是相同的二进制表示)。但它似乎总是无法验证我的签名..这是我用来做的:
byte[] hash = hasher.digest(packet.getBytes("UTF-8"));
InputStream hashStream = new ByteArrayInputStream(hash);
final Signature sign = Signature.getInstance("MD5withRSA");
sign.initVerify(pubKey);
byte[] buffer = new byte[256];
int length;
while ((length = hashStream.read (buffer)) != -1)
sign.update (buffer, 0, length);
hashStream.close();
System.out.println(sign.verify(signature.getBytes("UTF-8")));
不幸的是,这只会打印错误。
我真正能看到的唯一区别是,当我在 Java 中通过它进行验证时,它要求一个 long 数组,而在 python 中它需要一个字节序列。我最好的猜测是获取那个 long 的字符串表示并将其转换为一堆字节,但是失败了。我所有的其他尝试也都失败了(查看底层大整数的字节表示,查看数组的字节表示等)。我觉得我错过了一些非常简单的东西,但对于我的生活,我无法弄清楚它是什么......
对于签名的外观示例,在 python 中,我给出了:
[68830459489863257411523011520104203035626147084548742757940226446079486348431212041096334237130703774949375015187747280487790006116898192460644067270457728626039524097117092304115366780581423597886886987279231850120937691165013216970647150989646220735762034864029622135210042186666476516651349805320771941650]