Я пытаюсь вычислить подпись RSA сообщения в коде Python 2, используя rsa
или же pyopenssl
упаковать и проверить это с Microsoft CryptoApi. К несчастью, CryptVerifySignature
всегда сообщает об ошибке 0x80090006: Invalid signature
,
Мой код Python:
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
команда
Мой код C ++ (короткая версия):
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
Задача ещё не решена.
Других решений пока нет …