非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例
RSA算法,在1977年由Ron Rivest、Adi Shamirh和LenAdleman,在美国的麻省理工学院开发完成。这个算法的名字,来源于三位开发者的名字。RSA已经成为公钥数据加密标准。
RSA属于公开密钥密码体制。公开密钥体制就是产生两把密钥,一把用于加密,一把用于解密,而且不能根据算法和其中的一把密钥,而去推出另外的一把密钥。在使用的时候,将公钥公开,对方用公开的公钥加密数据后,将密文发回,然后用另一把私钥进行解密,从而还原出明文。
RSA算法的数学基础是数论中的素数相关性质。RSA的算法如下:
(1)、找出两个数p和q,其中p与q都是比较大的素数,其中p不等于q,为了保证安全性,RSA中使用的素数都比较大,且对这两个数要进行严格的保密;
(2)、计算乘积n = p *q;
(3)、计算乘积f(p,q) =(p - 1) * (q - 1);
(4)、找到一个素数e,使1 < e< f(p,q),并且e与f(p,q)互素;
(5)、将(e, n)做公钥,对明文按公式C=p^e mod n进行加密;
(6)、计算私钥d=e^-1mod f(p,q);对密文按P = C^d mod n进行解密。
其中,e,n作为公钥公开,任何人都可以知道。而f(p,q)作为密钥,要进行保密。一旦f(p,q)被别人获取,那么该RSA算法就不再安全。并且RSA算法的安全性和p,q的长度直接相关,长度越长安全性越高。因此,实际应用中p,q的长度至少为512比特。具体实现原理下图所示。
RSA在加解密的运用中,公钥是公开的,即有很多人都能得到,第三方也很容易窃取到e和n的数值。所以破解的关键就在,从e和n这两个数值开始,想办法求出数值d,如果能够得到d的值,也就是能够找到私钥,那么就可以破解相应的信息,达到情报窃取的目的。RSA算法的安全性完全依赖于大数的分解。
优缺点:由于RSA算法的理论基础是大数的分集,它是公认的世界难题,这就为RSA的安全性作了保障,所以它在一定程度上能抵抗外界的各种攻击。RSA是公钥加密系统中使用最广的加密算法,也是第一个既可以用于数据加密,同时还可以用于数字签名的算法。它的缺点:由于没有直接产生大素数的技术,RSA算法密钥产生比较麻烦;其次,为保证安全性,n一般要达到1024bit,使加密解密运算代价很高,严重影响了其加密速度,因此RSA算法不适合用于加密数据量大的信息;随着保密级别的提高,密钥的长度也在随着增加。
RSA is vulnerable to timing attacks. In a setup where attackers can measure the timeof RSA decryption or signature operations, blinding must be used to protect theRSA operation from that attack. RSA_blinding_on(),RSA_blinding_off():protectthe RSA operation from timing attacks.
1. RSA_blinding_on():turnsblinding on for key B<rsa> and generates a random blinding factor.B<ctx> is B<NULL> or a pre-allocated and initializedB<BN_CTX>. The random number generator must be seeded prior to callingRSA_blinding_on().returns 1 on success, and 0 if an error occurred.
2. RSA_blinding_off():turnsblinding off and frees the memory used for the blinding factor.
3. RSA_check_key():validateprivate RSA keys. This function validates RSA keys. It checks that B<p>and B<q> are in fact prime, and that B<n = p*q>. It also checksthat B<d*e = 1 mod (p-1*q-1)>, and that B<dmp1>, B<dmq1> andB<iqmp> are set correctly or are B<NULL>. As such, this functioncan not be used with any arbitrary RSA key object, even if it is otherwise fitfor regular RSA operation. returns 1 if B<rsa> is a valid RSA key, and 0otherwise. -1 is returned if an error occurs while checking the key. Thisfunction does not work on RSA public keys that have only the modulus and publicexponent elements populated. It performs integrity checks on all the RSA keymaterial, so the RSA key structure must contain all the private key data too.
4. RSA_generate_key():generates akey pair and returns it in a newly allocated B<RSA> structure. Thepseudo-random number generator must be seeded prior to callingRSA_generate_key().The modulus size will be B<num> bits, and the publicexponent will be B<e>. Key sizes with B<num> E<lt> 1024should be considered insecure. The exponent is an odd number, typically 3, 17or 65537. A callback function may be used to provide feedback about the progressof the key generation. If key generation fails, RSA_generate_key() returnsB<NULL>. RSA_generate_key() goes into an infinite loop for illegal inputvalues.
5. RSA_set_ex_data():is used toset application specific data, the data is supplied in the B<arg>parameter and its precise meaning is up to the application. returns 1 onsuccess or 0 on failure.
6. RSA_get_ex_data():is used toretrieve application specific data. The data is returned to the application,this will be the same value as supplied to a previousB<RSA_set_ex_data()> call. returns the application data or 0 on failure.0 may also be valid application data but currently it can only fail if given aninvalid B<idx> parameter.
7. RSA_get_ex_new_index():returnsa new index or -1 on failure (note 0 is a valid index value).
8. RSA_new():allocate RSA objects.allocates and initializes an B<RSA> structure. It is equivalent to callingRSA_new_method(NULL).
9. RSA_free():free RSA objects. freesthe B<RSA> structure and its components. The key is erased before thememory is returned to the system.
10. RSA_padding_xxx_xxx(): these functionsare called from the RSA encrypt, decrypt, sign and verify functions. Normallythey should not be called from application programs. However, they can also becalled directly to implement padding for other asymmetric ciphers.
12. RSA_public_decrypt():ow levelsignature operations. recovers the message digest from the B<flen> byteslong signature at B<from> using the signer's public key B<rsa>.B<to> must point to a memory section large enough to hold the messagedigest (which is smaller than B<RSA_size(rsa) - 11>). B<padding> isthe padding mode that was used to sign the data. returns the size of the recoveredmessage digest.
13. RSA_public_encrypt():encryptsthe B<flen> bytes at B<from> (usually a session key) using thepublic key B<rsa> and stores the ciphertext in B<to>. B<to>must point to RSA_size(B<rsa>) bytes of memory. returns the size of theencrypted data (i.e., RSA_size(B<rsa>)).
14. RSA_private_decrypt():decryptsthe B<flen> bytes at B<from> using the private key B<rsa> andstores the plaintext in B<to>. B<to> must point to a memory sectionlarge enough to hold the decrypted data (which is smaller thanRSA_size(B<rsa>)). B<padding> is the padding mode that was used toencrypt the data. returns the size of the recovered plaintext.
15. RSA_set_default_method():makesB<meth> the default method for all RSA structures created later.B<NB>: This is true only whilst no ENGINE has been set as a default forRSA, so this function is no longer recommended.
16. RSA_get_default_method():returnsa pointer to the current default RSA_METHOD. However, the meaningfulness ofthis result is dependent on whether the ENGINE API is being used, so thisfunction is no longer recommended.
17. RSA_set_method():selectsB<meth> to perform all operations using the key B<rsa>. This willreplace the RSA_METHOD used by the RSA key and if the previous method wassupplied by an ENGINE, the handle to that ENGINE will be released during thechange. It is possible to have RSA keys that only work with certain RSA_METHODimplementations (eg. from an ENGINE module that supports embeddedhardware-protected keys), and in such cases attempting to change the RSA_METHODfor the key can have unexpected results.
18. RSA_get_method():returns apointer to the RSA_METHOD being used by B<rsa>. This method may or maynot be supplied by an ENGINE implementation, but if it is, the return value canonly be guaranteed to be valid as long as the RSA key itself is valid and doesnot have its implementation changed by RSA_set_method().
19. RSA_flags():returns theB<flags> that are set for B<rsa>'s current RSA_METHOD.
20. RSA_new_method():allocates andinitializes an RSA structure so that B<engine> will be used for the RSAoperations. If B<engine> is NULL, the default ENGINE for RSA operationsis used, and if no default ENGINE is set, the RSA_METHOD controlled byRSA_set_default_method() is used.
21. RSA_sign():signs the messagedigest B<m> of size B<m_len> using the private key B<rsa> asspecified in PKCS #1 v2.0. It stores the signature in B<sigret> and thesignature size in B<siglen>. B<sigret> must point to RSA_size(B<rsa>)bytes of memory.
22. RSA_verify():verifies that thesignature B<sigbuf> of size B<siglen> matches a given messagedigest B<m> of size B<m_len>. B<type> denotes the messagedigest algorithm that was used to generate the signature. B<rsa> is thesigner's public key.
23. RSA_sign_ASN1_OCTET_STRING():signsthe octet string B<m> of size B<m_len> using the private keyB<rsa> represented in DER using PKCS #1 padding. It stores the signaturein B<sigret> and the signature size in B<siglen>. B<sigret>must point to B<RSA_size(rsa)> bytes of memory.
24. RSA_verify_ASN1_OCTET_STRING():verifiesthat the signature B<sigbuf> of size B<siglen> is the DERrepresentation of a given octet string B<m> of size B<m_len>.B<dummy> is ignored. B<rsa> is the signer's public key.
25. RSA_size():getRSA modulus size. This function returns the RSA modulus size in bytes. It canbe used to determine how much memory must be allocated for an RSA encrypted value.
下面是测试用例代码:
1. cryptotest.h:
#ifndef _CRYPTOTEST_H_
#define _CRYPTOTEST_H_#include <string>using namespace std;typedef enum {GENERAL = 0,ECB,CBC,CFB,OFB,TRIPLE_ECB,TRIPLE_CBC
}CRYPTO_MODE;string DES_Encrypt(const string cleartext, const string key, CRYPTO_MODE mode);
string DES_Decrypt(const string ciphertext, const string key, CRYPTO_MODE mode);string RC4_Encrypt(const string cleartext, const string key);
string RC4_Decrypt(const string ciphertext, const string key);string MD5_Digest(const string cleartext);int GenerateRSAKey(string strKey[]);
//string RSA_Encrypt(string cleartext, string key);
//string RSA_Decrypt(string ciphertext, string key);
void RSA_test1(const string cleartext);
void RSA_test2(const string cleartext);#endif //_CRYPTOTEST_H_
2. rsatest.cpp:
#include "stdafx.h"
#include "cryptotest.h"
#include "openssl/err.h"
#include <iostream>using namespace std;#define KEY_LENGTH 2048
int padding = RSA_PKCS1_PADDING;
int encrypt_len = 0;
#define PUB_EXP 3
//#define PRINT_KEYS
//#define WRITE_TO_FILEint GenerateRSAKey(string strKey[])
{size_t pri_len; // Length of private keysize_t pub_len; // Length of public keychar *pri_key = NULL; // Private keychar *pub_key = NULL; // Public keyRSA* keypair = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL);BIO *pri = BIO_new(BIO_s_mem());BIO *pub = BIO_new(BIO_s_mem());PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);PEM_write_bio_RSAPublicKey(pub, keypair);pri_len = BIO_pending(pri);pub_len = BIO_pending(pub);pri_key = new char[pri_len + 1];pub_key = new char[pub_len + 1];BIO_read(pri, pri_key, pri_len);BIO_read(pub, pub_key, pub_len);pri_key[pri_len] = '\0';pub_key[pub_len] = '\0';strKey[0] = pub_key;strKey[1] = pri_key;//printf("\n%s\n%s\n", pri_key, pub_key);RSA_free(keypair);BIO_free_all(pub);BIO_free_all(pri);delete [] pri_key;delete [] pub_key;return 0;
}RSA* createRSA(unsigned char* key, int flag)
{RSA *rsa= NULL;BIO *keybio ;keybio = BIO_new_mem_buf(key, -1);if (keybio==NULL) {printf( "Failed to create key BIO");return 0;}if(flag)rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);elsersa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);if(rsa == NULL)printf( "Failed to create RSA");return rsa;
}int public_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
{RSA * rsa = createRSA(key, 1);int result = RSA_public_encrypt(data_len, data, encrypted, rsa, padding);return result;
}int private_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
{RSA * rsa = createRSA(key, 0);int result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);return result;
}int private_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
{RSA * rsa = createRSA(key, 0);int result = RSA_private_encrypt(data_len, data, encrypted, rsa, padding);return result;
}int public_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
{RSA * rsa = createRSA(key, 1);int result = RSA_public_decrypt(data_len, enc_data, decrypted, rsa, padding);return result;
}void printLastError(char *msg)
{char * err = (char*)malloc(130);;ERR_load_crypto_strings();ERR_error_string(ERR_get_error(), err);printf("%s ERROR: %s\n", msg, err);free(err);
}void RSA_test1(const string cleartext)
{//char plainText[2048/8] = "Hello this is Ravi"; //key length : 2048string plainText = cleartext;//下面的公钥和私钥是通过命令行方式获取的//char publicKey[]="-----BEGIN PUBLIC KEY-----\n"string publicKey = "-----BEGIN PUBLIC KEY-----\n" \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n" \"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n" \"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n" \"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n" \"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n" \"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n" \"wQIDAQAB\n" \"-----END PUBLIC KEY-----\n";//char privateKey[]="-----BEGIN RSA PRIVATE KEY-----\n"string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"\"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\"-----END RSA PRIVATE KEY-----\n";unsigned char encrypted[4098] = {};unsigned char decrypted[4098] = {};//int encrypted_length= public_encrypt((unsigned char*)plainText,strlen(plainText),(unsigned char*)publicKey,encrypted);int encrypted_length= public_encrypt((unsigned char*)plainText.c_str(), plainText.length(), (unsigned char*)publicKey.c_str(), encrypted);if (encrypted_length == -1) {printLastError("Public Encrypt failed ");exit(0);}printf("Encrypted length =%d\n", encrypted_length);int decrypted_length = private_decrypt(encrypted, encrypted_length, (unsigned char*)privateKey.c_str(), decrypted);if (decrypted_length == -1) {printLastError("Private Decrypt failed ");exit(0);}printf("Decrypted Text =%s\n", decrypted);printf("Decrypted Length =%d\n", decrypted_length);encrypted_length= private_encrypt((unsigned char*)plainText.c_str(), plainText.length(),(unsigned char*)privateKey.c_str(), encrypted);if(encrypted_length == -1) {printLastError("Private Encrypt failed");exit(0);}printf("Encrypted length =%d\n", encrypted_length);decrypted_length = public_decrypt(encrypted, encrypted_length, (unsigned char*)publicKey.c_str(), decrypted);if(decrypted_length == -1) {printLastError("Public Decrypt failed");exit(0);}printf("Decrypted Text =%s\n", decrypted);printf("Decrypted Length =%d\n", decrypted_length);
}void RSA_test2(const string cleartext)
{size_t pri_len; // Length of private keysize_t pub_len; // Length of public keychar *pri_key; // Private keychar *pub_key; // Public keychar msg[KEY_LENGTH/8]; // Message to encryptchar *encrypt = NULL; // Encrypted messagechar *decrypt = NULL; // Decrypted messagechar *err; // Buffer for any error messagesstring str;// Generate key pair//printf("Generating RSA (%d bits) keypair...", KEY_LENGTH);fflush(stdout);RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);// To get the C-string PEM form:BIO *pri = BIO_new(BIO_s_mem());BIO *pub = BIO_new(BIO_s_mem());PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);PEM_write_bio_RSAPublicKey(pub, keypair);pri_len = BIO_pending(pri);pub_len = BIO_pending(pub);pri_key = (char*)malloc(pri_len + 1);pub_key = (char*)malloc(pub_len + 1);BIO_read(pri, pri_key, pri_len);BIO_read(pub, pub_key, pub_len);pri_key[pri_len] = '\0';pub_key[pub_len] = '\0';#ifdef PRINT_KEYSprintf("\n%s\n%s\n", pri_key, pub_key);
#endif//printf("done.\n");// Get the message to encryptprintf("Message to encrypt: ");fgets(msg, KEY_LENGTH-1, stdin);msg[strlen(msg)-1] = '\0';//string msg = cleartext;//cout<<"length:"<<strlen(msg)<<endl;// Encrypt the messageencrypt = (char*)malloc(RSA_size(keypair));int encrypt_len;err = (char*)malloc(130);if((encrypt_len = RSA_public_encrypt(strlen(msg)+1, (unsigned char*)msg, (unsigned char*)encrypt, keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {//if((encrypt_len = RSA_public_encrypt(msg.length(), (unsigned char*)msg.c_str(), (unsigned char*)encrypt, keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {ERR_load_crypto_strings();ERR_error_string(ERR_get_error(), err);fprintf(stderr, "Error encrypting message: %s\n", err);goto free_stuff;}#ifdef WRITE_TO_FILE// Write the encrypted message to a fileFILE *out = fopen("out.bin", "w");fwrite(encrypt, sizeof(*encrypt), RSA_size(keypair), out);fclose(out);printf("Encrypted message written to file.\n");free(encrypt);encrypt = NULL;// Read it backprintf("Reading back encrypted message and attempting decryption...\n");encrypt = (char*)malloc(RSA_size(keypair));out = fopen("out.bin", "r");fread(encrypt, sizeof(*encrypt), RSA_size(keypair), out);fclose(out);
#endif// Decrypt itdecrypt = (char*)malloc(encrypt_len);//decrypt = new char[encrypt_len + 1];//memset(decrypt, encrypt_len+1, 0);if(RSA_private_decrypt(encrypt_len, (unsigned char*)encrypt, (unsigned char*)decrypt, keypair, RSA_PKCS1_OAEP_PADDING) == -1) {ERR_load_crypto_strings();ERR_error_string(ERR_get_error(), err);fprintf(stderr, "Error decrypting message: %s\n", err);goto free_stuff;}printf("Decrypted message: %s\n", decrypt);free_stuff:RSA_free(keypair);BIO_free_all(pub);BIO_free_all(pri);free(pri_key);free(pub_key);free(encrypt);free(decrypt);free(err);
}
3. main.cpp:
#include "stdafx.h"
#include "cryptotest.h"
#include <iostream>
#include <string>using namespace std;int main(int argc, char* argv[])
{//string strKey[2] = {};//[0]:public key; [1]:private key //GenerateRSAKey(strKey);//cout<<"public key:"<<endl<<strKey[0]<<endl;//cout<<"private key:"<<endl<<strKey[1]<<endl;string cleartext = "中国北京12345$abcde%ABCDE@!!!!";if (cleartext.length() > 256) {cout<<"cleartext too length!!!"<<endl;return -1;}RSA_test1(cleartext);//RSA_test2(cleartext);cout<<"ok!!!"<<endl;return 0;
}
RSA算法理论摘自:
1. 《基于DES_RSA加密算法的改进与实现》
2. 《DES和RSA混合加密算法的研究》
测试代码中:
1. RSA_test1中的代码主要来自于: http://hayageek.com/rsa-encryption-decryption-openssl-c/
2. RSA_test2中的代码主要来自于: https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/
GitHub:https://github.com/fengbingchun/OpenSSL_Test
相关文章:

