I am trying to develop a solution for license verification. Licenses are encoded on the server using the OpenSSL RSA_private_encrypt function.
For Mac OX X, I use RSA_public_decrypt and it works like a charm. On Windows, I have to use a very small bit of code, so I canβt communicate with OpenSSL or another library. And I have to use the MS Crypto API.
I spent several days trying to figure out what was wrong, but no luck. I can successfully import the public key, but here my success ends. I know that I need to change the byte order using CAPI, so this may not be a problem.
I tried everything including CryptVerifyMessageSignatureWithKey and CryptDecodeObject to load blob with different parameters, but still no luck.
It always ends with GetLastError() == CRYPT_E_ASN1_BADTAG , which I believe means that the BLOB is not formatted in ASN1 ... Google does not report anything about the output format RSA_private_encrypt ... so I got completely lost here.
Here is the OS X code based on OpenSSL:
void cr_license_init(const char* lic) { __cr_license_ = lic; unsigned char lic_encoded[CR_LIC_LEN]; BIO* b64 = BIO_new(BIO_f_base64()); BIO* licIn = BIO_new_mem_buf((void*)lic, -1); licIn = BIO_push(b64, licIn); if(BIO_read(licIn, lic_encoded, CR_LIC_LEN) == CR_LIC_LEN) { const unsigned char* key_data = license_pub_der; RSA* r = d2i_RSA_PUBKEY(NULL, &key_data, sizeof(license_pub_der)); if(r != NULL) { if(__cr_license_data_ != NULL) { free((void*)__cr_license_data_); } __cr_license_data_ = malloc(CR_LIC_LEN); if(RSA_public_decrypt(CR_LIC_LEN, lic_encoded, (unsigned char*)__cr_license_data_, r, RSA_PKCS1_PADDING) <= 0) { free((void*)__cr_license_data_); __cr_license_data_ = NULL; } RSA_free(r); } } BIO_free_all(licIn); }
This piece of code on windows works well, so I assume the public key is not a problem.
__cr_license_ = lic; unsigned char lic_encoded[CR_LIC_LEN]; DWORD dwSize; if(CryptStringToBinaryA(__cr_license_, 0, CRYPT_STRING_BASE64, lic_encoded, &dwSize, NULL, NULL) && dwSize == CR_LIC_LEN) { HCRYPTPROV hProv; if(CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { PCERT_PUBLIC_KEY_INFO pki = NULL; DWORD dwKeySize; if(CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, license_pub_der, sizeof(license_pub_der), CRYPT_ENCODE_ALLOC_FLAG, NULL, &pki, &dwKeySize)) { HCRYPTKEY hKey = 0; if(CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, pki, &hKey)) {
But after that, everything I try to do with the message results in CRYPT_E_ASN1_BADTAG . I tried CryptMsgOpenToDecode with CryptMsgUpdate , CryptDecodeObject , CryptVerifyMessageSignatureWithKey - nothing works.
Basically, I think the problem is the incompatibility of pkcs1 and pkcs7, as mentioned above. Does anyone have any experience with importing / converting pkcs1 / etc format with MS CAPI?
Any help or even a hint is greatly appreciated! Thanks in advance!