C++基础:OpenSSL常用函数(签名与验证)

合集下载

OpenSSLX509证书操作函数

OpenSSLX509证书操作函数

现有的证书大都采用X。

509规范,主要同以下信息组成:版本号、证书序列号、有效期、拥有者信息、颁发者信息、其他扩展信息、拥有者的公钥、CA 对以上信息的签名。

OpenSSL实现了对X。

509数字证书的所有操作。

包括签发数字证书、解析和验证证书等。

涉及证书操作的主要函数有验证证书(验证证书链、有效期、CRL)、解析证书(获得证书的版本、序列号、颁发者信息、主题信息、公钥、有效期等)。

主要函数1、DER编码转换为内部结构函数X509 *d2i_X509(X509 **cert, unsigned char **d, int len);函数功能:把一个DER编码的证书数据转化成OpenSSL内部结构体。

参数:cert:[OUT]X509结构体。

D:[IN]DER编码的证书数据指针地址。

Len证书数据长度;返回值:编码后的X509结构体数据2、获得证书版本函数X509_get_version#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version)参数:x:[IN]X509*结构体数据结构。

返回值:证书版本,数据类型“LONG”3、获得证书序列号函数ASN1_INTEGER *X509_get_serialNumber(X509 *x);返回值:证书序列号,数据类型“ASN1_INTEGER”.4、获得证书颁发者信息函数X509_NAME *X509_get_issuer_name(X509 *a);注*:X509_NAME结构体包括多个X509_NAME_ENTRY结构体。

X509_NAME_ENTRY保存了颁发者的信息,这些信息包括对象和值(object 和value)。

对象的类型包括国家、通用名、单位、组织、地区、邮件等。

5、获得证书拥有者信息函数X509_NAME *X509_get_subject_name(X509 *a);6、获得证书有效期的起始日期函数#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)返回值:证书起始有效期,数据类型“ASN1_TIME”7、获得证书有效期的终止日期函数#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)8、获得证书公钥函数EVP_PKEY *X509_get_pubkey(X509 *x);9、创建和释放证书存储区X509_STORE *X509_STORE_new(void);Void X509_STORE_free(X509_STORE *v);函数功能:创建和释放一个X509_STORE结构体,主要用于验证证书。

openssl操作手册

openssl操作手册

OpenSSL 是一个开源的加密库,提供了各种加密算法、数字证书、SSL/TLS 协议等功能,被广泛用于网络安全和加密通信领域。

以下是OpenSSL 的一些常见用法和操作:1. 生成证书:使用OpenSSL 可以生成各种类型的数字证书,包括自签名证书、CA 证书、服务器证书、客户端证书等。

您可以使用OpenSSL 提供的命令行工具或API 接口来生成证书。

2. 加密和解密:OpenSSL 提供了各种加密算法,包括对称加密和非对称加密。

您可以使用OpenSSL 提供的命令行工具或API 接口来进行加密和解密操作。

3. 签名和验证:OpenSSL 提供了数字签名和验证的功能,可以用于保证数据的完整性和真实性。

您可以使用OpenSSL 提供的命令行工具或API 接口来进行签名和验证操作。

4. SSL/TLS 安全通信:OpenSSL 提供了SSL/TLS 协议的实现,可以用于安全通信。

您可以使用OpenSSL 提供的命令行工具或API 接口来实现SSL/TLS 安全通信。

5. 网络安全工具:OpenSSL 提供了各种网络安全工具,包括OpenSSL s_server、OpenSSL s_client、OpenSSL speed、OpenSSL rand 等。

这些工具可以用于测试和评估网络安全性能。

要使用OpenSSL,您需要安装OpenSSL 库,并包含相应的头文件。

在编写代码时,您可以调用OpenSSL 提供的函数和数据结构来实现您需要的加密、签名、SSL/TLS 安全通信等功能。

OpenSSL 提供了详细的文档和使用手册,您可以在OpenSSL 官方网站上找到完整的文档和参考手册。

在文档中,您可以找到各种函数的使用说明、示例代码和详细的接口说明,以帮助您更好地使用OpenSSL 库。

OpenSSL签名流程

OpenSSL签名流程

OpenSSL签证书流程生成根证书生成根证书所用的密钥: genrsa -des3 -out ca.key 1024去除CA密钥的口令:rsa -in ca.key -out ca.key编辑C:\Windows\System32\drivers\etc\hosts文件:localhost LEE-PC192.168.20.186 LEE-PC生成CA即ROOT CA证书并自签:req -new -x509 -key ca.key -out ca.crt将“ca.crt”安装到我们的IE的信任域里。