依图科技CEO朱珑:“智能密度”对AI发展意味着什么?
8月9日,由中央网信办、工业和信息化部、公安部联合指导,厦门市政府主办的“中国人工智能峰会”于厦门召开。中国工程院院士、北京大学教授高文,依图科技创始人兼CEO朱珑博士等出席峰会并发表了主题演讲。当前,人工智能正在扮演越来…

Office 2016使用NTKO OFFICE控件提示“文件存取错误”的解决办法
2019独角兽企业重金招聘Python工程师标准>>> 之前使用NTKO,电脑安装的说OFFICE2007,但是前2天电脑固态硬盘坏了 ,重新安装了系统,安装的说win10和office2016,再访问网站使用ntko时,却提示“文件存取错误”&…
如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇《如何使用CCRenderTexture创建动态纹理》基础上,增加创建动态山丘,原文《How To Create A Game Like Tiny Wings with Cocos2D 2.X Part 1》,在这里继续以Cocos2d-x进行实现。有关源码、资源等在文章下面给出了地址。 步骤如下&…

腾讯优图开源业界首个3D医疗影像大数据预训练模型
整理 | Jane出品 | AI科技大本营(ID:rgznai100)近日,腾讯优图首个医疗AI深度学习预训练模型 MedicalNet 正式对外开源。这也是全球第一个提供多种 3D 医疗影像专用预训练模型的项目,将为全球医疗AI发展提供基础。许多研…

