Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有效创建数字签名的正确方法是什么?我可以使用DSA_sign_setup()吗?_C++_Openssl_Digital Signature_Dsa - Fatal编程技术网

C++ 有效创建数字签名的正确方法是什么?我可以使用DSA_sign_setup()吗?

C++ 有效创建数字签名的正确方法是什么?我可以使用DSA_sign_setup()吗?,c++,openssl,digital-signature,dsa,C++,Openssl,Digital Signature,Dsa,我正在开发一个性能至关重要的应用程序 在这个应用程序中,我有很多消息(即数千条)需要使用相同的私钥/公钥分别签名(当然还有验证)。我正在使用OpenSSL库 使用DSA函数(见下文)的简单方法将需要数十秒的时间进行签名,这并不好。我试图使用DSA\u sign\u setup()函数来加快速度,但我想不出正确的使用方法 我也尝试过ECDSA,但我无法获得正确的配置 如果我真的关心效率,那么正确的方法是什么 #include <openssl/dsa.h> #include <o

我正在开发一个性能至关重要的应用程序

在这个应用程序中,我有很多消息(即数千条)需要使用相同的私钥/公钥分别签名(当然还有验证)。我正在使用OpenSSL库

使用DSA函数(见下文)的简单方法将需要数十秒的时间进行签名,这并不好。我试图使用
DSA\u sign\u setup()
函数来加快速度,但我想不出正确的使用方法

我也尝试过ECDSA,但我无法获得正确的配置

如果我真的关心效率,那么正确的方法是什么

#include <openssl/dsa.h>
#include <openssl/engine.h>
#include <stdio.h>
#include <openssl/evp.h>

int N=3000;

