密码学
密码学家研究的主要技术
(1) 对称密码
(2) 公钥密码
(3) 单向散列函数
(4) 消息认证码
(5) 数字签名
(6) 伪随机数生成器
可用如下图示解释

加密算法 分对称加密算法 与 非对称加密算法。
| 对称分组密码 | 非对称加密算法 |
|
数据加密标准(Data Encryption Standard, DES) 三重数据加密标准(Triple DES, 3DES) 高级加密标准(Advanced Encryption Standard, AES) |
RSA Diffie-Hellman DSA ECC SM2 |
RSA 、ECC既可以用于加/解密数据,也可以用于密钥交换,也可以用于数字签名。
DH算法一般来说只能用于密钥交换。
DSA算法则是专用于数字签名的算法。
SM2国标算法
对称加密 模型

为解决密钥配送的问题
* 通过事先共享密钥来解决
* 通过密钥分配中心来解决
* 通过Diffie-Hellman密钥交换来解决
* 通过公钥密码来解决
非对称密钥算法
RSA 算法一般用来
* 密钥交换
* 数字签名
也可以用于加密数据,因加密速度慢,一般不用做大量的数据加密。
使用openssl生成RSA密钥
参考链接 https://www.openssl.org/docs/manmaster/man1/genrsa.html
openssl genrsa
[-help] 打印帮助信息
[-out filename] -out 输出文件名
[-passout arg] -passout 加密RSA密钥
[-aes128] [-aes192] [-aes256] [-aria128] [-aria192] [-aria256] [-camellia128] [-camellia192] [-camellia256] [-des] [-des3] [-idea] 加密RSA密钥的算法
[-f4] [-3] 指数选项 -f4(值为 65537, 默认) 或 3(值为3)
[-rand file...] [-writerand file] [-engine id] [-primes num]
[numbits] 密钥长度
可配置参数
* RSA 输出密钥文件名
* RSA 密钥文件是否是加密
* RSA 密钥长度
例子1: 使用OpenSSL 生成RSA密钥
要求输出文件名为Client.Key
密钥长度为1024个字节
# openssl genrsa -out client.key 1024 Generating RSA private key, 1024 bit long modulus ..............++++++ ....++++++ e is 65537 (0x10001)
查看生成的RSA文件
# cat client.key -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDLUzbPSNQOC25Idro5MTud9Wv+JRBaZDQt5/Ue2E5+icpGfKgz MLjj7FHUA/AwlgoDiUF+MEgv7dvF623k1BeW8+/d/uMx9equZ4gkCkqgqIc02698 G1y1g/kszB9loRLQYVKaizg2Sb+ULeK01G7Yesn+tLNsmljjeh40qlp0AwIDAQAB AoGAM5cwwBXVoJ6r4/0kMWDZpLHiLgFPjfABAWjq3GG8QQVLauk0cJC7STHsbWR2 bI2ViuIn2RH9LxQmgKjFIJvkQ/foeFnT9VjIIdqUSu5Yy/RUCcPf9w3JE1cP+nMJ HAbbf8cS5UsQ3zs5RiuLVyBSwedp0jjVWopr4S7/tKc2bPkCQQD6TqR3o1ty7Moo xgUvARshvAnpaMFkqk4uyjEEzvHUOB4ds97ynjeCTZfFDQTr0WRkAdZvYbBAap1w v1a4bganAkEAz/MHVjJhVJ2CqXkEqQMSBHoRCc2+Jom+ewTe8aQvBExYqFprotoY NbXbBWBiRyQP4bRxM4OX/gRyusQ3W/YvRQJBAOrLCCWdW3PjQAKdNVGRJQUw4M9M T1SBGBN14CNVh6x882sDRZep6AHXjQzvGHWoFhZlTuNt7CmQmJyhLtSTiLMCQQC9 /kgHw0QWMUs+WCmf2gROPtDuaiJ/x35Xm52undmvTan7N5H8WtOfzyXrhaKFaTdx epGrBWKLXbkNV1VVGlsZAkAm/MJ73VW/+yS8HYPLsM+EqbIqtIqrkW4n4LUex+hl 9VQEQRuj2IR6xYHhq83YDMQkVNq6FdFy4MDq9ucEnatE -----END RSA PRIVATE KEY-----
例子2:使用OpenSSL 生成加密RSA文件
要求
输出文件名为 clientenc.key
使用des3加密算法
密码为weiwei
密钥长度为1024位
# openssl genrsa -out clientenc.key -des3 -passout pass:weiwei 1024 Generating RSA private key, 1024 bit long modulus .........++++++ ...........................................................................................................++++++ e is 65537 (0x10001)
# cat clientenc.key -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,6D0FB82EE1B256FF 5lBP5/AG0YMBmx7Xg2YF2JgEZG8sXPqgViJ02R03p/YMMhtgFLm4UeBtp0Us56qd 0Uf/+i7f2yAtFKSPeu8sElp5daQvdmNokjbzYJDsdY2dmdp4Tr5cJvvLqw83y6xS tLdhZPCAgdvaSd8qld5zRU53f3A1UKaniqfaeYef6T6vsbwgjcxDYpp+bjMY6bZM zQuf0rg5D9ZaYhpKoZq8dtXPrPs/x6wiumjC6Ti3natcTl0DHwpn9bT2Ekiacx1W Z6RB3X8Ai7bTCTvTvN/pGxPg65y96wDkkgkiLqQiw3nxWK6xnBEk9BVoYsuQCt8y 0S81rZ3e44JNNAcCf/MXfOk2yRrXE3LLbODslRr81+uUe5quo+PAakYffU547a6j aY+q4GbsngMK6Gh8dDROF+ixsJo1ikZIrz4kODUmc+lII2tFACj5VS8x7v2ogJyN m2gvFlcskBSP9075Rp0nmrhGG7/FRZyRn02RPj8DhgiNSkWIZFfCLXw/GJ+4VqkE QkPrzt8sF0SgrRP+gPgb8koxHy7S5sEnRHhGkum477PcvVcawTaAcjgeeHzsQmz3 lp3NMZLCzQCBflHYJ8ZPsldjcYhOULjoHIKpCJ7VUgwTSDCkKyN6I9EQMUe1jiOV P8jQqRY/ZmZOaXdPWKcuH47bHiQe2IeUC6TwVBA6qanLm5O6A66TlMXVlAYX2j2e c95wqEtEamjBKPd6os5fcSorFFsqhpDdy35yvQNo6a+pU4/DK+B+0fm9KkaQPthZ OxfQWwWLVXpi/Z1EgnH0cgbt3gJjD/CoYV07pyRj5AxsZ3UGxG36WA== -----END RSA PRIVATE KEY-----
RSA 使用openssl库的实现
RSA 密钥包含三个部分:公钥指数, 私钥指数, 模数 e
第一步: 分别保存好三个数, 其中私钥指数与模数都是大素数
第二步: 构造公钥与私钥RSA结构
第三步: 利用构造的RSA结构的指针进行公钥加密-私钥解密或者
公钥解密-私钥加密
/* * file: genrsa.c * purpose: Example code for creating RSA key pairs * author: 06/29/2018 Qiwei * * gcc -o genrsa genrsa.c -lssl -lcrypto */ #include <stdio.h> #include <openssl/rsa.h> #include <openssl/pem.h> int main(int argc, char* argv[]) { int ret = 0; RSA *rsa = RSA_new(); BIGNUM *bn = BN_new(); BIO *bp_public = NULL; BIO *bp_private = NULL; int bits = 2048; /* RSA密钥长度 */ unsigned long e = RSA_F4; /* 模数e */ if (bn == NULL || rsa == NULL) { ret = 1; goto end; } /* 1. generate rsa key */ if (!BN_set_word(bn, e) || !RSA_generate_key_ex(rsa, bits, bn, NULL)) { ret = 1; goto end; } /* 2. save public key */ bp_public = BIO_new_file("public.pem", "w+"); ret = PEM_write_bio_RSAPublicKey(bp_public, rsa); if(ret != 1){ goto end; } /* 3. save private key */ bp_private = BIO_new_file("private.pem", "w+"); ret = PEM_write_bio_RSAPrivateKey(bp_private, rsa, NULL, NULL, 0, NULL, NULL); /* 4. free */ end: BIO_free_all(bp_public); BIO_free_all(bp_private); BN_free(bn); RSA_free(rsa); return (ret); }
Diffie-Hellman 算法
参考文档 https://www.openssl.org/docs/manmaster/man1/dhparam.html
ECC 算法