接口冲突的一种解决方法
问题描述:在一个大的项目中往往会包括很多模块,会有不同的部门或公司来负责实现某个模块,也有可能有第三方或客户的参与。假如他们都用到了某个开源软件,底层模块根据自身的需求对这个开源软件进行了修改或裁减。上层也用到了此开…

程序员:请你不要对业务「置之不理」
成长是条孤独的路,一个人会走得更快;有志同道合者同行,会走得更远。本篇内容整理自 21 天鲲鹏新青年计划线上分享内容。鲲鹏新青年计划是由 TGO 鲲鹏会组织的线上分享活动,希望能帮助更多同学一起学习、成长。12 月 28 日…

史上最简单的人脸识别项目登上GitHub趋势榜
来源 | GitHub Trending整理 | Freesia译者 | TommyZihao出品 | AI科技大本营(ID: rgznai100)导读:近日,一个名为 face_recognition 的人脸识别项目登上了 GitHub Trending 趋势榜,赚足了眼球。自开源至截稿࿰…

Centos 64位 Install certificate on apache 即走https协议
2019独角兽企业重金招聘Python工程师标准>>> 一: 先要apache 请求ssl证书的csr 一下是步骤: 重要注意事项 An Important Note Before You Start 在生成CSR文件时同时生成您的私钥,如果您丢了私钥或忘了私钥密码,则颁发 证书给您…

