数字签名
-
int err;
-
int sig_len;
-
unsigned char sig_buf [4096];
-
static char certfile[] = "cert.pem";
-
static char keyfile[] = "key.pem";
-
static char data[] = "I owe you...";
-
EVP_MD_CTX md_ctx;
-
EVP_PKEY * pkey;
-
FILE * fp;
-
X509 * x509;
-
ERR_load_crypto_strings();
-
/* Read private key */
-
fp = fopen (keyfile, "r");
-
pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); //加载私钥
-
fclose (fp);
-
-
EVP_SignInit (&md_ctx, EVP_sha1());
-
EVP_SignUpdate (&md_ctx, data, strlen(data));
-
sig_len = sizeof(sig_buf);
-
err = EVP_SignFinal (&md_ctx, sig_buf, &sig_len, pkey)
关键是这几个函数:
EVP_SignInit 初始化结构ctx。成功返回1,失败返回0。
EVP_SignUpdate 该函数使用方法和功能与EVP_DigestUpdate函数一样,将一个cnt字节的数据经过信息摘要运算存储到结构ctx中,该函数可以在一个相同的ctx中调用多次来实现对更多数据的信息摘要工作。成功返回1,失败返回0。
EVP_SignFinal
该函数将签名操作的信息摘要结构ctx拷贝一份,然后调用
EVP_DigestFinal_ex完成信息摘要工作,然后开始对摘要信息用私钥pkey进行签名(加密),并将签名信息保存在参数sig里面。如果参数s不为
NULL,那么就会将签名信息数据的长度(单位字节)保存在该参数中,通常写入的数据是EVP_PKEY_size(key)。成功返回1,否则返回0。
验证签名的代码
-
fp = fopen (certfile, "r");
-
x509 = PEM_read_X509(fp, NULL, NULL, NULL);
-
fclose (fp);
-
/* Get public key - eay */
-
pkey=X509_get_pubkey(x509); //加载公钥
-
/* Verify the signature */
-
EVP_VerifyInit (&md_ctx, EVP_sha1());
-
EVP_VerifyUpdate (&md_ctx, data, strlen((char*)data));
-
err = EVP_VerifyFinal (&md_ctx, sig_buf, sig_len, pkey)
关键是这几个函数:
EVP_VerifyInit 该函数与EVP_SignInit 相同,同为初始化一个上下文结构
EVP_VerifyUpdate 计算摘要
EVP_VerifyFinal
该函数使用公钥pkey和ctx结构里面的信息验证sigbuf里面的数据的签名。事实上,该函数先调用EVP_MD_CTX_copy_ex函数将原来的ctx拷贝一份,然后调用EVP_DigestFinal_ex函数完成拷贝的ctx的信息摘要计算,最后才使用公钥进行签名的验证工作。
看完上面的代码还有一点不太明白,摘要和签名到底什么区别,为什么加密了就是签名,下面看一下原理:
:
(1)
被发送文件用SHA编码加密产生128bit的
(2) 用自己的私用密钥对摘要再加密,这就形成了数字签名
(3)
将原文和加密的摘要同时传给对方
(4) 对方用发送方的公共密钥对摘要解密,同时对收到的文件用SHA编码加密产生又一摘要。
(5)
将解密后的摘要和收到的文件在接收方重新加密产生的摘要相互对比。如两者一致,则说明传送过程中信息没有被破坏或篡改过。否则不然。
数字摘要:发送端把原信息用HASH函数计算成摘要,然后把数字摘要和原信息一起发送到接收端,接收端也用HASH函数把原消息加密为摘要,看两个摘要是否相同,若相同,则表明信息的完整.否则不完整.
数字签名使用了非对称加密算法,用私钥加密了摘要,因为私钥只有消息发送方有,所以保证了发送方的正确性。而摘要没有这一层机制,所以不能保证接收到的信息没有被第三方篡改。
阅读(1574) | 评论(0) | 转发(0) |