bool rsaverify(const unsigned char *src,int src_len,unsigned char *sig,unsigned int sign_len,unsigned char *publicKey){ X509 * cert = NULL; EVP_PKEY * key = NULL; BIO *keybio ; keybio = BIO_new_mem_buf((unsigned char *)publicKey, strlen((char *)publicKey)); if (keybio==NULL) { printf( "Failed to create key BIO"); return 0; } //cert can't get !!! Here have a ghost!~!!!!!!!! /* cert = X509_new();*/ // d2i_X509(&cert, (const unsigned char **)&publicKey, -1); // cert = d2i_X509_bio(keybio, NULL); // if (cert ==NULL) // { // printf("Failed to get cert!!!\n"); // } // cert = PEM_read_bio_X509(keybio, NULL, NULL, NULL); /* key = X509_get_pubkey(cert);*/ RSA *rsa = createRSA(publicKey, 1); key = EVP_PKEY_new(); int err = EVP_PKEY_assign_RSA(key,rsa); // key = EVP_PKEY_new(); // key = d2i_PUBKEY_bio(keybio, NULL); EVP_MD_CTX * ctx = NULL; int size=0; if (key) { size = EVP_PKEY_size(key); } ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(ctx); EVP_VerifyInit_ex(ctx, EVP_sha1(), NULL); EVP_VerifyUpdate(ctx, src,src_len); int suc = EVP_VerifyFinal(ctx, sig, sign_len, key); EVP_PKEY_free(key); EVP_MD_CTX_cleanup(ctx); if (suc == 1) { return true; } else return false; } unsigned char *rsasign(unsigned char * privateKey, const unsigned char *plaintext, int plaintext_len, unsigned int *dst_len){ BIO *bio_private = NULL; RSA *rsa_private = NULL; bio_private = BIO_new_mem_buf(privateKey, strlen((char *)privateKey)); if (bio_private==NULL) { printf( "Failed to create key BIO"); return 0; } rsa_private = PEM_read_bio_RSAPrivateKey(bio_private, NULL, NULL, ""); EVP_PKEY *key = EVP_PKEY_new(); int err ; err= EVP_PKEY_assign_RSA(key,rsa_private); int size=0; if (err) { size = EVP_PKEY_size(key); } // key = d2i_PKCS8PrivateKey_bio(bio_private, NULL, NULL, ""); // int size = EVP_PKEY_size(key); EVP_MD_CTX *ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(ctx); EVP_SignInit_ex(ctx,EVP_sha1() , NULL); EVP_SignUpdate(ctx, plaintext,plaintext_len); unsigned char *md=(unsigned char *)malloc(size); unsigned int len = 0; EVP_SignFinal(ctx, md, &len, key); *dst_len = len; EVP_PKEY_free(key); EVP_MD_CTX_cleanup(ctx); return md; }
這裏面有兩個坑,一個是簽名算法,一個是pading,致使我跟java端對接不上。java
java代碼有不少pkcs8轉pkcs#1的方法,然而c++中我沒能轉換過來,這個坑估計要之後填了。算法
其次是在verify函數中,測試了四五種api經過字符串傳入key來獲取x509格式key的方法,最後才測試成功,爲嘛?不知道。。api
最後是關於 RSA_sign和RSA_verify 配對函數的使用,二者最終調用都是evp,然而簽名校驗不經過。此坑待填!函數
建立rsa測試
RSA * createRSA(unsigned char * key,int publictype) { RSA *rsa= NULL; BIO *keybio ; keybio = BIO_new_mem_buf(key, strlen((char *)key)); if (keybio==NULL) { printf( "Failed to create key BIO"); return 0; } if(publictype) { rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL); } else { rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL); } if(rsa == NULL) { printf( "Failed to create RSA by type %d", publictype); } return rsa; }
格式化傳入的純字符串key值編碼
//format the strkey to rsakey void completeKey(unsigned char* strPublicKey, unsigned char* PublicKey, unsigned int publictype ) { int nPublicKeyLen = strlen((char*) strPublicKey); //strPublicKey爲base64編碼的公鑰字符串 int line = 0; int i; unsigned char strheader[40]; unsigned char strend[40]; if (publictype) { strcpy((char *)strheader, "-----BEGIN PUBLIC KEY-----\n"); strcpy((char *)strend, "\n-----END PUBLIC KEY-----\n"); }else { strcpy((char *)strheader, "-----BEGIN RSA PRIVATE KEY-----\n"); strcpy((char *)strend, "\n-----END RSA PRIVATE KEY-----\n"); } int iheaderlength = strlen((char *)strheader); memcpy(PublicKey, strheader, iheaderlength); for(i = 64; i < nPublicKeyLen; i+=64) { if(strPublicKey[i] != '\n') { memcpy((void *)&PublicKey[line*64+iheaderlength+line], (void *)&strPublicKey[line*64], 64); memset((void *)&PublicKey[line*64+64+iheaderlength+line], 0x0a, 1); //"\n" } line++; i++; } memcpy((void *)&PublicKey[line*64+iheaderlength+line], (void *)&strPublicKey[line*64], strlen((char *)&strPublicKey[line*64])); memset((void *)&PublicKey[line*64+strlen((char *)&strPublicKey[line*64])+iheaderlength+line], 0x0a, 1); //"\n" memcpy((void *)&PublicKey[line*64+iheaderlength+line + strlen((char *)&strPublicKey[line*64])], strend, strlen((char *)strend)); }
代碼一直很爛,湊和看吧,擼了一天半時間,使用的openssl的lib庫,並且是64位,各類堆棧信息看不全,能力不足,只能本身一直跟着內存看hex格式是否正確,瞎了!code