[Computer and Network Security] Programming with OpenSSL
来源:互联网 发布:hp1010墨盒清零软件 编辑:程序博客网 时间:2024/05/01 10:39
零、SSL和OpenSSL
SSL是HTTPS(安全的HTTP)背后的安全协议,它可以保证在TCP上工作的任何协议的安全。OpenSSL是对SSL全功能的实现,包括TLS(传输层安全)。
当你要把BIGNUM保存在一个文件中或者通过socket连接传送时,你需要将BIGNUM转为二进制表现方式。
简单地,可以将BIGNUM转换成十进制或十六进制表达。
1.5 生成伪随机指数
BIGNUM *prime = BN_generate_prime();
关注:RSA的公钥加密,Diffie-Hellman的密钥管理,DSA的数字签名。
在BIGNUM上的公钥密码操作
Bob首先生成RSA密钥,例如1024位,指数为3.
Bob随后可以解密
RSA的填充机制:
RSA_PKCS1_PADDING:明文长度要小于RSA_size(rsa)-11
RSA_PKCS1_OAEP_PADDING:明文长度要小于RSA_size(rsa)-41
RSA_SSLV23_PADDING:很少用
RSA_NO_PADDING:假设调用者执行填充,明文长度必须等于RSA_size(rsa),不推荐使用。
你可以在命令行中生成参数并且将其保存在一个PEM文件中。
3.2 Diffie-Hellman in OpenSSL
头文件:#include <openssl/dh.h>
DH的结构体
%openssl dhparam -out dh1024.pem 1024
文件中读参数
头文件:<openssl/dsa.h>
发送者发送DSA参数(比如,1024位)
四、OpenSSL的哈希函数
头文件:#include <openssl/md5.h>
目标:认证一个通过公钥签名的CA发布的证书
主要思想:在命令行中生成证书,并且在程序中通过API来调用certs
第一步,我们需要一个CA,首先创建一个子签名的证书。
第二步,当用户想要应用证书时,CA会生成一个新的公钥和私钥对,相应的证书请求如下:
第三步,CA会基于请求生成一个证书
认证某证书是否被正确地创建,可运行如下命令:
六、在OpenSSL中使用Cert签名/认证的方法
签名的人:使用私钥去签名;发布公钥证书
认证的人:使用证书中的公钥去认证
这里我们证明EVP API的使用
EVP API提供了一个通用接口来进行密码openssl的给出。当你更改使用新的密码学算法时,你仅仅需要在初始化的过程中注册新的算法。
6.1 在Openssl中使用证书来签名
第一步,载入私钥文件
当文件被加密时,我们需要指定使用何种加密算法,为了防止麻烦,我们仅仅需要调用OpenSSL添加所有algorithm()来包含所有可能需要的密码和摘要算法。
第一步,在认证消息之前,我们需要先获得签名者的证书,证书中包含公钥。
SSL/TLS编程步骤
第1步,初始化SSL库,初始化所有的密码/哈希算法。
第2步,创建SSL上下文结构:指定SSL版本。
第3步,建立证书和密钥
SSL服务器:服务器自己的证书(强制的)和CA证书(可选)
SSL客户端:CA证书(强制的)用来认证服务器的证书和客户端自己的证书(可选)
第4步,建立证书认证
可以指定链长度(认证深度verify_depth)
客户端可以设置SSL_VERIFY_PEER来验证服务器的证书确实是CA发布
第5步,创建SSL结构和TCP/IP套接字并与其绑定
第6步,SSL握手
当客户调用SSL_connect()来触发
如果之前证书认证被指定,那么实际的认证工作在这里会执行
第7步,传输SSL数据
第8步,关闭SSL结构
OpenSSL的总结:
底层设计:BIGNUM:使用BIGNUM来建立你自己的密码学基元。
中层设计:密码学基元:使用不同的密码学基元组合成一个密码学系统。
高层设计:SSL编程,SSL实施的方法。
SSL是HTTPS(安全的HTTP)背后的安全协议,它可以保证在TCP上工作的任何协议的安全。OpenSSL是对SSL全功能的实现,包括TLS(传输层安全)。
OpenSSL综述:OpenSSL是一个开源的密码学函数的实现。它包括密码学函数的可执行命令和一个API库,程序员可以使用这个库来开发密码学程序。
一、BIGNUM
公钥密码学需要处理非常大的整数,标准的C数据类型是不够的。BIGNUM包对数字的上界实际上是没有限制的。
头文件:#include <openssl/bn.h>
1.1 初始化&撤销BIGNUM
BIGNUM static_bn,*dynamic_bn;/*initialize a static BIGNUM*/BN_init(&static_bn);/*allocate a dynamic BIGNUM*/dynamic_bn=BN_new();/*free the BIGNUMs*/BN_free(dynamic_bn);BN_free(&static_bn);1.2 复制BIGNUMS
当你复制一个BIGNUM对象时需要深拷贝
BIGNUM a,b,*c;BN_copy(&a,&b);/*copies b to a*/c = BN_dup(&b);/*creates c and initialize it to same value as b*/1.3 BIGNUM到二进制
当你要把BIGNUM保存在一个文件中或者通过socket连接传送时,你需要将BIGNUM转为二进制表现方式。
简单地,可以将BIGNUM转换成十进制或十六进制表达。
BIGNUM *num;/*converting from BIGNUM to binary*/len=BN_num_bytes(num);buf=(unsigned char*)calloc(len,sizeof(unsigned char));len=BN_bn2bin(num,buf);/*converting from binary to BIGNUM*/BN_bin2bn(buf,len,num);num=BN_bin2bn(buf,len,NULL);
1.4 模运算
BIGNUM *r,*g,*x,*p;BN_CTX *ctx=BN_CTX_new();/*store temporary results*//*..call BN_new() on r,g,x,p*//*r=g^x mod p*/BN_mod_exp(r,g,x,p,ctx);/*when done,free r,g,x,p and ctx*/BN_CTX保存操作的临时值,为了提高性能。
1.5 生成伪随机指数
BIGNUM *prime = BN_generate_prime();
二、OpenSSL中的对称密码
头文件:#include <openssl/aes.h>
找到被加密消息的实际长度,使其长度为128bits的倍数。
unsigned int message_len = strlen((char*)input_string)+1;//including '\0'unsigned encrypt_len = (message_len % AES_BLOCK_SIZE == 0)?message_len:(message_len/AES_BLOCK_SIZE+1)*AES_BLOCK_SIZE;定义密钥(假设128bits)
unsigned char key[16];AES aes;int ret = AES_set_encrypt_key(key,128,&aes);//ret<0->error定义IV
unsigned char iv[AES_BLOCK_SIZE];memset(iv,0,AES_BLOCK_SIZE);加密明文(注意iv会被更新)
AES_cbc_encrypt(input_string,encrypt_string,encrypt_len,&aes,iv,AES_ENCRYPT);解密密文,解密端必须同步iv和密钥,其中iv可以明文传输,key必须秘密传输
AES_set_decrypt_key(key,128,&aes);memset(iv,0,AES_BLOCK_SIZE);...AES_cbc_encrypt(encrypt_string,decrypt_string,encrypt_len,&aes,iv,AES_DECRYPT);三、OpenSSL中的公钥密码
关注:RSA的公钥加密,Diffie-Hellman的密钥管理,DSA的数字签名。
在BIGNUM上的公钥密码操作
typedef struct{BIGNUM *n;//public modulusBIGNUM *e;//public exponentBIGNUM *d;//private exponentBIGNUM *p;//secret prime factorBIGNUM *q;//...}RSA;3.1 RSA in OpenSSL
Bob首先生成RSA密钥,例如1024位,指数为3.
#include <openssl/rsa.h>RSA ×rsa = RSA_generate_key(1024,3,NULL,NULL);Bob把公钥传递给Alice
#include <openssl/bn.h>unsigned char* n_b = (unsigned char*)calloc(RSA_size(rsa),sizeof(unsigned char));unsigned char* e_b = (unsigned char*)calloc(RSA_size(rsa),sizeof(unsigned char));int n_size = BN_bn2bin(rsa->n,n_b);int b_size = BN_bn2bin(rsa->e,e_b);Alice从公共参数中构建RSA上下文
RSA *encrypt_rsa = RSA_new();encrypt_rsa->n = BN_bin2bn(n_b,n_size,NULL);encrypt_rsa->e = BN_bin2bn(e_b,b_size,NULL);Alice现在可以加密数据
unsigned char* encrypt_string=(unsigned char*)calloc(RSA_size(encrypt_rsa),sizeof(unsigned char));int encrypt_size = RSA_public_encrypt(strlen((char*)input_string),input_string,encrypt_string,encrypt_rsa,RSA_PKCS1_OAEP_PADDING);推荐使用RSA_PKCS1_OAEP_PADDING,输入信息块的尺寸必须比RSA(size)-41要小
Bob随后可以解密
unsigned char* decrypt_string = (unsigned char*)calloc(RSA_size(rsa),sizeof(unsigned char));int decrypt_size = RSA_private_decrypt(encrypt_size,encrypt_string,decrypt_string,rsa,RSA_PKCS1_OAEP_PADDING);在加密之前填充数据包:
RSA的填充机制:
RSA_PKCS1_PADDING:明文长度要小于RSA_size(rsa)-11
RSA_PKCS1_OAEP_PADDING:明文长度要小于RSA_size(rsa)-41
RSA_SSLV23_PADDING:很少用
RSA_NO_PADDING:假设调用者执行填充,明文长度必须等于RSA_size(rsa),不推荐使用。
你可以在命令行中生成参数并且将其保存在一个PEM文件中。
3.2 Diffie-Hellman in OpenSSL
头文件:#include <openssl/dh.h>
DH的结构体
typedef struct{BIGNUM *p; //prime numberBIGNUM *g; //generatorBIGNUM *pub_key; //public keyBIGNUM *pri_key; //private key}DH;在命令行中生成DH参数(例如指数p和生成器g)
%openssl dhparam -out dh1024.pem 1024
文件中读参数
#include <openssl/dh.h>#include <openssl/pem.h>FILE *fp = fopen("dh1024.pem","r");DH *dh1 = PEM_read_DHparams(fp,NULL,NULL,NULL);文件中没有密钥,你需要单独生成密钥
unsigned char* key1 = (unsigned char*)calloc(DH_size(dh1),sizeof(unsigned char));unsigned char* key2 = (unsigned char*)calloc(DH_size(dh2),sizeof(unsigned char));DH_compute_key(key1,dh2_pub_key,dh1);DH_compute_key(key2,dh1_pub_key,dh2);3.3 DSA in OpenSSL
头文件:<openssl/dsa.h>
发送者发送DSA参数(比如,1024位)
DSA *dsa = DSA_generate_parameters(1024,NULL,0,NULL,NULL,NULL);生成密钥
DSA_generate_key(dsa);对消息签名
unsigned char* sign_string = (unsigned char*)calloc(DSA_size(dsa),sizeof(unsigned char));int ret = DSA_sign(0,input_string,strlen((char*)input_string),sign_string,&sig_len,dsa);认证消息
int is_valid = DSA_verify(0,input_string,strlen((char*)input_string),sign_string,sig_len,dsa);is_valid=1意味着认证完成,0意味着错误签名。
四、OpenSSL的哈希函数
头文件:#include <openssl/md5.h>
MD5_CTX hash_ctx:MD5_Init(&hash_ctx);//initalizechar input_string[100];strcpy(input_string,"abcdefg");MD5_Update(&hash_ctx,input_string,strlen(input_string));//updateunsigned char hash_ret[16];MD5_Final(hash_ret,&hash_ctx);//compute the hash value五、OpenSSL中的证书
目标:认证一个通过公钥签名的CA发布的证书
主要思想:在命令行中生成证书,并且在程序中通过API来调用certs
第一步,我们需要一个CA,首先创建一个子签名的证书。
%openssl genrsa -aes128 -out cakey.pem 1024
%openssl req -x509 -newkey rsa:1024 -out cacert.pem -outform PEM -days 365 -key cakey.pem使用'-days'选项指定过期时间为1年,证书被编码为PEM格式,可以通过以下命令查看其内容
%openssl x509 -in cacert.pem -text -noout创建了两个文件:cakey.pem---CA的私钥;cacert.pem---CA的证书
第二步,当用户想要应用证书时,CA会生成一个新的公钥和私钥对,相应的证书请求如下:
%openssl genrsa -aes128 -out key.pem 1024
%openssl req -new -key key.pem -keyform PEM -out req.pem -outform PEM上面的命令当在证书发布时会用口令短语(passphrase)来加密私钥文件(key.pem),它会提示你输入口令短语。
第三步,CA会基于请求生成一个证书
%openssl ca -in req.pem -out cert.pem -config ca.conf注意在调用此命令之前,我们必须准备好两个文件:index.txt(可以是空的),和序列(存储一个数字,例如01)。私钥文件(key.pem)和证书(cert.pem)将会给用户。
认证某证书是否被正确地创建,可运行如下命令:
%openssl verify -CAfile cacert.pem cert.pem
六、在OpenSSL中使用Cert签名/认证的方法
签名的人:使用私钥去签名;发布公钥证书
认证的人:使用证书中的公钥去认证
这里我们证明EVP API的使用
EVP API提供了一个通用接口来进行密码openssl的给出。当你更改使用新的密码学算法时,你仅仅需要在初始化的过程中注册新的算法。
6.1 在Openssl中使用证书来签名
第一步,载入私钥文件
当文件被加密时,我们需要指定使用何种加密算法,为了防止麻烦,我们仅仅需要调用OpenSSL添加所有algorithm()来包含所有可能需要的密码和摘要算法。
#include <openssl/evp.h>#include <openssl/pem.h>...OpenSSL_add_all_algorithms();...//load the private keyFILE *fp = fopen("key.pem","r");EVP_PKEY *priv_key = PEM_read_PrivateKey(fp,NULL,NULL,(char*)"5470");fclose(fp);if (priv_key==NULL){fprintf(stderr,"cannot read private key.\n");exit(-1);}第二步,签名消息摘要,你不需要签名整个消息,仅仅需要签名消息摘要
int sig_len=128;//1024-bit keyunsigned char sign_string[128];EVP_MD_CTX evp_md_ctx;EVP_SignInit(&evp_md_ctx,EVP_sha1());EVP_SignUpdate(&evp_md_ctx,input_string,strlen((char*)input_string));if(EVP_SignFinal(&evp_md_ctx,sign_string,&sig_len,priv_key)==0){fprintf(stderr,"Unable to sign.\n");exit(-1);}6.2 在openssl中使用证书来认证
第一步,在认证消息之前,我们需要先获得签名者的证书,证书中包含公钥。
X509 *cert;EVP_PKEY *pub_key;FILE *fp=fopen("cert.pem","r");if((cert=PEM_read_X509(fp,NULL,NULL,NULL))==NULL){fprintf(stderr,"cannot read certfile\n");exit(-1);}fclose(fp);if((pub_key=X509_get_pubkey(cert))==NULL){fprintf(stderr,"cannot read X509's public key\n");exit(-1);}第二步,认证消息摘要
EVP_VerifyInit(&evp_md_ctx,EVP_sha1());EVP_VerifyUpdate(&evp_md_ctx,input_string,strlen((char*)input_string));if(EVP_VerifyFinal(&evp_md_ctx,sign_string,sig_len,pub_key)){printf("Verified\n");}else{printf("Wrong\n");}七、SSL/TLS编程
SSL/TLS编程步骤
第1步,初始化SSL库,初始化所有的密码/哈希算法。
第2步,创建SSL上下文结构:指定SSL版本。
第3步,建立证书和密钥
SSL服务器:服务器自己的证书(强制的)和CA证书(可选)
SSL客户端:CA证书(强制的)用来认证服务器的证书和客户端自己的证书(可选)
第4步,建立证书认证
可以指定链长度(认证深度verify_depth)
客户端可以设置SSL_VERIFY_PEER来验证服务器的证书确实是CA发布
第5步,创建SSL结构和TCP/IP套接字并与其绑定
第6步,SSL握手
当客户调用SSL_connect()来触发
如果之前证书认证被指定,那么实际的认证工作在这里会执行
第7步,传输SSL数据
第8步,关闭SSL结构
OpenSSL的总结:
底层设计:BIGNUM:使用BIGNUM来建立你自己的密码学基元。
中层设计:密码学基元:使用不同的密码学基元组合成一个密码学系统。
高层设计:SSL编程,SSL实施的方法。
0 0
- [Computer and Network Security] Programming with OpenSSL
- Network Security with OpenSSL [ILLUSTRATED]
- [Computer and Network Security] Firewall and NIDS
- [Computer and Network Security] Applied Cryptography
- [Computer and Network Security] Gaining Access using Network Attacks
- [Computer and Network Security] Large-Scale Network Attacks
- [Computer and Network Security] HTTP and Session Management
- Guide to Computer Network Security
- Computer Security and Cryptography
- Computer Security and Cryptography
- 下载:Network programming.NET with C# and VB.NET 2004
- Network Programming with IOCP and Thread Pool – Intro
- Mathematics for 3D Game Programming and Computer Graphics - Rotations with Quaternions
- Computer Science and Programming: Books and Resources
- Network Security Technologies and Solutions
- Cryptography And Network Security - notes
- Multiplayer and Network Programming (zz)
- FAQ - Multiplayer and Network Programming
- WebDriverWait
- ajax传递给后台数组参数方式
- 安卓修改过源码之后如何给生成的app进行系统签名
- PHP完整的MySQL数据库操作类
- Java开发必会的Linux命令
- [Computer and Network Security] Programming with OpenSSL
- 微信支付DEMO完整版
- spring--AspectJ的Execution表达式
- android Studio 加载git插件
- IMD 油墨
- 从框架到完整项目搭建,实战项目《约个球》(3)-为library引入超全的工具类
- AFNetworking
- HTTP详解
- Java读取文本文件中文乱码问题