椭圆曲线上的离散对数问题:
已知
椭圆曲线E
椭圆曲线E上一点G(基点)
椭圆曲线E上的一点xG(x倍的G)
求解
x
ECC 优点
* 生成密钥速度更快
* 密钥内容更小
openssl ecparam [-help] [-inform DER|PEM] [-outform DER|PEM] 输入与输出格式,默认PEM [-in filename] [-out filename] 输入与输出文件名 [-noout] 不打印ec参数 [-text] 以文本方式打印ec参数 [-C] 以C函数方式打印参数
[-check] 验证ec参数 [-name arg] [-list_curves] [-conv_form arg] [-param_enc arg] [-no_seed] [-rand file...] [-writerand file] [-genkey] 生成ec密钥 [-engine id]
列表当前所支持 ec 长度
# openssl ecparam -list_curves secp256k1 : SECG curve over a 256 bit prime field secp384r1 : NIST/SECG curve over a 384 bit prime field secp521r1 : NIST/SECG curve over a 521 bit prime field prime256v1: X9.62/SECG curve over a 256 bit prime field
使用案例
openssl ecparam -out ecckey.pem -name prime256v1 -genkey
# cat ecckey.pem
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJqXNSvRphWnpKXg/RKGf5vzkb/emTaVIvWFiu8iK37uoAoGCCqGSM49
AwEHoUQDQgAExRqYLPjN9nIAkvJ+CoVS5tC3kKGels2hGfqMGUQvKOYQMAyF83BA
RqzhccdmPVaHa0LGgU6322M1t7BN+n5IAQ==
-----END EC PRIVATE KEY-----
/* * file: genecc.c * purpose: Example code for creating elliptic curve * author: 06/29/2018 Qiwei * * gcc -o genecc genecc.c -lssl -lcrypto */ #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/pem.h> #define ECCTYPE "prime256v1" int main(int argc, char* argv[]) { BIO *outbio = NULL; EC_KEY *myecc = NULL; EVP_PKEY *pkey = NULL; int eccgrp; int ret = 0; /* Create a EC key sructure, setting the group type from NID */ eccgrp = OBJ_txt2nid(ECCTYPE); myecc = EC_KEY_new_by_curve_name(eccgrp); /* For cert signing, we use the OPENSSL_EC_NAMED_CURVE flag*/ EC_KEY_set_asn1_flag(myecc, OPENSSL_EC_NAMED_CURVE); /* Create the public/private EC key pair here */ if (! EC_KEY_generate_key(myecc)) { goto end; BIO_printf(outbio, "Error generating the ECC key."); } /* * Converting the EC key into a PKEY structure let us * handle the key just like any other key pair. */ pkey=EVP_PKEY_new(); if (!EVP_PKEY_assign_EC_KEY(pkey,myecc)) { BIO_printf(outbio, "Error assigning ECC key to EVP_PKEY structure."); goto end; } /* * Now we show how to extract EC-specifics from the key */ myecc = EVP_PKEY_get1_EC_KEY(pkey); const EC_GROUP *ecgrp = EC_KEY_get0_group(myecc); /* Create the Input/Output BIO's */ outbio = BIO_new(BIO_s_file()); outbio = BIO_new_fp(stdout, BIO_NOCLOSE); /* * Here we print the key length, and extract the curve type. */ BIO_printf(outbio, "ECC Key size: %d bit\n", EVP_PKEY_bits(pkey)); BIO_printf(outbio, "ECC Key type: %s\n", OBJ_nid2sn(EC_GROUP_get_curve_name(ecgrp))); /* * Here we print the private/public key data in PEM format. */ if(!PEM_write_bio_PrivateKey(outbio, pkey, NULL, NULL, 0, 0, NULL)) { BIO_printf(outbio, "Error writing private key data in PEM format"); goto end; } if(!PEM_write_bio_PUBKEY(outbio, pkey)) { BIO_printf(outbio, "Error writing public key data in PEM format"); } end: EVP_PKEY_free(pkey); EC_KEY_free(myecc); BIO_free_all(outbio); return ret; }
DSA 算法
只能用于数据签名

浙公网安备 33010602011771号