C/C++中“#”和“##”的作用和用法
在C/C的宏中,”#”的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。而”##”被称为连接符(concatenator),用来将两个子串Token连接为一个Token。注意这里连接…
国贫县山西永和:“一揽子”保险“保”脱贫
永和是吕梁山特困连片地区的深度贫困县,生产生活条件极差。 范丽芳 摄 永和是吕梁山特困连片地区的深度贫困县,生产生活条件极差。 范丽芳 摄 中新网太原1月16日电 题:国贫县山西永和:“一揽子”保险“保”脱贫 作者范丽芳 李海金…
内存泄漏检测工具VLD在VS2010中的使用举例
Visual LeakDetector(VLD)是一款用于Visual C的免费的内存泄露检测工具。它的特点有:(1)、它是免费开源的,采用LGPL协议;(2)、它可以得到内存泄露点的调用堆栈,可以获取到所在文件及行号;(3)、它可以得到泄露内存的完整…

天下武功,唯快不破,论推荐系统的“实时性”
作者 | 王喆转载自知乎王喆的机器学习笔记导读:周星驰著名的电影《功夫》里面有一句著名的台词——“天下武功,无坚不摧,唯快不破”。如果说推荐系统的架构是那把“无坚不摧”的“玄铁重剑”,那么推荐系统的实时性就是“唯快不破”…
新疆兵团开展迎新春“送文化下基层”慰问演出活动
演员表演舞蹈。 戚亚平 摄 演员表演舞蹈。 戚亚平 摄演员表演豫剧《花木兰》选段。 戚亚平 摄为物业公司员工送春联。 戚亚平 摄公安民警收到春联后留影。 戚亚平 摄走进退休职工家中表演节目。 戚亚平 摄为退休职工送春联。 戚亚平 摄 1月16日,2019年迎新春新疆生产…