生成Web服务器端证书生成Web服务器端证书密钥:genrsa -des3 -out server.key 1024去除CA密钥的口令:rsa -in server.key -out server.key生成Web服务器端证书的签名请求:req –new –key server.key –out server.csrD:\tools\openssl-1.0.1g\apps\demoCA下,建立“文件夹”newcerts编辑修改f修改:dir = D:\\tools\\openssl-1.0.1g\\apps\\demoCA用Root CA去对Web服务器的证书请求即csr(certificate request)进行签名认证:ca –in server.csr –out server.crt –cert ca.crt –keyfile ca.key提示全部输入y点击生成的server.crt生成Tomcat的SSL证书生成JKS密钥对:keytool -genkey -keystore tcps.jks -alias tcps -keyalg RSA -keysize 1024 -validity 3650 -dname "CN=LEE-PC, OU=TCPS, O=TCPS, L=TJ, S=TJ, C=CN"生成JSK的CSR:keytool -certreq -alias tcps -sigalg "MD5withRSA" -file tcps.csr -keystore tcps.jks使用openssl结合ca.crt与ca.key为jsk的csr来签名认证并产生jks格式的crt:openssl x509 -req -in tcps.csr -out tcps.crt -CA ca.crt -CAkey ca.key -days 3650 -CAcreateserial -sha1 -trustout -CA ca.crt -CAkey ca.key -days 3650 -CAserial ca.srl -sha1 -trustout生成符合x509格式的jks文件将Root CA导入jks信任域:keytool -import -alias rootca -trustcacerts -file ca.crt -keystore tcps.jks补链,补信任链:keytool -import -alias tcps -file tcps.crt -keystore tcps.jks。

openssl摘要和签名验证指令dgst使用详解

openssl摘要和签名验证指令dgst使用详解

openssl摘要和签名验证指令dgst使⽤详解1、信息摘要和数字签名概述信息摘要:对数据进⾏处理,得到⼀段固定长度的结果,其特点输⼊:1、输出长度固定。

即输出长度和输⼊长度⽆关。

2、不可逆。

即由输出数据理论上不能推导出输⼊数据4、对输⼊数据敏感。

当输⼊数据变化极⼩时,输出数据也会发⽣明显的变化5、防碰撞。

即不同的数据数据得到相同输出数据的可能性极低。

由于信息摘要有上述特点,⼀般保证数据的完整性,对⼀个⼤⽂件进⾏摘要运算,得到其摘要值。

通过⽹络或者其他渠道传输后,通过验证其摘要值,确定⼤⽂件本⾝有没有发⽣变化。

数字签名:数字签名其实分成两步,⾸先对原始⽂件进⾏摘要运算,得到摘要值,然后使⽤公开密钥算法中的私钥对摘要值进⾏加密。

其签名和验证过程如下图所⽰有数字签名的过程可以知道,对发送信息进⾏数字签名,可以保证数字签名的完整性、真实性、不可抵赖性。

即接收者可以确认消息的来源、消息的真实,发送者不可以抵赖⾃⼰发送的消息,与现实⽣活中签名的作⽤⼤致相同。

2、摘要算法和数字签名相关指令及⽤法⽬前openssl提供的摘要算法有md4、md5、ripemd160、sha、sha1、sha224、sha256、sha512、sha384、wirlpool。

可以通过openssl dgst -命令查看。

上⾯我们已经提到了,数字签名分为摘要和加密两部分。

在openssl提供的指令中,并没有区分两者。

⽽是在摘要算法指令中包含了签名和校验参数。

例如我们适⽤openssl md5 -命令可以看到它提供的选项有签名和验证等参数。

在openssl中单独使⽤摘要算法指令完成摘要或者签名操作,也可以通过dgst完成相同的操作。

在签名的时候多数使⽤RSA私钥或者DSA私钥,当使⽤RSA私钥的时候,我们可以使⽤单独的摘要算法指令指定摘要算法进⾏签名,但当使⽤DSA使⽤签名的时候,就必须使⽤dgst指令,因为使⽤DSA签名的时候必须使⽤DSA⾃⾝的摘要算法,⽽openssl没有为它提供相应的指令。

openssl 操作手册

openssl 操作手册

OpenSSL 是一个强大的安全套接字层密码库,包含了各种加密算法的实现,提供了通用的密码安全服务。

下面是一个简要的OpenSSL 操作手册,包括一些常用的命令和选项:1. 生成密钥对:```openssl genpkey -algorithm RSA -out private_key.pemopenssl rsa -pubout -in private_key.pem -out public_key.pem```2. 生成自签名证书:```cssopenssl req -new -x509 -key private_key.pem -out cert.pem -days 365```3. 生成证书签名请求(CSR):```openssl req -new -key private_key.pem -out request.csr```4. 验证证书签名:```bashopenssl x509 -in cert.pem -text -noout```5. 导出证书为PEM 格式:```bashopenssl x509 -in cert.der -inform DER -outform PEM -out cert.pem```6. 加密数据:```cssopenssl enc -aes-256-cbc -salt -in plaintext.txt -out ciphertext.enc```7. 解密数据:```cssopenssl enc -aes-256-cbc -d -in ciphertext.enc -out plaintext.txt```8. 生成随机数:```openssl rand -out random.bin 1024```9. 验证数字签名:```cssopenssl dgst -sha256 -sign private_key.pem -in file.txt -out signature.bin openssl dgst -sha256 -verify public_key.pem -signature signature.bin file.txt```10. 生成Diffie-Hellman 密钥交换参数:```openssl dhparam -out dhparam.pem 2048```11. 生成CA 证书:```cssopenssl req -new -x509 -days 365 -extensions v3_ca -key private_ca_key.pem -out ca.pem```12. 生成服务器证书:```cssopenssl req -new -key private_server_key.pem -out server.reqopenssl x509 -req -days 365 -in server.req -CA ca.pem -CAkey private_ca_key.pem -CAcreateserial -out server.pem```13. 生成客户端证书:```cssopenssl req -new -key private_client_key.pem -out client.reqopenssl x509 -req -days 365 -in client.req -CA ca.pem -CAkey private_ca_key.pem -CAcreateserial -out client.pem```这只是一些常见的OpenSSL 命令示例,OpenSSL 还提供了许多其他功能和选项,具体可以参考官方文档或使用`man openssl` 命令来获取完整的操作手册。

