代码之家  ›  专栏  ›  技术社区  ›  S Meaden

Microsoft Cryptographic API允许从字节流创建ECDSA密钥吗?

  •  1
  • S Meaden  · 技术社区  · 8 年前

    因此,我正在考虑使用哪个加密C++库(我已经知道如何在C#中进行等效)来验证许可证文件签名哈希。

    阅读CNG的Microsoft文档,似乎不可能从字节流中生成代码中的ECDSA密钥,尽管这对于RSA密钥是可能的(我认为,不是百分之百确定)。

    因此,我想回到使用微软在其桌面Windows操作系统中提供的东西,但我回到了我最初的问题,即没有代码内bytestream生成的键。

    专家能确认这真的不可能吗?另外,他们能提出替代方案吗?我很高兴回到RSA,用一个长(2048?)钥匙

    以下代码为我编译并运行。可以在 MSDN article - Signing Data with CNG . 我想知道它是否可以被改编。此代码是否(a)动态创建ECDSA密钥(b)签署哈希(c)将密钥保存到证书存储(d)检索密钥并验证签署的哈希。如果是这样的话,我想这是演示代码。我需要的是一个硬编码ECDSA密钥的示例,而不是一个动态创建的密钥。

    // CngECDSA.cpp : Defines the entry point for the console application.
    // Based on https://msdn.microsoft.com/en-us/library/windows/desktop/aa376304(v=vs.85).aspx
    
    #include "stdafx.h"
    
    #include <Windows.h>
    #include <stdint.h>
    #include <Bcrypt.h>
    #include <ncrypt.h>
    
    #pragma comment(lib, "bcrypt")  
    #pragma comment(lib, "ncrypt")
    
    
    #define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
    #define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
    
    static const  BYTE rgbMsg[] =
    {
        0x04, 0x87, 0xec, 0x66, 0xa8, 0xbf, 0x17, 0xa6,
        0xe3, 0x62, 0x6f, 0x1a, 0x55, 0xe2, 0xaf, 0x5e,
        0xbc, 0x54, 0xa4, 0xdc, 0x68, 0x19, 0x3e, 0x94,
    };
    
    BYTE value[] =
    { 0x02,0x00,0x00,0x00 };
    
    void __cdecl wmain(
        int                      argc,
        __in_ecount(argc) LPWSTR *wargv)
    {
        NCRYPT_PROV_HANDLE      hProv = NULL;
        NCRYPT_KEY_HANDLE       hKey = NULL;
        BCRYPT_KEY_HANDLE       hTmpKey = NULL;
        SECURITY_STATUS         secStatus = ERROR_SUCCESS;
        BCRYPT_ALG_HANDLE       hHashAlg = NULL,
            hSignAlg = NULL;
        BCRYPT_HASH_HANDLE      hHash = NULL;
        NTSTATUS                status = STATUS_UNSUCCESSFUL;
        DWORD                   cbData = 0,
            cbHash = 0,
            cbBlob = 0,
            cbSignature = 0,
            cbHashObject = 0;
        PBYTE                   pbHashObject = NULL;
        PBYTE                   pbHash = NULL,
            pbBlob = NULL,
            pbSignature = NULL;
    
        UNREFERENCED_PARAMETER(argc);
        UNREFERENCED_PARAMETER(wargv);
    
        //open an algorithm handle
        if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
            &hHashAlg,
            BCRYPT_SHA1_ALGORITHM,
            NULL,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
            &hSignAlg,
            BCRYPT_ECDSA_P256_ALGORITHM,
            NULL,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
            goto Cleanup;
        }
    
        //calculate the size of the buffer to hold the hash object
        if (!NT_SUCCESS(status = BCryptGetProperty(
            hHashAlg,
            BCRYPT_OBJECT_LENGTH,
            (PBYTE)&cbHashObject,
            sizeof(DWORD),
            &cbData,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
            goto Cleanup;
        }
    
        //allocate the hash object on the heap
        pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
        if (NULL == pbHashObject)
        {
            wprintf(L"**** memory allocation failed\n");
            goto Cleanup;
        }
    
        //calculate the length of the hash
        if (!NT_SUCCESS(status = BCryptGetProperty(
            hHashAlg,
            BCRYPT_HASH_LENGTH,
            (PBYTE)&cbHash,
            sizeof(DWORD),
            &cbData,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
            goto Cleanup;
        }
    
        //allocate the hash buffer on the heap
        pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
        if (NULL == pbHash)
        {
            wprintf(L"**** memory allocation failed\n");
            goto Cleanup;
        }
    
        //create a hash
        if (!NT_SUCCESS(status = BCryptCreateHash(
            hHashAlg,
            &hHash,
            pbHashObject,
            cbHashObject,
            NULL,
            0,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
            goto Cleanup;
        }
    
    
        //hash some data
        if (!NT_SUCCESS(status = BCryptHashData(
            hHash,
            (PBYTE)rgbMsg,
            sizeof(rgbMsg),
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
            goto Cleanup;
        }
    
        //close the hash
        if (!NT_SUCCESS(status = BCryptFinishHash(
            hHash,
            pbHash,
            cbHash,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
            goto Cleanup;
        }
    
        //open handle to KSP
        if (FAILED(secStatus = NCryptOpenStorageProvider(
            &hProv,
            MS_KEY_STORAGE_PROVIDER,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
            goto Cleanup;
        }
    
        //create a persisted key
        if (FAILED(secStatus = NCryptCreatePersistedKey(
            hProv,
            &hKey,
            NCRYPT_ECDSA_P256_ALGORITHM,
            L"my ecc key",
            0,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
            goto Cleanup;
        }
    
        //create key on disk
        if (FAILED(secStatus = NCryptFinalizeKey(hKey, 0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptFinalizeKey\n", secStatus);
            goto Cleanup;
        }
    
        //sign the hash
        if (FAILED(secStatus = NCryptSignHash(
            hKey,
            NULL,
            pbHash,
            cbHash,
            NULL,
            0,
            &cbSignature,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
            goto Cleanup;
        }
    
    
        //allocate the signature buffer
        pbSignature = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSignature);
        if (NULL == pbSignature)
        {
            wprintf(L"**** memory allocation failed\n");
            goto Cleanup;
        }
    
        if (FAILED(secStatus = NCryptSignHash(
            hKey,
            NULL,
            pbHash,
            cbHash,
            pbSignature,
            cbSignature,
            &cbSignature,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
            goto Cleanup;
        }
    
        if (FAILED(secStatus = NCryptExportKey(
            hKey,
            NULL,
            BCRYPT_ECCPUBLIC_BLOB,
            NULL,
            NULL,
            0,
            &cbBlob,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
            goto Cleanup;
        }
    
        pbBlob = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlob);
        if (NULL == pbBlob)
        {
            wprintf(L"**** memory allocation failed\n");
            goto Cleanup;
        }
    
        if (FAILED(secStatus = NCryptExportKey(
            hKey,
            NULL,
            BCRYPT_ECCPUBLIC_BLOB,
            NULL,
            pbBlob,
            cbBlob,
            &cbBlob,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptImportKeyPair(
            hSignAlg,
            NULL,
            BCRYPT_ECCPUBLIC_BLOB,
            &hTmpKey,
            pbBlob,
            cbBlob,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptVerifySignature(
            hTmpKey,
            NULL,
            pbHash,
            cbHash,
            pbSignature,
            cbSignature,
            0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status);
            goto Cleanup;
        }
    
        wprintf(L"Success!\n");
    
    Cleanup:
    
        if (hHashAlg)
        {
            BCryptCloseAlgorithmProvider(hHashAlg, 0);
        }
    
        if (hSignAlg)
        {
            BCryptCloseAlgorithmProvider(hSignAlg, 0);
        }
    
        if (hHash)
        {
            BCryptDestroyHash(hHash);
        }
    
        if (pbHashObject)
        {
            HeapFree(GetProcessHeap(), 0, pbHashObject);
        }
    
        if (pbHash)
        {
            HeapFree(GetProcessHeap(), 0, pbHash);
        }
    
        if (pbSignature)
        {
            HeapFree(GetProcessHeap(), 0, pbSignature);
        }
    
        if (pbBlob)
        {
            HeapFree(GetProcessHeap(), 0, pbBlob);
        }
    
        if (hTmpKey)
        {
            BCryptDestroyKey(hTmpKey);
        }
    
        if (hKey)
        {
            NCryptDeleteKey(hKey, 0);
        }
    
        if (hProv)
        {
            NCryptFreeObject(hProv);
        }
    }
    

    secp384r1 – {1.3.132.0.34}

    1 回复  |  直到 7 年前
        1
  •  3
  •   bartonjs    8 年前

    此代码是否(a)动态创建ECDSA密钥(b)签署哈希(c)将密钥保存到证书存储(d)检索密钥并验证签署的哈希。如果是这样的话,我想这是演示代码。

    A) 是的。

    B) 是的。

    nullptr / NULL 可能被传递,使其成为一个短暂的关键。(它将其保存到“密钥存储”,而不是“证书存储”。


    获取公钥数据(这是 openssl ec -in eckey.pem -pubout -outform der | xxd -g1

    static const BYTE data[] =
    {
        '1', '2', '3', '4',
    };
    
    static const BYTE publicKey[] =
    {
        0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
        0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x23, 0x63, 0xdd, 0x13, 0x1d,
        0xa6, 0x5e, 0x89, 0x9a, 0x2e, 0x63, 0xe9, 0xe0,
        0x5e, 0x50, 0xc8, 0x30, 0xd4, 0x99, 0x46, 0x62,
        0xff, 0xe8, 0x83, 0xdb, 0x2b, 0x9a, 0x76, 0x7d,
        0xcc, 0xab, 0xa2, 0xf0, 0x70, 0x81, 0xb5, 0x71,
        0x1b, 0xe1, 0xde, 0xe9, 0x0d, 0xfc, 0x8d, 0xe1,
        0x79, 0x70, 0xc2, 0xd9, 0x37, 0xa1, 0x6c, 0xd3,
        0x45, 0x81, 0xf5, 0x2b, 0x8d, 0x59, 0xc9, 0xe9,
        0x53, 0x2d, 0x13,
    };
    
    static const BYTE signature[] =
    {
        // r
        0xc6, 0x4c, 0x14, 0x55, 0xfe, 0xc0, 0x2f, 0xe7,
        0x4a, 0x25, 0x87, 0xe7, 0x0c, 0x10, 0x4e, 0x73,
        0xf0, 0x28, 0x86, 0x18, 0x28, 0xae, 0xef, 0x4f,
        0xe5, 0xa0, 0xcc, 0x7a, 0xa8, 0xe4, 0x1f, 0xbf,
    
        // s
        0x35, 0x9f, 0x23, 0xfd, 0xc3, 0xd6, 0x33, 0xfb,
        0x52, 0x47, 0x9b, 0xef, 0x2b, 0x2a, 0x48, 0xa8,
        0x6f, 0x37, 0x04, 0xd0, 0x8c, 0xc3, 0x49, 0x04,
        0x21, 0x53, 0xb8, 0x3c, 0x9d, 0x8c, 0x6c, 0xf5,
    };
    
    #define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
    
    int main()
    {
        NTSTATUS status = NTE_BAD_DATA;
        int exitCode = ERROR_INVALID_FUNCTION;
        BCRYPT_KEY_HANDLE importedPublicKey = nullptr;
        PCERT_PUBLIC_KEY_INFO subjectPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)LocalAlloc(0, 2048);
        BCRYPT_ALG_HANDLE sha256 = nullptr;
        BCRYPT_HASH_HANDLE hHash = nullptr;
        BYTE dataHash[256 >> 3];
    
        DWORD structSize = 2048;
        if (!CryptDecodeObject(
            X509_ASN_ENCODING,
            X509_PUBLIC_KEY_INFO,
            publicKey,
            sizeof(publicKey),
            0,
            subjectPublicKeyInfo,
            &structSize))
        {
            wprintf(L"**** Error 0x%x returned by CryptDecodeObject\n", GetLastError());
            goto Cleanup;
        }
    
        if (!CryptImportPublicKeyInfoEx2(
            X509_ASN_ENCODING,
            subjectPublicKeyInfo,
            0,
            nullptr,
            &importedPublicKey))
        {
            wprintf(L"**** Error 0x%x returned by CryptImportPublicKeyInfoEx2\n", GetLastError());
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&sha256, BCRYPT_SHA256_ALGORITHM, nullptr, 0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptCreateHash(sha256, &hHash, nullptr, 0, nullptr, 0, 0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptHashData(hHash, (PUCHAR)data, sizeof(data), 0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
            goto Cleanup;
        }
    
        if (!NT_SUCCESS(status = BCryptFinishHash(hHash, (PUCHAR)dataHash, sizeof(dataHash), 0)))
        {
            wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
            goto Cleanup;
        }
    
        status = BCryptVerifySignature(
            importedPublicKey,
            nullptr,
            (PUCHAR)dataHash,
            sizeof(dataHash),
            (PUCHAR)signature,
            sizeof(signature),
            0);
    
        switch (status)
        {
            case STATUS_SUCCESS:
                wprintf(L"Signature verified successfully\n");
                exitCode = ERROR_SUCCESS;
                break;
            case STATUS_INVALID_SIGNATURE:
                wprintf(L"Signature did not verify\n");
                exitCode = ERROR_INVALID_DATA;
                break;
            default:
                wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status);
                goto Cleanup;
        }
    
    
    
    Cleanup:
        if (hHash != nullptr)
            BCryptDestroyHash(hHash);
    
        if (sha256 != nullptr)
            BCryptCloseAlgorithmProvider(sha256, 0);
    
        if (importedPublicKey != nullptr)
            BCryptDestroyKey(importedPublicKey);
    
        LocalFree(subjectPublicKeyInfo);
    
        return exitCode;
    }