Python爬取B站5000条视频,揭秘为何千万人为它流泪
作者 | Yura编辑 | 胡巍巍来源 | CSDN(ID:CSDNnews)导语:我们特邀作者Yura爬取B站5000条视频,为你揭秘电影《哪吒》的更多“优秀梗”,看完还能Get新技能,赶快往下滑吧。这个夏天,《哪…

父域与子域之的信任关系
搭了一个测试环境,做一个父、子域间信任关系的测试,过程如下:两台测试服务器,主域为primary.com,子域为child.primary.com客户机Clientpri加入父域,客户机Clientcli加入子域,父域中有一个用户为…

Ubantu安装maven
2019独角兽企业重金招聘Python工程师标准>>> 一、下载maven http://maven.apache.org/download.cgi 二、解压到指定目录 tar -xvf apache-maven-3.6.0-bin.tar.gz 三、添加环境变量 cd /etc vi profile 向其中添加 export M2_HOMEmaven所在目录 export M2$M2_HOME/b…

Leptonica在VS2010中的编译及简单使用举例
在tesseract-ocr中会用到leptonica库,这里对leptonica简单介绍下。Leptonica是一个开源的图像处理和图像分析库,它的license是BSD 2-clause。它主要包括的操作有:位图操作、仿射变换、形态学操作、连通区域填充、图像变换及像素掩模、融合、增…

