gpt4 book ai didi

c++ - 不同消息的 OpenSSL 签名长度不同

转载 作者:太空宇宙 更新时间:2023-11-04 08:05:13 26 4
gpt4 key购买 nike

我一直在努力解决 RSA_verify 的一个奇怪问题。我正在尝试使用 C 进行 RSA_sign 并使用 C++ 进行 RSA_verify。我已经使用 OpenSSL 命令生成了私钥和证书。

message = "1.2.0:08:00:27:2c:88:77"

当我使用上面的消息时,生成一个散列并使用 RSA_sign 对摘要进行签名,我得到一个长度为 256 的签名 (strlen(signature)) 并且从 RSA_sign 返回的长度也是 256 .我用这个长度来验证,验证成功。

但是当我使用 message = "1.2.0:08:00:27:2c:88:08" 时,签名长度为 60,RSA_sign 返回 256。当我使用这个长度时60 验证失败。它也无法验证长度为 256。同样对于某些消息 (1.2.0:08:00:27:2c:88:12),生成的签名为零。

我正在使用 SHA256 对消息进行哈希处理,并使用 NID_SHA256 对这个摘要进行 RSA_sign 和 RSA_verify。我在使用 OpenSSL 命令生成 key 时使用了 -sha256。

我通过使用一些字符串操作读取一些标签来解析 XML 文件来形成消息。

请提出建议。

下面是用于签名的代码。

int main(void)  
{
int ret;
RSA *prikey;
char *data ;
unsigned char* signature;
int slen = 0;
FILE * fp_priv = NULL;
char* privfilepath = "priv.pem";
unsigned char* sign = NULL;

ERR_load_crypto_strings();

data = generate_hash();
printf("Message after generate hash %s: %d\n", data, strlen(data));

fp_priv = fopen(privfilepath, "r");
if (fp_priv == NULL)
{
printf("Private key path not found..");
return 1;
}
prikey = RSA_new();
prikey = PEM_read_RSAPrivateKey(fp_priv, &prikey, NULL, NULL);
if (prikey == NULL)
{
printf("Private key returned is NULL\n");
return 1;
}

signature = (unsigned char*)malloc(RSA_size(prikey));

if( signature == NULL )
return 1;

if(RSA_sign(NID_sha256, (unsigned char*)data, strlen(data),
signature, &slen, prikey) != 1) {
ERR_print_errors_fp(stdout);
return 1;
}
printf("Signature length while signing... %d : %d : %d ",
strlen(signature), slen, strlen(data));

FILE * sig_bin = fopen("sig_bin", "w");
fprintf(sig_bin, "%s", signature);
fclose(sig_bin);

system("xxd -p -c256 sig_bin sig_hex");

RSA_free(prikey);
if(signature)
free(signature);
return 0;
}

最佳答案

关于 C 的一个非常非常重要的事情是它有两个同名的不同类型。

  • char*:表示字符串的开头。您可以执行类似 strstr 或 strlen 的操作。
    • 您永远不应该使用 strstr 或 strlen,而应该使用 strnstr 和 strnlen,但这是一个不同的问题。
  • char*:这表示数据 blob 的开始(又名字节数组,又名八位字节串),您不能对其应用 strlen/etc 有意义。

RSA_sign 使用的是后者。它返回“数据”,而不是“消息”。所以,在你的片段中

printf("Signature length while signing... %d : %d : %d ",  
strlen(signature), slen, strlen(data));

FILE * sig_bin = fopen("sig_bin", "w");
fprintf(sig_bin, "%s", signature);
fclose(sig_bin);

data 来自一个名为 generate_hash() 的函数;它可能是非文本的,因此 strlen 不适用。 signature肯定是数据,所以strlen不适用。出于同样的原因,fprintf 也不适用。这些函数通过第一次出现零字节(0x00、'\0' 等)来标识字符串的结尾。但是 0x00 在签名、散列或大量“数据”中是完全合法的。

RSA_sign 的输出长度被写入到传递给第 5 个参数的地址中。您传递了 &slen(slen 的地址),因此一旦函数退出(成功),slen 就是签名的长度。请注意,它很少会匹配 strlen(signature)。

要将你的签名写成二进制,你应该使用fwrite ,例如 fwrite(sig_bin, sizeof(char), signature, slen);。如果你想要它作为文本,你应该 Base-64对您的数据进行编码。

关于c++ - 不同消息的 OpenSSL 签名长度不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43342661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com