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