使用CryptoApi验证rsa签名

时间:2016-06-29 16:18:17

标签: python c++ cryptoapi pyopenssl

我尝试使用rsapyopenssl包在python 2代码中计算消息rsa签名,并使用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 signed string not getting verified by 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

生成公开

0 个答案:

没有答案