非对称加密:即两端使用一对不同的密钥进行加密。
在非对称加密中,需要两对密钥,公钥和私钥。
公钥个私钥属于对立关系,一把加密后,只有另一把才可以进行解密。
- 公钥数据加密
数字证书内包含了公钥,在进行会话连接时,双方交换各自的公钥,保留自己的私钥。进行数据传输时,利用对方的公钥进行数据加密。加密后的数据只有对方的私钥才能进行解密。
- 私钥数字签名
私钥进行数据加密,所有人用公钥都能解密数据,但是加密后的数据却唯有私钥能生成。可以用于消息来源验证。将数据用私钥加密并明文告诉用户密文内容,用户进行公钥解密比较确认数据来源可靠。
在非对称加密算法中有RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。
其中RSA加密最为广泛利用,毫不夸张地说,只要有计算机网络的地方,就有RSA算法。
其原理为数论中一个公认的定论:两个大素数相乘非常容易,但是这个数要分解成二个质数的积,非常困难。
根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。
具体RSA加密算法在计算机网络中的运用方式和原理可以查看:OpenSSL - 网络安全之数据加密和数字证书
如何利用openssl命令行来生成证书和密钥可查看:OpenSSL - 利用OpenSSL自签证书和CA颁发证书
在使用OpenSSL进行RSA加密算法时,流程与上述理论流程保持一致。
- 生成密钥或读取密钥
- 根据需要选择签名还是加密
- 使用公钥进行数据加密
- 使用私钥进行数字签名
- 数据通过网络进行安全传输
- 对端进行解密获取明文
下面是OpenSSL的RSA加密算法对数据进行加密解密过程实现:
View Code1 #include <iostream> 2 #include <fstream> 3 #include <openssl/bn.h> 4 #include <openssl/rsa.h> 5 #include <openssl/pem.h> 6 7 #define DATA_BUFF_LENTH 1024 8 #define RSA_BIT 1024 9 10 using namespace std; 11 12 class File 13 { 14 public: 15 File(string strFilePath):m_strFilePath(strFilePath){}; 16 ~File(){}; 17 bool open(_Ios_Openmode opreator); 18 void close(); 19 void read(char* buff,int length); 20 private: 21 fstream m_file; 22 string m_strFilePath; 23 }; 24 25 bool File::open(_Ios_Openmode opreator) 26 { 27 m_file.open(m_strFilePath.c_str(),opreator); 28 if (m_file.fail()) //打开失败 29 { 30 cout<<"open file failure!"<<endl; 31 return false; 32 } 33 return true; 34 } 35 36 void File::close() 37 { 38 m_file.close(); 39 } 40 41 void File::read(char* buff,int length) 42 { 43 m_file.read(buff,length); 44 } 45 46 class RSAKey 47 { 48 public: 49 RSAKey(int rsabit,int bignum); 50 ~RSAKey(); 51 void UsePrivateRSAKeyDecode(char* dsc,char* src); //加密解密操作 52 void UsePublicRSAKeyEncode(char* dsc,char* src); 53 void printPublicKey(); //打印秘钥操作 54 void printPrivateKey(); 55 void exportPrivateKey(string fileName); //导出秘钥操作 56 void exportPublicKey(string fileName); 57 /* 58 We can also output the key into an encrypted PEM file. 59 60 And the APIs is easy to use. 61 62 PEM_write_bio_RSAPrivateKey 63 64 PEM_write_bio_RSAPublicKey 65 66 PEM_read_bio_RSAPrivateKey 67 68 PEM_read_bio_RSAPublicKey 69 */ 70 void importPrivateKey(string fileName); //导入秘钥操作,也可利用上述API通过证书导入秘钥,证书命令行生成和颁发签证 71 void importPublicKey(string fileName); 72 private: 73 BIGNUM* m_bigNum; 74 RSA* m_rsa; 75 int m_rsa_bit; 76 RSA* m_pubKey; 77 RSA* m_privateKey; 78 }; 79 80 RSAKey::RSAKey(int rsabit,int bignum) 81 { 82 m_rsa_bit = rsabit; 83 m_rsa = RSA_new(); 84 m_pubKey = RSA_new(); 85 m_privateKey = RSA_new(); 86 m_bigNum = BN_new(); 87 BN_set_word(m_bigNum,bignum); //设置大数 88 RSA_generate_key_ex(m_rsa,m_rsa_bit,m_bigNum,NULL); //生成密钥 89 } 90 91 RSAKey::~RSAKey() 92 { 93 RSA_free(m_rsa); 94 RSA_free(m_pubKey); 95 RSA_free(m_privateKey); 96 BN_free(m_bigNum); 97 } 98 99 void RSAKey::UsePrivateRSAKeyDecode(char* dsc,char* src) 100 { 101 int rsa_len = RSA_size(m_privateKey); 102 RSA_private_decrypt(rsa_len,(unsigned char *)src,(unsigned char*)dsc,m_privateKey,RSA_NO_PADDING); 103 } 104 105 void RSAKey::UsePublicRSAKeyEncode(char* dsc,char* src) 106 { 107 int rsa_len = RSA_size(m_pubKey); 108 RSA_public_encrypt(rsa_len, (unsigned char *)src,(unsigned char*)dsc,m_pubKey, RSA_NO_PADDING); 109 } 110 111 void RSAKey::printPublicKey() 112 { 113 RSA_print_fp(stdout,m_pubKey,11); 114 } 115 116 void RSAKey::printPrivateKey() 117 { 118 RSA_print_fp(stdout,m_privateKey,11); 119 } 120 121 void RSAKey::exportPrivateKey(string fileName) 122 { 123 FILE *ifile; 124 ifile = fopen(fileName.c_str(),"w"); 125 PEM_write_RSAPrivateKey(ifile,m_rsa, NULL, NULL, 0, NULL, NULL); 126 fclose(ifile); 127 } 128 129 void RSAKey::exportPublicKey(string fileName) 130 { 131 FILE *ifile; 132 ifile = fopen(fileName.c_str(),"w"); 133 PEM_write_RSAPublicKey(ifile,m_rsa); 134 fclose(ifile); 135 } 136 137 void RSAKey::importPrivateKey(string fileName) 138 { 139 FILE *ifile; 140 ifile = fopen(fileName.c_str(),"r"); 141 m_privateKey = PEM_read_RSAPrivateKey(ifile, NULL, NULL, NULL); 142 } 143 144 void RSAKey::importPublicKey(string fileName) 145 { 146 FILE *ifile; 147 ifile = fopen(fileName.c_str(),"r"); 148 m_pubKey = PEM_read_RSAPublicKey(ifile,NULL,NULL,NULL); 149 } 150 151 int main(int arc,char *arv[]) 152 { 153 RSAKey rsa(RSA_BIT,RSA_F4); 154 rsa.exportPrivateKey("private.key"); // 导出密钥 155 rsa.exportPublicKey("public.key"); 156 157 string strFilePath = arv[1]; 158 File ifile(strFilePath.c_str()); 159 ifile.open(ios::in); 160 161 char DataBuff[DATA_BUFF_LENTH]; 162 ifile.read(DataBuff,DATA_BUFF_LENTH); //读文件内容 163 ifile.close(); 164 165 rsa.importPublicKey("public.key"); //导入公钥 166 rsa.importPrivateKey("private.key"); //导入秘钥 167 168 rsa.printPrivateKey(); //打印秘钥信息 169 rsa.printPublicKey(); //打印公钥信息 170 171 cout<<"-----------------------------------"<<endl; 172 cout<<"source :"<<DataBuff<<endl; //源数据 173 cout<<"-----------------------------------"<<endl; 174 175 char enData[DATA_BUFF_LENTH]; 176 rsa.UsePublicRSAKeyEncode(enData,DataBuff); 177 cout<<"-----------------------------------"<<endl; 178 cout<<"encode :"<<enData<<endl; //加密数据 179 cout<<"-----------------------------------"<<endl; 180 181 char deData[DATA_BUFF_LENTH]; 182 rsa.UsePrivateRSAKeyDecode(deData,enData); 183 cout<<"-----------------------------------"<<endl; 184 cout<<"decode :"<<deData<<endl; //解密数据 185 cout<<"-----------------------------------"<<endl; 186 187 return 0; 188 }scons编译脚本如下:
1 Program('pubkey','rsa_genkey.cpp',LIBS = ['ssl','crypto'])
执行可执行文件,输入文件路径,即可查看到经过RSA加密后的数据内容和解密后的内容。
从证书中提取公钥加密与上述代码类似,替换相应API即可。
tips:本来把这篇OpenSSL的RSA加密算法和代码写好点的,但是由于最近时间越来越紧张。后续有机会在扩充吧。代码部分很多地方没有做异常判段和处理,只是保证了正常功能。
由于后面参与公司新的后台服务器架构开发,将会使用到RabbitMQ中间件,后续将不定期慢速更新RabbitMQ及后台架构设计相关博客,欢迎关注!