Я пытаюсь разработать решение для проверки лицензии. Лицензии кодируются на сервере с помощью функции OpenSSL RSA_private_encrypt
.
Для Mac OX X я использую RSA_public_decrypt
, и он прекрасно работает. В Windows я должен использовать очень маленький фрагмент кода, поэтому я не могу связываться с OpenSSL или другой библиотекой, И я должен использовать MS Crypto API.
Я провел несколько дней, пытаясь понять, что не так, но безуспешно. Я могу успешно импортировать открытый ключ, но на этом мой успех заканчивается. Я знаю, что мне нужно изменить порядок байтов с помощью CAPI, поэтому проблема может быть не в этом.
Я пробовал все, включая CryptVerifyMessageSignatureWithKey
и CryptDecodeObject
, чтобы загрузить большой двоичный объект с разными параметрами, но все равно не повезло.
Он всегда заканчивается на GetLastError() == CRYPT_E_ASN1_BADTAG
, что, как я полагаю, означает, что BLOB не отформатирован ASN1... Google ничего не говорит о формате вывода RSA_private_encrypt... так что я здесь совершенно потерян.
Вот код OS X на основе 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);
}
Эта часть кода в Windows работает хорошо, поэтому я предполагаю, что открытый ключ не является проблемой.
__cr_license_ = lic;
unsigned char lic_encoded[CR_LIC_LEN];
DWORD dwSize;
if(CryptStringToBinaryA(__cr_license_, 0/*autocalculate*/, 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)) {
Но после этого все, что я пытаюсь сделать с сообщением, приводит к CRYPT_E_ASN1_BADTAG
. Пробовал CryptMsgOpenToDecode
с CryptMsgUpdate
, CryptDecodeObject
, CryptVerifyMessageSignatureWithKey
- ничего не работает.
В основном я думаю, что проблема в несовместимости pkcs1 и pkcs7, как упоминал owlstead. Есть ли у кого-нибудь опыт работы с форматом pkcs1, импортирующим/преобразующим/и т. д. с помощью MS CAPI?
Любая помощь или даже подсказка очень ценятся! Заранее спасибо!
CRYPT_E_ASN1_BADTAG
, на которую вы ссылаетесь. - person Daniel Roethlisberger   schedule 26.01.2013CryptVerifyMessageSignatureWithKey
? По какой-то причине это не указано API (не то чтобы я удивлен, Microsoft регулярно занижает) - person Maarten Bodewes   schedule 26.01.2013