M2Crypto 和 java.security return 不同的签名消息
M2Crypto and java.security return different signed messages
我在将项目的一些 Java 代码移植到 Python 时遇到困难。
以下 Java 代码用于对发布到服务器进行验证的伪随机随机数进行签名:
private static final String NONCE_SIGNATURE_ALGORITHM = "SHA512withRSA";
@JsonProperty
private String encodedData;
@JsonProperty
private String encodedSignedData;
@SuppressWarnings("unused")
private cacertnonceverification() {
}
public cacertnonceverification(byte[] decodedData, PrivateKey privateKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
byte[] decodedSignedData = sign(privateKey, decodedData);
encodedData = Base64.getEncoder().encodeToString(decodedData);
encodedSignedData = Base64.getEncoder().encodeToString(decodedSignedData);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("CACertNonceVerificationData{");
sb.append("encodedData='").append(encodedData).append('\'');
sb.append(", encodedSignedData='").append(encodedSignedData).append('\'');
sb.append('}');
return sb.toString();
}
private byte[] sign(PrivateKey privateKey, byte[] dataBytes)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sig = Signature.getInstance(NONCE_SIGNATURE_ALGORITHM);
sig.initSign(privateKey);
sig.update(dataBytes);
return sig.sign();
}
这按预期工作,但以下 Python 代码 return 是用相同私钥签名的相同随机数的不同值。我已经使用 PyCrypto 和 M2Crypto 进行了测试 - return 在签署随机数时具有相同的值,但它们不同于 Java return 值。
def sign_nonce(nonce, privKey):
key=EVP.load_key(privKey)
key.reset_context(md='sha512')
key.sign_init()
key.sign_update(nonce.encode('utf-8'))
return binascii.b2a_hex(key.sign_final()).decode("utf-8")
def sign_string(message, privKey):
f = open(privKey, 'r')
keyString = f.read()
keyString = keyString.encode('utf-8')
key = rsa.PrivateKey.load_pkcs1(keyString)
return binascii.b2a_hex(rsa.sign(message.encode(), key, 'SHA-512')).decode('utf-8')
知道是什么造成了这种差异,我遗漏了什么吗?
谢谢!
编辑:
我的 Python 脚本确实验证了签名的随机数是否有效,并且我对 Python 和 Java 代码使用相同的 public 和私钥,但显然得到有符号值的不同结果。这对我来说意味着 java.security 和 M2Crypto/RSA 使用的签名算法是不同的,但我可能离题太远了——我是加密新手。
编辑2:
我尝试使用 M2Crypto.RSA 对 nonce 进行签名,得到的响应仍然不同,但修改了代码,现在 M2Crypto EVP 和 RSA,以及 rsa 正在输出相同的签名值。仍然没有运气让他们匹配 Java:
的预期值
Expected value: 6d90537599b912ac0de9f68dc0d104a04c5aa74e35262f73872bb01ed1e2cc37100ff1a00735da307fa325f3e30f3c81157755fc60c7ee69bd91bf44b6a5f5e4161bdd67cf982550d992a0a16d12ed5ea30b878a8b2f8eee61cf64e083d7b74a635dabba44bf0b51b9b305aa901b3d090712ee3994057b076d53366a3a387de0f7b2e220cf11239facfce0df6d9a54dfb365f7d3996ea20b55ec75e3661cf95392eda75696cfc6bebda304a2671428dad38a43d5a579550595fe9180539b2b7eb3d568a1f8ce05ded2ae3241a732fffd1404f989eea3e68dda6cd13bfcd6b2e47e64685763a6c3c0f1c47f84c908e22e718254b9f46a7a1de7e2280ccb59c1c5
M2Crypto RSA: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
M2Crypto EVP: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
rsa: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
我能够通过同时使用 EVP 和 RSA 模块来签署我的随机数来解决问题:
key = RSA.load_key(privKey)
md = EVP.MessageDigest('sha512')
md.update(message)
digest=md.final()
signature = key.sign(digest, "sha512")
return b64encode(signature).decode('utf-8')
我在将项目的一些 Java 代码移植到 Python 时遇到困难。
以下 Java 代码用于对发布到服务器进行验证的伪随机随机数进行签名:
private static final String NONCE_SIGNATURE_ALGORITHM = "SHA512withRSA";
@JsonProperty
private String encodedData;
@JsonProperty
private String encodedSignedData;
@SuppressWarnings("unused")
private cacertnonceverification() {
}
public cacertnonceverification(byte[] decodedData, PrivateKey privateKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
byte[] decodedSignedData = sign(privateKey, decodedData);
encodedData = Base64.getEncoder().encodeToString(decodedData);
encodedSignedData = Base64.getEncoder().encodeToString(decodedSignedData);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("CACertNonceVerificationData{");
sb.append("encodedData='").append(encodedData).append('\'');
sb.append(", encodedSignedData='").append(encodedSignedData).append('\'');
sb.append('}');
return sb.toString();
}
private byte[] sign(PrivateKey privateKey, byte[] dataBytes)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature sig = Signature.getInstance(NONCE_SIGNATURE_ALGORITHM);
sig.initSign(privateKey);
sig.update(dataBytes);
return sig.sign();
}
这按预期工作,但以下 Python 代码 return 是用相同私钥签名的相同随机数的不同值。我已经使用 PyCrypto 和 M2Crypto 进行了测试 - return 在签署随机数时具有相同的值,但它们不同于 Java return 值。
def sign_nonce(nonce, privKey):
key=EVP.load_key(privKey)
key.reset_context(md='sha512')
key.sign_init()
key.sign_update(nonce.encode('utf-8'))
return binascii.b2a_hex(key.sign_final()).decode("utf-8")
def sign_string(message, privKey):
f = open(privKey, 'r')
keyString = f.read()
keyString = keyString.encode('utf-8')
key = rsa.PrivateKey.load_pkcs1(keyString)
return binascii.b2a_hex(rsa.sign(message.encode(), key, 'SHA-512')).decode('utf-8')
知道是什么造成了这种差异,我遗漏了什么吗?
谢谢!
编辑: 我的 Python 脚本确实验证了签名的随机数是否有效,并且我对 Python 和 Java 代码使用相同的 public 和私钥,但显然得到有符号值的不同结果。这对我来说意味着 java.security 和 M2Crypto/RSA 使用的签名算法是不同的,但我可能离题太远了——我是加密新手。
编辑2: 我尝试使用 M2Crypto.RSA 对 nonce 进行签名,得到的响应仍然不同,但修改了代码,现在 M2Crypto EVP 和 RSA,以及 rsa 正在输出相同的签名值。仍然没有运气让他们匹配 Java:
的预期值Expected value: 6d90537599b912ac0de9f68dc0d104a04c5aa74e35262f73872bb01ed1e2cc37100ff1a00735da307fa325f3e30f3c81157755fc60c7ee69bd91bf44b6a5f5e4161bdd67cf982550d992a0a16d12ed5ea30b878a8b2f8eee61cf64e083d7b74a635dabba44bf0b51b9b305aa901b3d090712ee3994057b076d53366a3a387de0f7b2e220cf11239facfce0df6d9a54dfb365f7d3996ea20b55ec75e3661cf95392eda75696cfc6bebda304a2671428dad38a43d5a579550595fe9180539b2b7eb3d568a1f8ce05ded2ae3241a732fffd1404f989eea3e68dda6cd13bfcd6b2e47e64685763a6c3c0f1c47f84c908e22e718254b9f46a7a1de7e2280ccb59c1c5
M2Crypto RSA: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
M2Crypto EVP: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
rsa: 2c973dd7006c058293787504203e36e921ae286f44bcdbf2bd4b48c8a7d9a73723c058d1bcd15b76f6a7145d55cf6109f4bbe5f3953d953177117ef4733e4d3ac22e8a4d320ae6c3a626ddce2a3d5db6b0f10656dd49179c3d60ba912bf21b2e2eac5def74aa6809b74d7711cbb86d719b1fe4df5b7215067af34de3e03859e2c919587bc7f00ec96c6b678c5fc8e114cebae3f5d301811dacc247cd2df9dadf62bccd524147f582f77f0ce29077c7352c8b9893056dce3d65de44d0fc45b88363db9df59c142a01d8f32bf48f05183757e3cd0954c528a7601f4edb56ed9175b219e08aa79514694aedff45bbb365e7d54e534973f6a2aa9f22da12890bbbb5
我能够通过同时使用 EVP 和 RSA 模块来签署我的随机数来解决问题:
key = RSA.load_key(privKey)
md = EVP.MessageDigest('sha512')
md.update(message)
digest=md.final()
signature = key.sign(digest, "sha512")
return b64encode(signature).decode('utf-8')