IJCAI 2019精选论文一览,从底层到应用都有了
作者 | 神经小姐姐来源 | HyperAI超神经(ID: HyperAI)导语:为期一周的 IJCAI 第一天议程已经圆满结束。在前三天的工作坊上,全球各地人工智能行业人士,在此讨论 AI 在各个领域与方向的最新研究成果与未来动向。超神经特…

UITableView 添加长按手势UILongPressGestureRecognizer
2019独角兽企业重金招聘Python工程师标准>>> 给UITableView 添加长按手势,识别长按哪一行。 长按手势类UILongPressGestureRecognizer, 属性minimumPressDuration表示最短长按的时间 添加手势代码: UILongPressGestureRecogniz…

像我这种垃圾学校出来的人...【原话,不是我编的】
今天这标题,是咱们先行者课程的学生的原话,不是我编的,咱有截图为证,我这没别的意思,就是想说一下我自己的想法, 这种情况怎么办呢?也得生活啊,对吧,也不能人人都上清华北…

二维码Data Matrix简介及在VS2010中的编译
Data Matrix 二维条码原名Datacode,由美国国际资料公司(International Data Matrix, 简称ID Matrix)于1989年发明。Data-Matrix二维条码是一种矩阵式二维条码。Data Matrix符号由规则排列的深浅色正方形模块构成,每个正方形模块就是一个基本单元&#x…

