c ++从xml导入CAPI / CNG中的RSA私钥

时间:2017-06-01 06:42:20

标签: c++ cryptography rsa cryptoapi cng

我在this question中读到了有关从本机组件导入公钥的信息。 我尝试基于BLOB文档对私钥做同样的事情,但是我收到了NTE_BAD_DATA错误。

我的想法可行吗?如果是的话,你能帮忙吗?

我的尝试:

void old_RSA_decrypt(PBYTE blob, DWORD blobSize)
{
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwDecryptedLen = 0;
    DWORD length;
    std::ifstream f;
    f.open("c:\\Programming\\encrypted.txt", std::ios::binary);
    if (!f.is_open())
    {
        std::cout << "Error on open file: " << GetLastError() << std::endl;
        return;
    }

    f.seekg(0, f.end);
    length = f.tellg();
    f.seekg(0, f.beg);

    char * buffer = new char[length];
    f.read(buffer, length);

    if (!f)
        std::cout << "error: only " << f.gcount() << " could be read" << std::endl;
    f.close();

    PBYTE bBuffer = (PBYTE)buffer;

    //now to get the decryption thing going

    if (!CryptAcquireContext(
        &hCryptProv,
        NULL,
        MS_STRONG_PROV,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT))

    {
        std::cout << "Error on CryptAcquireContext " << GetLastError() << std::endl;
        return;
    }
    if (!CryptImportKey(
        hCryptProv,
        blob,
        blobSize,
        NULL,
        0,
        &hKey))
    {
        std::cout << "Error on CryptImportKey " << GetLastError() << std::endl;
        return;
    }
    if (!CryptDecrypt(hKey, NULL, TRUE, 0, NULL, &dwDecryptedLen))
    {
        std::cout << "Error on CryptDecrypt (First Pass) " << GetLastError() << std::endl;
        return;
    }
    PBYTE decBuffer = new BYTE[dwDecryptedLen];
    for(int i = 0; i < length ; ++i)
        decBuffer[i] = bBuffer[i];

    if (!CryptDecrypt(hKey, NULL, TRUE, 0, decBuffer, &length))
    {
        std::cout << "Error on CryptDecrypt (Second Pass) " << GetLastError() << std::endl;
        return;
    }
    std::cout << "Yurika2!" << std::endl;
    std::ofstream of;
    of.open("c:\\Programming\\decrypted.txt", std::ios::binary);
    if (!of.is_open())
    {
        std::cout << "Error on open write file: " << GetLastError() << std::endl;
        return;
    }
    string sDecMsg = string(reinterpret_cast<char*>(decBuffer), length);
    of << sDecMsg << std::endl;
    of.close();
cleanup:
    delete[] buffer;
    delete[] decBuffer;

}

