为什么我在 C++ 和 Python 中执行 RSA 签名时得到不同的签名?
Why I got different signature when I perform RSA sign in C++ and Python?
我正在尝试使用 sha1 创建 RSA 签名。基本步骤是:
- 使用 sha1 散列源数据(以获取摘要)
- 使用摘要和私钥进行 RSA 签名
- 将签名转换为十六进制字符串
所以,Python 代码是这样的:
pri_key = RSA.load_key(key_file);
digest = sha1_func(data).digest();
signature = pri_key.sign(digest, 'sha1')
;
return binascii.hexlify(signature);
源数据为:
s34caoguangshui@163.com1100
这是最终结果:
2034c9d2cacfdac1a69b737ab00d3fc42e8533b656f638c60ca503924706e49f017d2b29c8efe6903927c2b02fd24a5f50fef49ba137697983ece22761082b00ac433362b305023814e95278641ad8d8b3aa097f79bd392a325ee7182881b5e6a2d4e4d383c49a8842a3f6cdaee8deb33c257385aa2cf2946216cf09c6383145
我正在使用 OpenSSL 库在 C++ 中编程。我采取了我认为相同的步骤,但得到了不同的结果。实际上我只得到了上面发布的结果的前半部分:
2034c9d2cacfdac1a69b737ab00d3fc42e8533b656f638c60ca503924706e49f017d2b29c8efe6903927c2b02fd24a5f50fef49ba137697983ece22761082b
后半段去哪了?
这是我的 C++ 代码:
int rc = 1;
SHA_CTX sha_ctx = { 0 };
unsigned char digest[SHA_DIGEST_LENGTH];
rc = SHA1_Init(&sha_ctx);
if (1 != rc) { }
rc = SHA1_Update(&sha_ctx, source_data, source_len);
if (1 != rc) { }
rc = SHA1_Final(digest, &sha_ctx);
if (1 != rc) { }
RSA* rsa = PEM_read_RSAPrivateKey(private_key_file, NULL, NULL, NULL);
int sig_len = 0;
unsigned char* sig = malloc(RSA_size(rsa));
rc = RSA_sign(NID_sha1, digest, sizeof digest, sig, &sig_len, rsa);
if (1 != rc) { }
return binToHex(sig);
此外,我从第一步得到了相同的摘要。
我还尝试了 EVP API,这是更推荐的方式:
EVP_PKEY* private_key = PEM_read_PrivateKey(private_key_file, NULL, NULL, NULL);
EVP_MD_CTX evp_ctx;
EVP_SignInit(&evp_ctx, EVP_sha1());
EVP_SignUpdate(&evp_ctx, source_data, source_len);
EVP_SignFinal(&evp_ctx, sig, sig_len, private_key);
return binToHex(sig);
我也只拿到了前半部分
根据您提供的内容,可能的推论是函数 bintohex 正在切断签名,因为它遇到了一个“00”('\0'),这表明从您生成的 string.The sig 终止C++ 代码仅在未遇到 \0 之前转换为十六进制。
你可以做的是,尝试从 python 和 c++ 代码为其他一些(测试)消息生成签名,以缩小问题范围并确保 bintohex 在这种情况下缩短签名,通过观察您是否在其他消息正文上获得相同的签名,如果它们仍然不相同,请查看 c++ 签名是否在 00 处缩短。
我正在尝试使用 sha1 创建 RSA 签名。基本步骤是:
- 使用 sha1 散列源数据(以获取摘要)
- 使用摘要和私钥进行 RSA 签名
- 将签名转换为十六进制字符串
所以,Python 代码是这样的:
pri_key = RSA.load_key(key_file);
digest = sha1_func(data).digest();
signature = pri_key.sign(digest, 'sha1')
;
return binascii.hexlify(signature);
源数据为:
s34caoguangshui@163.com1100
这是最终结果:
2034c9d2cacfdac1a69b737ab00d3fc42e8533b656f638c60ca503924706e49f017d2b29c8efe6903927c2b02fd24a5f50fef49ba137697983ece22761082b00ac433362b305023814e95278641ad8d8b3aa097f79bd392a325ee7182881b5e6a2d4e4d383c49a8842a3f6cdaee8deb33c257385aa2cf2946216cf09c6383145
我正在使用 OpenSSL 库在 C++ 中编程。我采取了我认为相同的步骤,但得到了不同的结果。实际上我只得到了上面发布的结果的前半部分:
2034c9d2cacfdac1a69b737ab00d3fc42e8533b656f638c60ca503924706e49f017d2b29c8efe6903927c2b02fd24a5f50fef49ba137697983ece22761082b
后半段去哪了?
这是我的 C++ 代码:
int rc = 1;
SHA_CTX sha_ctx = { 0 };
unsigned char digest[SHA_DIGEST_LENGTH];
rc = SHA1_Init(&sha_ctx);
if (1 != rc) { }
rc = SHA1_Update(&sha_ctx, source_data, source_len);
if (1 != rc) { }
rc = SHA1_Final(digest, &sha_ctx);
if (1 != rc) { }
RSA* rsa = PEM_read_RSAPrivateKey(private_key_file, NULL, NULL, NULL);
int sig_len = 0;
unsigned char* sig = malloc(RSA_size(rsa));
rc = RSA_sign(NID_sha1, digest, sizeof digest, sig, &sig_len, rsa);
if (1 != rc) { }
return binToHex(sig);
此外,我从第一步得到了相同的摘要。 我还尝试了 EVP API,这是更推荐的方式:
EVP_PKEY* private_key = PEM_read_PrivateKey(private_key_file, NULL, NULL, NULL);
EVP_MD_CTX evp_ctx;
EVP_SignInit(&evp_ctx, EVP_sha1());
EVP_SignUpdate(&evp_ctx, source_data, source_len);
EVP_SignFinal(&evp_ctx, sig, sig_len, private_key);
return binToHex(sig);
我也只拿到了前半部分
根据您提供的内容,可能的推论是函数 bintohex 正在切断签名,因为它遇到了一个“00”('\0'),这表明从您生成的 string.The sig 终止C++ 代码仅在未遇到 \0 之前转换为十六进制。
你可以做的是,尝试从 python 和 c++ 代码为其他一些(测试)消息生成签名,以缩小问题范围并确保 bintohex 在这种情况下缩短签名,通过观察您是否在其他消息正文上获得相同的签名,如果它们仍然不相同,请查看 c++ 签名是否在 00 处缩短。