OpenSSL使用指南-0.5

OpenSSL使用指南-0.5

OpenSSL使用指南目录1.介绍2.编译3.运行OpenSSL.exe4.算法编程API4.1 对称算法4.1.1 DES4.1.2 AES4.1.3 RC44.1.4 EVP_4.2 公钥算法4.3 Hash算法4.4 随机数算法5.SSL协议编程API6.CA和证书7.8.参考网址9.A.示例程序B.1.介绍OpenSSL是使用非常广泛的SSL的开源实现。

由于其中实现了为SSL所用的各种加密算法,因此OpenSSL也是被广泛使用的加密函数库。

1.1 SSLSSL(Secure Socket Layer)安全协议是由Netscape公司首先提出,最初用在保护Navigator浏览器和Web服务器之间的HTTP通信(即HTTPS)。

后来SSL协议成为传输层安全通信事实上的标准,并被IETF吸收改进为TLS(Transport Layer Security)协议。

SSL/TLS协议位于TCP协议和应用层协议之间,为传输双方提供认证、加密和完整性保护等安全服务。

SSL作为一个协议框架,通信双方可以选用合适的对称算法、公钥算法、MAC 算法等密码算法实现安全服务。

1.2 OpenSSLOpenSSL是著名的SSL的开源实现,是用C语言实现的。

OpenSSL的前身是SSLeay,一个由Eric Young开发的SSL的开源实现,支持SSLv2/v3和TLSv1。

伴随着SSL协议的普及应用,OpenSSL被广泛应用在基于TCP/Socket的网络程序中,尤其是OpenSSL和Apache相结合,是很多电子商务网站服务器的典型配置。

2.编译和安装OpenSSLOpenSSL开放源代码,这对学习、分析SSL和各种密码算法提供了机会,也便于在上面进一步开发。

2.1 获得OpenSSL到OpenSSL的网站即可下载当前版本的OpenSSL源代码压缩包。

当前版本openssl-0.9.8.tar.gz,只有3M多,比较精简。

openssl_sign 方法

openssl_sign 方法openssl_sign 方法是 OpenSSL 所提供的用于数字签名的函数。

数字签名是一种常见的信息安全技术,用于确保消息的完整性、鉴别身份和防止篡改。

在网络通信、电子商务、数字证书等领域都广泛应用。

该方法的定义如下:```int openssl_sign(const unsigned char *data, int data_len,unsigned char *signature, unsigned int *signature_len,EVP_PKEY *private_key, EVP_MD *md);```其中,各参数意义如下:- `data`:待签名的数据,可以是任意格式的二进制数据。

- `data_len`:待签名数据的长度,单位为字节。

- `signature`:签名结果的缓冲区,大小至少应为`EVP_PKEY_size(private_key)`。

- `signature_len`:签名结果的长度,单位为字节。

- `private_key`:用于签名的私钥,类型为 `EVP_PKEY`。

- `md`:使用的哈希算法,类型为 `EVP_MD`。

该函数的返回值是一个整数,表示签名操作的执行结果。

大于0表示签名成功,返回值为签名结果的长度;小于或等于0表示签名失败,具体错误可以通过调用`ERR_get_error()` 函数获取。

下面我们来详细解释一下其中各参数的使用方法和作用。

### data 和 data_len`data` 参数是待签名的数据,可以是任意格式的二进制数据。

数字签名的目的是为了保证数据的完整性,因此我们通常对数据进行哈希运算,得到一个固定长度的哈希值,再对该哈希值进行签名。

因此签名的内容实际上是哈希值,而非原始数据本身。

`data_len` 参数是待签名数据的长度,单位为字节。

它告诉 OpenSSL 所有签名操作所需的字节数,因此我们必须先计算出待签名数据的长度,再传递给该函数。

openssl_sign()的可能原因

openssl_sign() 函数是PHP中用来对数据进行数字签名的一个重要函数。

当我们调用openssl_sign()函数时,有时候可能会出现签名失败的情况。

这种情况可能会导致我们的应用无法正常运行,因此我们有必要深入探讨openssl_sign()函数签名失败的可能原因。

本文将围绕这一主题展开,分析可能导致openssl_sign()函数签名失败的几种常见原因。

一、参数传递错误在调用openssl_sign()函数时,可能会传递错误的参数,导致函数签名失败。

出现这种情况的原因可能有多种,例如传递的数据格式不正确、私钥文件路径错误等。

解决这种问题的关键在于仔细检查参数传递的正确性,并根据函数的规范进行调整。