void do_decrypt()
{
    string modStr = "yVUndgQFuB5Z5FgC0/WgWCg6Y8VuB582avGjQDdeoJDa1+RBKCyXo700sAMSGjM/bVakOlFqvCsVFNBysx1CH731CDb2DR1a0bsmYmDQ9d0ZHX+AOohVDIx9mc7bkDQZoEFpe9NqFsu95Y9yktpl1JKPmKyLOFgufGJYYvQyoOM=";
    string expStr = "AQAB";
    string PStr = "/JydNn89lSWjgWOG1XRJm1qTWDekzzoLfTQU+GK+h8DGQ6gkUbgqGosLGo+eAxbO/ETZV3ibbBuIdvL4UxC5Qw==";
    string QStr = "zAh23Gc8Oqz/Uh2wh+yt8DqUesVLwMn2koc9CbyF9/Z5Qe8OIR4yygJtuYruRC1x/KYj85l6DGzstUZOtYmv4Q==";
    string DPStr ="+1INj1SUPjjOLUKJuQAS4z7/7PqfO5RyLcSNQHltOb5vAozcZXkmWnYPPAO6nzQoBg+xdDcH2kyiPkWJDYtL5Q==";
    string DQStr = "cbYh8HJEufrijTRox0hcJG+xgr7kmjy1BDMFDKEaFPkz2VBPEpwO+FDkMC1C35JoXcOGc+RMhhJK1jip8zkaYQ==";
    string InverseQStr = "3PAXzlAXgvLVrbOEygjA2zhJEYALBEi6VTKqfDKlnv8/D9QUkC39bEDIRLG0wMFFxN8NlLx5zTiiVswxnMy8Mw==";
    string DStr = "KKBSyKkyID+bowyxcWUAuJlRgv19YPNbL0RYTWZ+5UalqmfoT/uDk+pjndrYxcmulFkl5ZC1SYgmBl+zrXoLc/Ei86BtNiuwfcqHlUDp0fdP+fyYN45wh/251HQ3UM1zBpMP8XeYB6zjpCU/s3/wCBE6WpJWN9fKcG0W5PLq8eE=";

    //FROM STRINGS TO BYTE VECTORS!
    vector<BYTE> modBinMSB = base64_decode(modStr);
    vector<BYTE> expBinMSB = base64_decode(expStr);
    vector<BYTE> PBinMSB = base64_decode(PStr);
    vector<BYTE> QBinMSB = base64_decode(QStr);
    vector<BYTE> DPBinMSB = base64_decode(DPStr);
    vector<BYTE> DQBinMSB = base64_decode(DQStr);
    vector<BYTE> InverseQBinMSB = base64_decode(InverseQStr);
    vector<BYTE> DBinMSB = base64_decode(DStr);

    //TURN MSB TO LSB

    DWORD offset = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY); // to keep track of things
    const DWORD modulusLengthInBytes = 128;
    DWORD keyBlobLength = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (modulusLengthInBytes * 4) + (modulusLengthInBytes / 2);
    BYTE* keyBlob = (PBYTE)malloc(keyBlobLength);
    BLOBHEADER* blobheader = (BLOBHEADER*)keyBlob;
    blobheader->bType = PRIVATEKEYBLOB;
    blobheader->bVersion = CUR_BLOB_VERSION;
    blobheader->reserved = 0;
    blobheader->aiKeyAlg = CALG_RSA_KEYX;
    RSAPUBKEY* rsapubkey = (RSAPUBKEY*)(keyBlob + sizeof(BLOBHEADER));
    rsapubkey->magic = 0x31415352;
    rsapubkey->bitlen = modulusLengthInBytes * 8 *4 + modulusLengthInBytes*4;
    rsapubkey->pubexp = MSBByteVectorToDword(expBinMSB);

    BYTE* modulus = keyBlob + offset;
    copyReversed(modBinMSB, modulus);
    offset += modulusLengthInBytes;
    BYTE* prime1 = keyBlob + offset ;
    copyReversed(PBinMSB, prime1);
    offset += modulusLengthInBytes / 2;
    BYTE* prime2 = keyBlob + offset;
    copyReversed(QBinMSB, prime2);
    offset += (modulusLengthInBytes / 2);
    BYTE* exponent1 = keyBlob + offset;
    copyReversed(DPBinMSB, exponent1);
    offset += (modulusLengthInBytes / 2);
    BYTE* exponent2 = keyBlob + offset;
    copyReversed(DQBinMSB, exponent2);
    offset += (modulusLengthInBytes / 2);
    BYTE* coefficient = keyBlob + offset;
    copyReversed(InverseQBinMSB, coefficient);
    offset += modulusLengthInBytes / 2;
    BYTE* privateExponent = keyBlob + offset;
    copyReversed(DBinMSB, privateExponent);

    old_RSA_decrypt(keyBlob, keyBlobLength);
}

1 个答案:

答案 0 :(得分:0)

当然可以这样做。您提到了两个Windows加密堆栈,但存在一些差异:

  • 编码:
    • CAPI:所有可变长度字段都是little-endian。
    • CNG:所有可变长度字段都是big-endian。
  • 刚性:
    • CAPI:模数和D必须具有相同的长度。此外,P,Q,DP,DQ,InverseQ都具有相同的长度(必须是模数长度的一半(向上))。
    • CNG:私钥仅询问n,e,p和q ...并且您分别指定每个字段的长度。

我在你的代码中看到一个明显的错误:

rsapubkey->bitlen = modulusLengthInBytes * 8 *4 + modulusLengthInBytes*4;

the documentation

  

<强> bitlen

     

模数中的位数。在实践中,这必须始终是8的倍数。

所以只是

rsapubkey->bitlen = modulusLengthInBytes * 8;

您对dwMagic值的设置似乎也不正确。

rsapubkey->magic = 0x31415352;

0x31415352是RSA_PUB_MAGIC,因此您将自己称为公钥。你想要RSA_PRIV_MAGIC(并使用常量)。

rsapubkey->magic = RSA_PRIV_MAGIC;

http://source.dot.net/#System.Security.Cryptography.Csp/System/Security/Cryptography/CapiHelper.Shared.cs,b7bc764e6deb34f5比较,这是C#中一个有效的blob编写器。