为什么我在 C++ 和 Python 中执行 RSA 签名时得到不同的签名?

Why I got different signature when I perform RSA sign in C++ and Python?

我正在尝试使用 sha1 创建 RSA 签名。基本步骤是:

  1. 使用 sha1 散列源数据(以获取摘要)
  2. 使用摘要和私钥进行 RSA 签名
  3. 将签名转换为十六进制字符串

所以,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 处缩短。