int main()
{
    DSA *set=DSA_new();
    int a;
    a=DSA_generate_parameters_ex(set,1024,NULL,1,NULL,NULL,NULL);
    printf("%d\n",a);
    a=DSA_generate_key(set);
    printf("%d\n",a);
    unsigned char msg[]="I am watching you!I am watching you!";
    unsigned char sign[256];
    unsigned int size;
    for(int i=0;i<N;i++)
        a=DSA_sign(1,msg,32,sign,&size,set);
    printf("%d %d\n",a,size);
}
#包括
#包括
#包括
#包括
int N=3000;
int main()
{
DSA*set=DSA_new();
INTA;
a=DSA_生成_参数_ex(set,1024,NULL,1,NULL,NULL,NULL);
printf(“%d\n”,a);
a=DSA_生成_密钥(设置);
printf(“%d\n”,a);
unsigned char msg[]=“我在看你!我在看你!”;
无符号字符符号[256];
无符号整数大小;

对于(int i=0;i如果消息较大,通常会对其进行安全哈希并对哈希进行签名。这要快得多。当然,您需要传输消息、哈希和签名,检查过程必须包括重新哈希和检查是否相等,以及数字签名验证。

如果消息较大,则通常是对它们进行安全哈希并对哈希进行签名。这要快得多。当然,您需要传输消息、哈希和签名,并且检查过程必须包括重新哈希和检查是否相等,以及数字签名验证。

我决定删除此答案,因为它会影响您的工作使他们的软件安全

如果您查看编辑,我发布的代码仍然可见,但是不要使用它,它是不安全的。如果这样做,您就有风险公开您的私钥


请不要说您没有收到警告。事实上,如果您使用的是
DSA\u sign\u setup()
在您自己的代码中,因为您不应该这样做。Romen在上面的回答中有更多关于这一点的详细信息。谢谢。

我决定删除这个答案,因为它损害了OpenSSL团队为确保其软件安全所做的努力

如果您查看编辑,我发布的代码仍然可见,但是不要使用它,它是不安全的。如果这样做,您就有风险公开您的私钥

请不要说您没有收到警告。事实上,如果您在自己的代码中使用
DSA\u-sign\u-setup()
,请将其视为警告,因为您不应该收到警告。罗门在上面的回答中有更多关于此的详细信息。谢谢。

使用
DSA\u-sign\u-setup()
上面提出的方法实际上是完全不安全的,幸运的是,OpenSSL开发人员使DSA结构不透明,因此开发人员无法强行使用

DSA\u sign\u setup()
生成一个新的随机nonce(即每个签名的一种临时密钥)。它应该永不在相同的长期密钥下重复使用。永不

从理论上讲,对同一条消息重复使用相同的nonce仍然相对安全,但一旦对两条不同的消息重复使用相同的私钥和nonce组合,攻击者就可以泄露检索密钥所需的所有信息(请参阅这基本上是由于在ECDSA中重复使用nonce时犯了相同的错误)

不幸的是,DSA速度很慢,尤其是现在需要更长的键:为了加快应用程序的速度,您可以尝试使用ECDSA(例如,使用曲线NISTP256,仍然没有nonce重用)或Ed25519(确定性nonce)


使用
EVP\u DigestSign
API进行概念验证 更新:以下是如何使用OpenSSL以编程方式生成签名的概念证明。 首选的方法是使用,因为它抽象出正在使用哪种非对称密钥

下面的示例在中扩展了PoC:我使用DSA或NIST p-256私钥以及OpenSSL 1.0.2、1.1.0和1.1.1-pre6测试了这一功能

#包括
#包括
#包括
#包括
#包括
#包括
#定义密钥文件“private_key.pem”
#定义N 3000
#定义大小80
EVP_PKEY*从文件(const char*fname)读取_secret_key_
{
EVP_PKEY*key=NULL;
文件*fp=fopen(fname,“r”);
如果(!fp){
perror(fname);返回NULL;
}
key=PEM_read_PrivateKey(fp,NULL,NULL,NULL);
fclose(fp);
返回键;
}
int do_符号(EVP_PKEY*键,常量无符号字符*消息,常量大小,
未签名字符**sig,大小(S)
{
EVP_MD_CTX*mdctx=NULL;
int-ret=0;
/*创建消息摘要上下文*/
如果(!(mdctx=EVP_MD_CTX_create())出现错误;
/*初始化DigestSign操作-已选择SHA-256
*作为本例中的消息摘要函数*/
if(1!=EVP_DigestSignInit(mdctx,NULL,EVP_sha256(),NULL,key))
后悔莫及;
/*用消息调用update*/
如果(1!=执行副总裁DigestSignUpdate(mdctx、msg、mlen))出现错误;
/*完成签名操作*/
/*首先使用NULL sig参数调用EVP_DigestSignFinal以
*获取签名的长度。长度以slen形式返回*/
如果(1!=EVP_DigestSignFinal(mdctx,NULL,slen))转到错误;
/*根据slen中的大小为签名分配内存*/
如果(!(*sig=OPENSSL_malloc(*slen)),则转到错误;
/*获得签名*/
如果(1!=执行副总裁DigestSignFinal(mdctx,*sig,slen))出现错误;
/*成功*/
ret=1;
错误:
如果(ret!=1)
{
/*做一些错误处理*/
}
/*清理*/
如果(*sig&&!ret)OPENSSL_免费(*sig);
如果(mdctx)EVP_MD_CTX_destroy(mdctx);
返回ret;
}
int main()
{
内网
Running ./op_example
time ./op_example >/dev/null
0.32user 0.00system 0:00.32elapsed 100%CPU (0avgtext+0avgdata 3452maxresident)k
0inputs+0outputs (0major+153minor)pagefaults 0swaps

Running ./dsa_example
time ./dsa_example >/dev/null
0.42user 0.00system 0:00.42elapsed 100%CPU (0avgtext+0avgdata 3404maxresident)k
0inputs+0outputs (0major+153minor)pagefaults 0swaps

Running ./evp_example
time ./evp_example >/dev/null
0.12user 0.00system 0:00.12elapsed 99%CPU (0avgtext+0avgdata 3764maxresident)k
0inputs+0outputs (0major+157minor)pagefaults 0swaps