二、密钥对不匹配openssl_sign()函数需要使用私钥对数据进行签名,而公钥用于验证签名。

如果在签名过程中使用了不匹配的密钥对,就会导致签名失败。

我们需要确保在调用openssl_sign()函数时,使用与数据对应的正确私钥进行签名。

三、未加载openssl扩展在PHP中使用openssl相关函数之前,需要确保openssl扩展已经正确加载。

如果未加载openssl扩展,就会导致openssl_sign()函数无法使用,从而导致签名失败。

解决这个问题的方法是在php.ini文件中启用openssl扩展,并重启PHP服务。

四、不支持的哈希算法在调用openssl_sign()函数时,需要指定用于签名的哈希算法。

如果指定的哈希算法不被支持,就会导致签名失败。

在调用openssl_sign()函数时,需要仔细选择合适的哈希算法,确保被签名的数据与哈希算法匹配。

五、内存不足openssl_sign()函数在签名大数据量时可能会占用大量内存,如果服务器的内存不足,就可能导致签名失败。

解决这个问题的方法是优化代码,减少签名的数据量,或者在服务器上增加内存。

六、证书格式错误在使用openssl_sign()函数进行签名时,需要确保使用的证书格式正确。

openssl生成签名与验证签名

openssl⽣成签名与验证签名 继上⼀篇,再写个⽣成签名和验证签名。

⼀般,安全考虑,⽐如接⼊⽀付平台时,请求⽅和接收⽅要互相验证是否是你,就⽤签名来看。

签名⽅式⼀般两种,对称加密和⾮对称加密。

对称加密就是双⽅互相有⼀个相同的key。

⾮对称⽐如就是公钥和私钥。

利⽤⾮对称openssl,下⾯是⽣成签名和验证签名的php⽰例。

<?php$arrParams = array('z' => 1,'a' => 2,'n' => "hello",'p' => "你好",'c' => 0,);$sortStr = createString($arrParams);// 有序⽣成字符串// echo $sortStr;die;$sha = sha1($sortStr);// sha1⽣成摘要// echo $sha;die;$private_key = '-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDKEquCt8WfdPFldkwy7GH3P274g4rxT2bFtaAlGKV03NVnZd/o8+NvHyScilc4Awpp+xv0EJl25qI+OxoFjl0dGFXf8P4E93onPeZYfYtynTkhsFZvCFYuf0GQW8o7M16d7WDeOKhyf9G/RWWTYYHwFO0uIPDXEgDHfLzf4NsZsQIDAQABAoGAUyLZQ19+Q/tl8Xt5IB5Ws9V6P25HNL6ZJtBxwbFhKTJN7ktgksP8l1Q1yN21woqltzKjrodBzERZDcddDloi/kFCSj0I5rmnfMRifo8PLbv5+F9knxAyBc8Na52wJLyv5+vqJM5cJ5OBxX055ipssQxBgno7OVJCgP8dY/EGnW0CQQDl9No8cmr3tha0I9KPHbibwrwT9THBB5oGu3PUqTlBuJixjxGgf0pUm+qHw/r3PG1jNqD9Xx5REoQNRrfQgLdPAkEA4PVjU8361m8weCUkm4jh/rsa8VYsiDEGCKEM6vmtaBYRlAXSeeb2P/2MNlwI9bMSjiQ0q/XftHdSz4N+5/Le/wJBALDGBW4qVuiN5e4dC6RRKLU0gfilqNXGzjUWrPhyDj3jdh4o6VgEAlQAd85ebfLZVQ3L1P5xvJB+N10tW+jAyikCQQCmjAYlnXIAIAG6cYVQwV7PwKaJ1krR6bmV2eY+cOs5DF2nQUg6iAv4BDcyZ6EahqFOKu/z/+zHJzBgAfKKtvzxAkBeT86uZ6tfTNLR72UbP0abWKfE65cTNHGQZKp3Df79Gx+UKVNiDHnfYmUu412QbpqDqi95XTDiPnry0fGqlzVJ-----END RSA PRIVATE KEY-----';// 获取私钥$pri_key_id = openssl_pkey_get_private($private_key);// 可⽤返回资源id Resource id//var_dump($pri_key_id);die;$re = openssl_sign($sha, $signature, $pri_key_id, OPENSSL_ALGO_SHA1);// var_dump($re);die;// $signature_base = base64_encode($signature); // ⽹络请求,post过去该base64字段,另⼀端解密// echo $signature_base;die;// -----------------验签----------------// 验签服务器拿到以上的参数(unset($signature)),同样⽣成有序串;sha1();$public_key = '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKEquCt8WfdPFldkwy7GH3P274g4rxT2bFtaAlGKV03NVnZd/o8+NvHyScilc4Awpp+xv0EJl25qI+OxoFjl0dGFXf8P4E93onPeZYfYtynTkhsFZvCFYuf0GQW8o7M16d7WDeOKhyf9G/RWWTYYHwFO0uIPDXEgDHfLzf4NsZsQIDAQAB-----END PUBLIC KEY-----';$pu_key = openssl_pkey_get_public($public_key);$verify = openssl_verify($sha, $signature, $pu_key, OPENSSL_ALGO_SHA1);if($verify == 1){echo 'ok';} else {echo 'fail';}/*** @param $param* @return bool|string* ⽣成有序字符串*/function createString($param){if (!is_array($param) || empty($param)){return false;}ksort($param);$concatStr = '';foreach ($param as$k=>$v) {$concatStr .= $k.'='.$v.'&';}$concatStr = rtrim($concatStr, '&'); return$concatStr;}。

