Verify rsa signature with CryptoApi

1

I'm trying to calculate message rsa signature in python 2 code using rsa or pyopenssl package and verify it with microsoft CryptoApi. Unfortunately, CryptVerifySignature is always reporting error 0x80090006: Invalid signature. My python code:

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')

Signature becomes aa69b87840390e6032e57f4bb... bytes, and the same signature I have via openssl dgst -md5 -sign private.pem -keyform PEM message.txt command

My c++ code (short version):

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);

Why CryptVerifySignature think that my signature is incorrect? A found related questions (php openssl signed string not getting verified by Win CryptoAPI) with advice to reverse just signature or signature and public key data bytes, but doing this with signature changes nothing and reversing public key results in error ASN1 bad tag value met. 0x8009310b by CryptDecodeObjectEx function.

Private key was generated with openssl genrsa -out private.pem 1024 command and public was generated with openssl rsa -in private.pem -inform PEM -outform PEM -pubout

python
c++
cryptoapi
pyopenssl
asked on Stack Overflow Jun 29, 2016 by xpp_T • edited May 23, 2017 by Community

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0