一、数据库设计与性能优化--概述
前言我1998年第一次接触SQL Server 6.5 for Windows NT 4.0,当时的感觉就认为SQL Server只是一个功能强大的Excel文件。现在回想起来,当年抱着这样一种态度,我开发的那些应用程序应该是非常幼稚的,其性能可想而知。记得那时候随便…

第四范式戴文渊:AI落地,为什么不能照搬教科书?
“年少成名”、“天才”,在中国 AI 行业里用这两个词同时形容一个人的牛人不多,第四范式创始人戴文渊位列其中。在上海交通大学就读本科期间,戴文渊就带领三人团队夺得了 2005 年 ACM 的世界冠军和三个亚洲冠军,并担任ACM竞赛教练…

Kong Api 网关使用 docker 部署
Kong 镜像: https://hub.docker.com/_/kong 官网给定的用户安装手册上并没有设置 PG 的密码,导致如下问题无法启动 nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/kong/init.lua:277: [PostgreSQL error] failed to >retrieve server_version_num…

Windows7中搭建Android x86_64及armv8-a操作步骤
1. 从https://developer.android.com/tools/sdk/ndk/index.html 下载android-ndk-r10d-windows-x86_64.exe 和 android-ndk-r10d-linux-x86_64.bin; 2. 在Ubuntu1404 64位中通过终端安装ndkr10d:./android-ndk-r10d-linux-x86_64.bin ; 3.…

ContentResolver.query()—buildQueryString()
Cursor cursor context.getContentResolver().query(Sms.CONTENT_URI, new String[]{"thread_id from sms where type 3 group by thread_id—"}, // 可以这样使用。 null, null, null); 07-17 10:55:17.084: E/AndroidRuntime(30157): FATAL EX…

Room Database完全使用手册
前言 Android数据持久层直接使用SQLite很麻烦,Google官方推出了Room, Google对Room的定义: The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of …

wiki的使用
Wiki一词来源于夏威夷语的”weekee wee kee”,被译为”维基”或”维客”。Wiki是一种多人协作的写作编辑平台。在Wiki网站上,访问者可以修改、完善已经存在的页面,或者创建新内容。 可以利用”维基百科:沙盒”来练习如何编辑&…

GAMIT安装备忘
2019独角兽企业重金招聘Python工程师标准>>> 系统环境: VMware Workstation9 ubuntu 10.04 操作 1.安装VMware Workstation 参考: VMware Workstation下载:http://pan.baidu.com/share/link?shareid407480&uk258569718…

FreeType简介及在vs2010的编译使用
FreeType库是一个开源、高质量、可扩展、可定制、可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,包括点阵字、TrueType、OpenType、Type1、CID、CFF、Windows FON/FNT、X11 PCF等。 FreeType有两个License,一个是BSD-stype&…