OpenSSL椭圆曲线签名与校验(ECDSA)

OpenSSL: 椭圆曲线签名与校验 (ECDSA)/*目录:--------------------1. 简介2. 生成 ECDSA 密钥对3. 签名4. 校验*//*1. 简介--------------------对 PE 文件做 ECDSA 签名. 签名写入 PE 头部 DOS Stub代码后边. 使用的椭圆曲线是 FIPS 186-2 中的 P-192. 签名长度不超过 56 字节,强度和 RSA 1024 相当. *//*2. 生成 ECDSA 密钥对生成的私钥用 RC4 加密. 生成形式为 c 语言可用的形式.*/#include <stdio.h>#include <openssl/crypto.h>#include <openssl/bio.h>#include <openssl/evp.h>#include <openssl/x509.h>#include <openssl/ecdsa.h>#include <openssl/engine.h>#include <openssl/err.h>#include <openssl/rc4.h>#include <conio.h>#define MAXPASS 64#define PRIVKEY "static unsigned char privkey[%d] = {"#define PUBKEY "static const unsigned char pubkey[%d] = {"#define ENDKEY "\n};\n"int main(int argc, char* argv[]){RC4_KEY rc4;EC_KEY *ecdsa;char passbuf[MAXPASS + 3] = {MAXPASS};char *pass;byte buf[1024];byte *pp;int i,len;printf("Input password: ");pass = _cgets(passbuf);if (*pass == '\0' || passbuf[1] == 0){printf("NULL password\n");return -1;}RAND_seed(passbuf,sizeof(passbuf));if ( (ecdsa = EC_KEY_new()) == NULL){printf("EC_KEY_new\n");return 0;}if ((ecdsa->group = EC_GROUP_new_by_nid(NID_X9_62_prime192v1)) == NULL) {printf("EC_GROUP_new_by_nid\n");goto err;}if (!EC_KEY_generate_key(ecdsa)){printf("EC_KEY_generate_key error\n");goto err;}/** 生成 RC4 加密的ECDSA私钥*/pp = buf;len = i2d_ECPrivateKey(ecdsa,&pp);if (!len){goto err;}RC4_set_key(&rc4,strlen(pass),(byte*)pass);RC4(&rc4,len,buf,buf);printf(PRIVKEY,len);for (i=0; i<len; i++){if ( !(i % 8) )printf("\n");printf("0x%02X , ",buf);}printf(ENDKEY);/** 生成ECDSA公钥*/pp = buf;len = ECPublicKey_get_octet_string(ecdsa,&pp);if (!len){goto err;}printf(PUBKEY,len);for (i=0; i<len; i++){if ( !(i % 8) )printf("\n");printf("0x%02X , ",buf);}printf(ENDKEY);err:EC_KEY_free(ecdsa);return 0;}/*3. 签名-------------------签名时需要输入私钥密码 (最长 512 位).*/#include <openssl/crypto.h>#include <openssl/bio.h>#include <openssl/evp.h>#include <openssl/x509.h>#include <openssl/ecdsa.h>#include <openssl/engine.h>#include <openssl/err.h>#include <openssl/sha.h>#include <openssl/rc4.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <io.h>#include <windows.h>#include <commdlg.h>#include "resource.h"typedef unsigned char byte;#define MAXSIGLEN 128#define MAXPASS 64#define MAGIC_CHAR 0x27static char password[MAXPASS];static RC4_KEY key;/** RC4 加密过的ECDSA私钥 ()*/static unsigned char privkey[] = {0xBE , 0x5E , 0x1D , 0x8F , 0x79 , 0xBA , 0xC7 , 0x2B , 0x32 , 0x9D , 0x4A , 0xFC , 0xE7 , 0x62 , 0x24 , 0x8C , 0x84 , 0x88 , 0x32 , 0x6F , 0x4C , 0x5B , 0x32 , 0xEA , 0x46 , 0x97 , 0x71 , 0x83 , 0x84 , 0x3D , 0x91 , 0x79 , 0x4D , 0x17 , 0xB1 , 0x28 , 0xED , 0x39 , 0xBF , 0xDF , 0xDD , 0xF2 , 0x93 , 0x88 , 0xBF , 0xFD , 0x4D , 0x02 , 0xC7 , 0x1A , 0x22 , 0xAB , 0x41 , 0x41 , 0x9F , 0x63 , 0x26 , 0x7E , 0x49 , 0x08 , 0x7F , 0xB0 , 0xE3 , 0xB9 , 0xDB , 0xC4 , 0x04 , 0xE9 , 0x01 , 0xB8 , 0xC1 , 0x71 , 0x93 , 0xC6 , 0xD4 , 0x83 , 0xB3 , 0x08 , 0x28 , 0x18 , 0xE1 , 0x4C , 0xE1 , 0xD7 , 0x0C , 0x66 , 0x77 , 0x3E , 0x65 , 0x2F , 0x12 , 0xD3 , 0x2F , 0xD4 , 0xC3 , 0xB4 , 0x99 , 0xA2 , 0xF5 , 0x57 , 0x59 , 0xA1 , 0x20 , 0x81 , 0xEB , 0x3F , 0xCF , 0x46 , 0xD2 , 0x45 , 0x71 , 0x06 , 0x9C , 0x5F , 0x60 , 0x2E , 0x68 , 0xFB , 0x6C , 0xA4 , 0xC8 , 0x94 , 0x72 , 0xA3 , 0x3B , 0xE0 , 0x10 , 0xB9 , 0x1B , 0xAE , 0xFE , 0xD4 , 0x58 , 0x1C , 0xA9 , 0x80 , 0x0F , 0xF0 , 0x55 , 0xDC , 0xC6 , 0x58 , 0xE0 , 0x5D , 0x83 , 0xBB , 0x27 , 0x82 , 0x7E , 0xA1 , 0xF5 , 0x10 , 0x2E , 0x18 , 0x9A , 0xDA , 0x61 , 0x3B , 0xD2 , 0xA2 , 0xAB , 0x45 , 0x63 , 0xBD , 0x89 , 0xAD , 0xFB , 0x4E ,0x2E , 0x6D , 0x23 , 0x4A , 0x55 , 0x57 , 0x28 , 0x1A ,0xE5 , 0x5B , 0xC3 , 0x62 , 0x3B , 0x6F , 0xA5 , 0x96 ,0x72 , 0xBD , 0x16 , 0x36 , 0xC4 , 0xB9 , 0x2B , 0x31 ,0xE6 , 0x3B , 0x78 , 0xF0 , 0x2C , 0xBE , 0x4A , 0x70 ,0xA0 , 0xA1 , 0x5E , 0x38 , 0x4A , 0x3F , 0xFE , 0x79 ,0xD4 , 0xCF , 0x0C , 0x70 , 0x1B , 0xD5 , 0xE5 , 0x54 ,0x52 , 0x44 , 0x1A , 0x47 , 0xFD , 0x59 , 0x81 , 0xBF ,0xAE , 0x0C , 0xF4 , 0xDB , 0xC2 , 0x19 , 0xAC , 0xA9 ,0x2F , 0x90 , 0x31 , 0xEC , 0xEA , 0xDD , 0xCE , 0x5F ,0xA8 , 0xA7 , 0xEE , 0x79 , 0x1C , 0x20 , 0x95 , 0x93 ,0x22 , 0x61 , 0xA2 , 0x41 , 0x40 , 0xCF , 0x26 , 0xF4 ,0x73 , 0xFE , 0xD8 , 0x23 , 0x12 , 0x81 , 0x42 , 0x6D ,0x32 , 0xC2 , 0xD0 , 0x64 , 0xF2 , 0x02 , 0x0A , 0x22 ,0xFE , 0x20 , 0xB3 , 0x25 , 0x29 , 0x7B , 0x78 , 0xFA ,0x0D , 0x9B , 0x95 , 0x61 , 0xF5 , 0x40 , 0x1B , 0x43 ,0xEC , 0x7D , 0xEB , 0x61 ,};static const unsigned char dos[] = {0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x69, 0x50,0x42, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64,0x2E, 0x20, 0x0D, 0x0D, 0x0A, 0x24, MAGIC_CHAR,};/** ECDSA 签名*/static unsigned int sign(byte *sig,const byte *buf,int len){unsigned int siglen = MAXSIGLEN;EC_KEY *ecdsa = NULL;unsigned char *pp = (unsigned char*)privkey;RAND_seed(buf, len);/** 解密私钥*/RC4(&key,sizeof(privkey),privkey,privkey);ecdsa = d2i_ECPrivateKey(&ecdsa, (const unsigned char**)&pp, sizeof(privkey));ZeroMemory(privkey,sizeof(privkey));if ( ecdsa == NULL){MessageBox(NULL,"Can't restore private key","Sign",MB_ICONERROR);return 0;}if (!ECDSA_sign(0,buf, len, sig,&siglen,ecdsa)){MessageBox(NULL,"Sign error","Sign",MB_ICONERROR);EC_KEY_free(ecdsa);return 0;}EC_KEY_free(ecdsa);return siglen;}static BOOL GetFileName(char *sFile){OPENFILENAME ofn;ZeroMemory(&ofn, sizeof(ofn));ofn.lStructSize = sizeof(ofn);ofn.lpstrFile = sFile;ofn.nMaxFile = MAX_PATH;ofn.lpstrFilter = "EXE/DLL/OCX files\0*.exe;*.dll;*.ocx\0All\0*.*\0";ofn.lpstrTitle = TEXT("Please Select a File to sign");ofn.lpstrInitialDir = ".";ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY;return GetOpenFileName(&ofn);}INT_PTR CALLBACK DlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {if(uMsg == WM_INITDIALOG){SetFocus(GetDlgItem(hwndDlg,IDC_PASSWORD));}else if(uMsg == WM_COMMAND){if( wParam == IDOK){GetDlgItemText(hwndDlg,IDC_PASSWORD,password,MAXPASS);if (password[0] == '\0'){MessageBeep(MB_ICONASTERISK);SetFocus(GetDlgItem(hwndDlg,IDC_PASSWORD));return TRUE;}else{EndDialog(hwndDlg,0);}}}else if( uMsg == WM_CLOSE ){EndDialog(hwndDlg,0);}return 0;}int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){int len;byte sig[MAXSIGLEN];unsigned int siglen;int fd;byte md[SHA_DIGEST_LENGTH];char buf[1024];SHA_CTX ctx;char sFile[MAX_PATH] = {0};/** 得到要签名的文件名*/if (!GetFileName(sFile)){return -1;}if ((fd = open(sFile,O_RDWR | O_BINARY)) < 0){MessageBox(NULL,"Can't open file for read-write","Open",MB_ICONERROR);return -1;}/** 检验文件*/if ( (len = read(fd,buf,0x40)) != 0x40 ){MessageBox(NULL,"Read error","Read",MB_ICONSTOP);goto out;}if (buf[0] != 'M' || buf[1] != 'Z'){MessageBox(NULL,"Not a valid PE file!","Sign",MB_ICONSTOP);goto out;}if ( *(unsigned int *)(buf + 0x3C) < 0xA0){MessageBox(NULL,"No enough file space to write signature","Sign",MB_ICONSTOP);goto out;}/** 计算 SHA1*/SHA1_Init(&ctx);SHA1_Update(&ctx,buf,len);lseek(fd,0xA0L,SEEK_SET);while ( (len = read(fd,buf,sizeof(buf))) > 0){SHA1_Update(&ctx,buf,len);}if (len == -1){MessageBox(NULL,"Read error","Error",MB_ICONERROR);goto out;}ZeroMemory(md,sizeof(md));SHA1_Final(md,&ctx);/** 输入解密口令*/ZeroMemory(password,MAXPASS);DialogBox(hInstance,MAKEINTRESOURCE(IDD_PASSWORD),NULL,(DLGPROC)DlgProc);if (password[0] == '\0'){MessageBox(NULL,"You must input password!","Error",MB_ICONSTOP);goto out;}RC4_set_key(&key,strlen(password),(const byte*)password);ZeroMemory(password,MAXPASS);/** ECDSA sign*/{siglen = sign(sig,md,SHA_DIGEST_LENGTH);if (siglen){/** Write*/lseek(fd,0x40L,SEEK_SET);write(fd,dos,sizeof(dos));write(fd,(byte*)&siglen,1);write(fd,sig,siglen);MessageBox(NULL,"File signed","Ok",MB_OK);}}out:close(fd);return 0;}/*4. 校验-------------------校验不需要输入密码.*/#include <openssl/crypto.h>#include <openssl/bio.h>#include <openssl/evp.h>#include <openssl/x509.h>#include <openssl/ecdsa.h>#include <openssl/engine.h>#include <openssl/err.h>#include <openssl/sha.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <io.h>#include <windows.h>#include <commdlg.h>typedef unsigned char byte;#define MAXSIGLEN 64#define MAGIC_CHAR 0x27/** ECDSA 公钥*/static const unsigned char pubkey[] = {0x04 , 0xDA , 0x4C , 0x77 , 0xEB , 0x7A , 0x8C , 0x12 , 0x87 , 0xF3 , 0x6C , 0x10 , 0x87 , 0xA1 , 0xB1 , 0x2D , 0x96 , 0xE6 , 0x85 , 0xE0 , 0x40 , 0xD0 , 0x19 , 0x14 , 0xE3 , 0x1F , 0xF0 , 0x1A , 0x76 , 0x8D , 0x3A , 0x5D , 0x57 , 0x33 , 0xE6 , 0xD5 , 0x5D , 0x23 , 0x75 , 0x1E , 0x54 , 0x60 , 0x67 , 0xC9 , 0xA9 , 0x60 , 0x74 , 0xC5 , 0x3F ,};/** DOS stub 代码*/static const unsigned char dos[] = {0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x69, 0x50,0x42, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64,0x2E, 0x20, 0x0D, 0x0D, 0x0A, 0x24, MAGIC_CHAR,};/** 校验 ECDSA 签名*/static int verify(const byte *sig,int siglen,const byte *buf,int buflen){int ret;EC_KEY *pub = NULL;byte *pp = (byte*)pubkey;if ( (pub = EC_KEY_new()) == NULL){return 0;}if ((pub->group = EC_GROUP_new_by_nid(NID_X9_62_prime192v1)) == NULL){EC_KEY_free(pub);return 0;}pub = ECPublicKey_set_octet_string(&pub,(const byte**)&pp,sizeof(pubkey));if (pub == NULL){EC_KEY_free(pub);return 0;}ret = ECDSA_verify(0,(const byte*)buf, buflen, sig, siglen,pub);EC_KEY_free(pub);return ret == 1 ? 1 : 0;}static BOOL GetFileName(char *sFile){OPENFILENAME ofn;ZeroMemory(&ofn, sizeof(ofn));ofn.lStructSize = sizeof(ofn);ofn.lpstrFile = sFile;ofn.nMaxFile = MAX_PATH;ofn.lpstrFilter = "EXE/DLL/OCX files\0*.exe;*.dll;*.ocx\0All\0*.*\0";ofn.lpstrTitle = TEXT("Please Select a File to verify");ofn.lpstrInitialDir = ".";ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_READONLY;return GetOpenFileName(&ofn);}int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){int len;byte sig[MAXSIGLEN];unsigned int siglen = 0xFF;int fd;byte md[SHA_DIGEST_LENGTH];char buf[1024];SHA_CTX ctx;char sFile[MAX_PATH] = {0};if (!GetFileName(sFile)){return -1;}if ((fd = open(sFile,O_RDONLY | O_BINARY)) < 0){MessageBox(NULL,"Can't open file for read","Open",MB_ICONERROR);return -1;}/** 读入签名并检查*/lseek(fd,0x40L,SEEK_SET);if ( (len = read(fd,buf,0x60)) != 0x60){MessageBox(NULL,"Read error","Read",MB_ICONSTOP);close(fd);return -1;}if (memcmp(buf,dos,sizeof(dos)) ||(byte)buf[sizeof(dos) - 1] != MAGIC_CHAR ||buf[sizeof(dos)] > MAXSIGLEN){MessageBox(NULL,"Not signed or incorrect!","Verify",MB_ICONSTOP);close(fd);return -1;}siglen = buf[sizeof(dos)];memcpy(sig,buf + sizeof(dos) + 1,siglen);/** 计算 SHA1*/SHA1_Init(&ctx);lseek(fd,0L,SEEK_SET);if ( (len = read(fd,buf,0x40)) != 0x40){MessageBox(NULL,"Read error","Read",MB_ICONSTOP);close(fd);return -1;}SHA1_Update(&ctx,buf,len);lseek(fd,0xA0L,SEEK_SET);while ( (len = read(fd,buf,sizeof(buf))) > 0){SHA1_Update(&ctx,buf,len);}if (len == -1){MessageBox(NULL,"Read error","Error",MB_ICONERROR);close(fd);return -1;}close(fd);memset(md,0,sizeof(md));SHA1_Final(md,&ctx);if ( verify(sig,siglen,md,SHA_DIGEST_LENGTH) )MessageBox(NULL,"Verify Ok!","Verify",MB_OK);elseMessageBox(NULL,"Verify Error!","Verify",MB_ICONERROR);return 0;}????????。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C++基础:OpenSSL常用函数(签名与验证)
OpenSSL中的验证是先对原始数据计算摘要, 再对摘要进行私钥加密. 验证的过程是对原始消息计算摘要,解密验证值, 和摘要对比是否一致.如果一致, 说明验证有效:否则,则认为原文或验证值已经被篡改.
函数介绍:
因为要先对原始数据计算摘要, 所以在计算摘要时用的函数是计算摘要的函数一样. 最后在结束函数中进行验证或验证. 为了方便描述, OpenSSL对计算摘要函数进行了宏定义封装.下边是函数定义:
1、签名初始化函数
#define EVP_SignInit_ex(a, b, c) EVP_DigestInit_ex(a, b, c)
Int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *imp1);
2、签名更新函数
#define EVP_SignUpdate(a, b, c) EVP_DigestUpdate(a, b, c)
Int EVP_DigestUpdate(EVP_MD_CTX *ctx, const *d, size_t cnt);
3、签名结束函数
Int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKey pkey);
功能:计算签名结束,输出签名值。

