Я пытаюсь рассчитать подпись сообщения rsa в коде python 2, используя пакет rsa
или pyopenssl
, и проверить его с помощью Microsoft CryptoApi. К сожалению, CryptVerifySignature
всегда сообщает об ошибке 0x80090006: Invalid signature
. Мой код питона:
import rsa
from OpenSSL import crypto
private_key = "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDFloLNqx8YZHc8D5Pk6TniJo5nwdvObNilEih2VZtTPCHooa/A\nUhz0mqh/lOKkskDNa5RCz4iTWy7wug2v+1GGlFp9jEtYq6foVu8N9DChvc8OIVV1\n4PgyFCCbCJOi5ccVUh5KBCyO8FtxHiS6a8wE3glSwsUGfzpMdrfKCYENRwIDAQAB\nAoGAJOcHZwIevJ+G5WDDbm1gsiwhTJ+YPeV2UN4jUHaMm+8PJjOMb47meYipD6ru\n6XOhRrxg5Fl+WIcfLTaSd9uoTfYIJArTPF6R2EAkcPGeil3mMSDMwqTz5eStOI/q\nRkMryHN5lCOWkm3dWXNmT/75rnqJ4dFGE1iw5dL4OJbovQECQQDyabjCqIjsTHZW\nIohqQaZAbO+wLvP4IgeUvJ31CR5Xms61FUUOe5WEs6GnSfZlsdzun+58DBEsjo7J\ncqbZxTD5AkEA0KmdPO9LMSweTSqIbH72NcIuW8cQGI2oJKNLG4Ncc7GN6ElyHJ7H\nIbRfrb2UupsLvLTDFLIrOdGWG74JGkoAPwJARGJ+tKtGtSJ835+uTAtpExOoKlOU\nj5NKADOVe+KupJgPaBYv/P3wGBd0qvS6hcW/RbHoXSYqUh+FOF8Xoqd2QQJAJeuN\nHbPHEGqaHx/ppv3ztJVTY25rqGql8fKTBa77sDLGPT6LtFPOkHt9H8/iJX9jxKl9\nAlfWry09gFEqylJEdQJAHEA0/fDR+yHxxx4w9QnfbPtn0RNHQbBzKx0K37hMu/tE\n0wxp8BFWEs5YAWWNw82ft5yOg81MH1n8iCIHzWTKrw==\n-----END RSA PRIVATE KEY-----\n"
message = "testmessage"
key = rsa.PrivateKey.load_pkcs1(private_key)
signature = rsa.sign(message, key, 'MD5')
Подпись становится aa69b87840390e6032e57f4bb... байт, и такая же подпись у меня есть с помощью команды openssl dgst -md5 -sign private.pem -keyform PEM message.txt
Мой код С++ (короткая версия):
const char kPublicVerifyKey[] =
"-----BEGIN PUBLIC KEY-----\n"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFloLNqx8YZHc8D5Pk6TniJo5n\n"
"wdvObNilEih2VZtTPCHooa/AUhz0mqh/lOKkskDNa5RCz4iTWy7wug2v+1GGlFp9\n"
"jEtYq6foVu8N9DChvc8OIVV14PgyFCCbCJOi5ccVUh5KBCyO8FtxHiS6a8wE3glS\n"
"wsUGfzpMdrfKCYENRwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
...
std::vector<unsigned char> key_buffer(public_key.size);
DWORD key_buffer_size = key_buffer.size();
if (!CryptStringToBinaryA(static_cast<const char*>(public_key.data),
public_key.size, CRYPT_STRING_BASE64HEADER,
key_buffer.data(), &key_buffer_size, NULL, NULL))
{
return false;
}
CERT_PUBLIC_KEY_INFO* key_info = nullptr;
DWORD key_info_size = 0;
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
key_buffer.data(), key_buffer_size,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &key_info, &key_info_size))
{
return false;
}
HCRYPTPROV crypt_context;
if (!CryptAcquireContext(&crypt_context, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
return false;
}
HCRYPTKEY crypt_key;
if (!::CryptImportPublicKeyInfo(crypt_context,
X509_ASN_ENCODING, key_info, &crypt_key))
{
return false;
}
HCRYPTHASH hash;
if (!::CryptCreateHash(crypt_context, CALG_MD5, 0, 0, &hash)) {
return false;
}
if (!::CryptHashData(hash,
static_cast<const BYTE*>(message.data), message.size, 0))
{
return false;
}
BOOL result = ::CryptVerifySignature(hash,
static_cast<const BYTE*>(signature.data), signature.size,
crypt_key, NULL, 0);
Почему CryptVerifySignature
считает, что моя подпись неверна? Найдены связанные вопросы (подписанная строка php openssl не проверяется от Win CryptoAPI) с советом инвертировать только байты данных подписи или подписи и открытого ключа, но выполнение этого с подписью ничего не меняет, а изменение открытого ключа приводит к ошибке ASN1 bad tag value met. 0x8009310b
функцией CryptDecodeObjectEx
.
Закрытый ключ был создан с помощью команды openssl genrsa -out private.pem 1024
, а открытый — с помощью openssl rsa -in private.pem -inform PEM -outform PEM -pubout
.
key_buffer.resize(key_buffer_size); std::reverse(key_buffer.begin(), key_buffer.end());
перед вызовом CryptDecodeObjectEx, но он начал возвращать ошибкуASN1 bad tag value met. 0x8009310b
. В любом случае буду думать в этом направлении, спасибо - person xpp_T   schedule 29.06.2016