参数说明:
Ctx:[IN]上下文变量
Md:[OUT] 签名结果输出值的指针 s:[OUT] 签名的长度
Pkey:[IN] 签名的私钥。

(*后面有私钥的计算过程)
4、验证初始化函数 (* 跟签名调用同一个函数)
#define EVP_VerifyInit_ex(a, b, c) EVP_DigestInit_ex(a, b, c)
Int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *imp1);
5、验证更新函数(* 跟签名调用同一个函数)
#define EVP_VerifyUpdate(a, b, c) EVP_DigestUpdate(a, b, c)
Int EVP_DigestUpdate(EVP_MD_CTX *ctx, const *d, size_t cnt);
6、验证结束函数
Int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKey pkey);
功能:计算验证结束,考试大提示输出验证值。

参数说明:
Ctx:[IN]上下文变量
sigbuf:[IN] 签名值 siglen:[IN] 签名的长度
Pkey:[IN] 验证签名的公钥。

计算私钥过程:直接写代码出来(*下面的代码如果按百分算的话,最多只能得三十分,所以不要照搬, 我这么写只是想把过程说得简单清楚点)
RSA rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);//产生一个1024位的RSA密钥
EVP_PKEY *evpKey = EVP_PKEY_new(); //新建一个EVP_PKEY变量
EVP_PKEY_set1_RSA(evpKey, rsa); //保存RSA结构体到EVP_PKEY结构体
//完成任务后面就可以用evpKey来签名了。

1 2。

相关文档
最新文档