C# ECDSA在c中签名#在c中验证

C# ECDSA在c中签名#在c中验证,c#,c,signing,cryptoapi,dsa,C#,C,Signing,Cryptoapi,Dsa,我正在尝试使用ECDSA算法(这部分看起来还可以)在C#中对数据进行签名,并使用Windows crypto API在C中验证签名 BYTE KeyBlob[] = { // public key exported by above c# code 69,67,83,49,32,0,0,0,227,146,138,255,218,235,122,141,44,110,211,95,59,227,226,163,81,188,242,115,60,171,46,141,221,117,16

我正在尝试使用ECDSA算法(这部分看起来还可以)在C#中对数据进行签名,并使用Windows crypto API在C中验证签名

BYTE KeyBlob[] = { // public key exported by above c# code
    69,67,83,49,32,0,0,0,227,146,138,255,218,235,122,141,44,110,211,95,59,227,226,163,81,188,242,115,60,171,46,141,221,117,169,139,42,143,67,85,144,242,232,188,22,158,230,15,110,6,214,252,252,242,224,241,110,186,1,244,176,65,88,184,94,19,98,174,158,7,154,152
};

int _tmain()
{
    HCRYPTPROV hProv = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwBlobLen;
    BYTE* pbKeyBlob;

    if (!CryptAcquireContext(
        &hProv,
        NULL,
        MS_ENHANCED_PROV,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT))
    {
        printf(" Error in AcquireContext 0x%08x \n", GetLastError());
        return 1;
    }

    if (!CryptImportKey(
        hProv,
        KeyBlob,
        sizeof(DesKeyBlob),
        0,
        CRYPT_EXPORTABLE,
        &hKey))
    {
        printf("Error 0x%08x in importing the key \n",
            GetLastError());
    }
签名部分:

CngKeyCreationParameters keyCreationParameters = new CngKeyCreationParameters();
keyCreationParameters.ExportPolicy = CngExportPolicies.AllowPlaintextExport;
keyCreationParameters.KeyUsage = CngKeyUsages.Signing;

CngKey key = CngKey.Create(CngAlgorithm.ECDsaP256, null, keyCreationParameters);

ECDsaCng dsa = new ECDsaCng(key); //dsa = Digital Signature Algorithm
byte[] privateKey = dsa.Key.Export(CngKeyBlobFormat.EccPrivateBlob);
File.WriteAllText("privatekey.txt", String.Join(",", privateKey));


byte[] publicKey = dsa.Key.Export(CngKeyBlobFormat.EccPublicBlob);
File.WriteAllText("publicKey.txt", String.Join(",", publicKey));


CngKey importedKey = CngKey.Import(File.ReadAllText("privatekey.txt").Split(',').Select(m => byte.Parse(m)).ToArray(), CngKeyBlobFormat.EccPrivateBlob);
ECDsaCng importedDSA = new ECDsaCng(importedKey); //dsa = Digital Signature Algorithm
byte[] signed = dsa.SignData(new byte[] { 1, 2, 3, 4, 5 });
File.WriteAllText("signed.txt", String.Join(",", signed));
此时,我能够创建一个签名密钥并将其导出到文件中的字节缓冲区

当我尝试使用windows crypto API在C中导入此公钥时,会出现问题

BYTE KeyBlob[] = { // public key exported by above c# code
    69,67,83,49,32,0,0,0,227,146,138,255,218,235,122,141,44,110,211,95,59,227,226,163,81,188,242,115,60,171,46,141,221,117,169,139,42,143,67,85,144,242,232,188,22,158,230,15,110,6,214,252,252,242,224,241,110,186,1,244,176,65,88,184,94,19,98,174,158,7,154,152
};

int _tmain()
{
    HCRYPTPROV hProv = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwBlobLen;
    BYTE* pbKeyBlob;

    if (!CryptAcquireContext(
        &hProv,
        NULL,
        MS_ENHANCED_PROV,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT))
    {
        printf(" Error in AcquireContext 0x%08x \n", GetLastError());
        return 1;
    }

    if (!CryptImportKey(
        hProv,
        KeyBlob,
        sizeof(DesKeyBlob),
        0,
        CRYPT_EXPORTABLE,
        &hKey))
    {
        printf("Error 0x%08x in importing the key \n",
            GetLastError());
    }
返回

导入密钥时出现错误0x80090007

这是(错误h):


我做错了什么?

多亏了我刚刚找到的这个很棒的网站:,我能够分解C#API在验证签名和导入密钥时的功能

显然我需要ncrypt/bcrypt,签名是根据散列而不是数据本身进行验证的:

public bool VerifyData(Stream data, byte[] signature) {
            if (data == null) {
                throw new ArgumentNullException("data");
            }
            if (signature == null) {
                throw new ArgumentNullException("signature");
            }

            using (BCryptHashAlgorithm hashAlgorithm = new BCryptHashAlgorithm(HashAlgorithm, BCryptNative.ProviderName.MicrosoftPrimitiveProvider)) {
                hashAlgorithm.HashStream(data);
                byte[] hashValue = hashAlgorithm.HashFinal();

                return VerifyHash(hashValue, signature);
            }
        }

        [SecuritySafeCritical]
        public override bool VerifyHash(byte[] hash, byte[] signature) {
            if (hash == null) {
                throw new ArgumentNullException("hash");
            }
            if (signature == null) {
                throw new ArgumentNullException("signature");
            }

            // We need to get the raw key handle to verify the signature. Asserting here is safe since verifiation
            // is not a protected operation, and we do not expose the handle to the user code.
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();

            // This looks odd, but Key.Handle is really a duplicate so we need to dispose it
            using (SafeNCryptKeyHandle keyHandle = Key.Handle) {
                CodeAccessPermission.RevertAssert();

                return NCryptNative.VerifySignature(keyHandle, hash, signature);
            }
        }
这是一个本机解决方案,适用于需要它的人:

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>

char key[72] = { 69,67,83,49,32,0,0,0,227,146,138,255,218,235,122,141,44,110,211,95,59,227,226,163,81,188,242,115,60,171,46,141,221,117,169,139,42,143,67,85,144,242,232,188,22,158,230,15,110,6,214,252,252,242,224,241,110,186,1,244,176,65,88,184,94,19,98,174,158,7,154,152 };
char sign[64] = { 165,50,54,149,14,175,128,54,21,30,129,165,137,203,45,123,180,121,118,20,15,61,253,186,65,129,21,26,54,84,40,205,103,254,108,34,126,205,116,183,44,189,5,180,28,119,228,70,127,116,227,248,232,144,53,226,185,251,217,179,148,88,208,152 };
char message[] = { 1, 2, 3, 4, 5 };

BOOL crypt_init(char* key, unsigned long key_len)
{
    HCRYPTPROV    hProv = NULL;

    BCRYPT_ALG_HANDLE       hHashAlg = NULL, hSignAlg = NULL;
    BCRYPT_HASH_HANDLE      hHash = NULL;
    PBYTE                   pbHash = NULL;
    PBYTE                   pbHashObject = NULL;
    DWORD                   cbHashObject = 0,
                            cbHash = 0,
                            cbData = 0;

    NTSTATUS status;

    if (ERROR_SUCCESS != NCryptOpenStorageProvider(&hProv, NULL, 0)) {
        printf("CryptAcquireContext failed - err=0x%x.\n", GetLastError());
        return FALSE;
    }

    NCRYPT_KEY_HANDLE keyHandle;

    if (ERROR_SUCCESS != NCryptImportKey(hProv, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, &keyHandle, (PBYTE)key, 72, 0)) {
        printf("CryptAcquireContext failed - err=0x%x.\n", GetLastError());
        return FALSE;
    }

    if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(
        &hHashAlg,
        BCRYPT_SHA256_ALGORITHM,
        NULL,
        0)))
    {
        printf("BCryptOpenAlgorithmProvider failed - err=0x%x.\n", status);
        return false;
    }

    if(!BCRYPT_SUCCESS(status = BCryptGetProperty(hHashAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0))) {
        printf("BCryptGetProperty failed - err=0x%x.\n", status);
        return FALSE;
    }

    pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
    if (NULL == pbHashObject) {
        printf("memory allocation failed\n");
        return FALSE;
    }

    if (!BCRYPT_SUCCESS(status = BCryptGetProperty(hHashAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbHash, sizeof(DWORD), &cbData, 0))) {
        printf("BCryptGetProperty failed - err=0x%x.\n", status);
        return FALSE;
    }

    pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
    if (NULL == pbHash)
    {
        printf("memory allocation failed\n");
        return FALSE;
    }

    if (!BCRYPT_SUCCESS(status = BCryptCreateHash(hHashAlg, &hHash, pbHashObject, cbHashObject, NULL, 0, 0)))
    {
        printf("BCryptCreateHash failed - err=0x%x.\n", status);
        return FALSE;
    }

    if (!BCRYPT_SUCCESS(status = BCryptHashData(hHash, (PBYTE)message, sizeof(message), 0)))
    {
        printf("BCryptHashData failed - err=0x%x.\n", status);
        return FALSE;
    }

    if (!BCRYPT_SUCCESS(status = BCryptFinishHash(hHash, pbHash, cbHash, 0)))
    {
        printf("BCryptFinishHash failed - err=0x%x.\n", status);
        return FALSE;
    }

    if(ERROR_SUCCESS != NCryptVerifySignature(keyHandle, NULL, pbHash, cbHash, (PBYTE) sign, sizeof(sign), 0)) {
        printf("BCryptVerifySignature failed - err=0x%x.\n", status);
        return FALSE;
    }


    return TRUE;
}

int main() {
    crypt_init(key, 72);
}
#包括
#包括
#包括
char key[72]={69,67,83,49,32,0,0,022714613825518235122141,44110211,95,59227226163,81188242115,60171,461412211117169139,42143,67,85144242232188,22158230,15110,6214252252242424110186,1244176,65,88184,94,19,98174158,7154152};
字符符号[64]={165,50,54149,14175128,54,21,30129165137203,45123180121118,20,15,61253186,65129,21,26,54,84,40205103254108,34126205151183,44189,5180,28119228,701271162248232144,532261852512179148,88208152};
字符消息[]={1,2,3,4,5};
BOOL crypt_init(字符*键,无符号长键)
{
HCRYPTPROV hProv=NULL;
BCRYPT_ALG_HANDLE hHashAlg=NULL,hSignAlg=NULL;
BCRYPT_HASH_HANDLE hHash=NULL;
PBYTE pbHash=NULL;
PBYTE pbHashObject=NULL;
DWORD cbHashObject=0,
cbHash=0,
cbData=0;
非关税国家地位;
if(ERROR_SUCCESS!=NCryptOpenStorageProvider(&hProv,NULL,0)){
printf(“CryptAcquireContext失败-错误=0x%x。\n”,GetLastError());
返回FALSE;
}
密码钥匙手柄钥匙手柄;
if(ERROR_SUCCESS!=NCryptImportKey(hProv,NULL,BCRYPT_ECCPUBLIC_BLOB,NULL,&keyHandle,(PBYTE)key,72,0)){
printf(“CryptAcquireContext失败-错误=0x%x。\n”,GetLastError());
返回FALSE;
}
如果(!BCRYPT_)成功(状态=bcryptoppenalgorithmprovider(
&哈沙尔格,
BCRYPT_SHA256_算法,
无效的
0)))
{
printf(“BCryptOpenAlgorithmProvider失败-错误=0x%x.\n”,状态);
返回false;
}
if(!BCRYPT_SUCCESS(status=BCryptGetProperty(hHashAlg,BCRYPT_OBJECT_LENGTH,(PBYTE)和cbHashObject,sizeof(DWORD),&cbData,0))){
printf(“BCryptGetProperty失败-错误=0x%x.\n”,状态);
返回FALSE;
}
pbHashObject=(PBYTE)HeapAlloc(GetProcessHeap(),0,cbHashObject);
if(NULL==pbHashObject){
printf(“内存分配失败\n”);
返回FALSE;
}
if(!BCRYPT_SUCCESS(status=BCryptGetProperty(hHashAlg,BCRYPT_HASH_长度,(PBYTE)和cbHash,sizeof(DWORD),&cbData,0))){
printf(“BCryptGetProperty失败-错误=0x%x.\n”,状态);
返回FALSE;
}
pbHash=(PBYTE)HeapAlloc(GetProcessHeap(),0,cbHash);
if(NULL==pbHash)
{
printf(“内存分配失败\n”);
返回FALSE;
}
如果(!BCRYPT_SUCCESS(状态=BCryptCreateHash(hHashAlg,&hHash,pbHashObject,cbHashObject,NULL,0,0)))
{
printf(“BCryptCreateHash失败-错误=0x%x.\n”,状态);
返回FALSE;
}
如果(!BCRYPT_SUCCESS(状态=BCryptHashData(hHash,(PBYTE)消息,sizeof(消息,0)))
{
printf(“BCryptHashData失败-错误=0x%x.\n”,状态);
返回FALSE;
}
如果(!BCRYPT_SUCCESS(状态=BCryptFinishHash(hHash,pbHash,cbHash,0)))
{
printf(“BCryptFinishHash失败-错误=0x%x.\n”,状态);
返回FALSE;
}
if(ERROR_SUCCESS!=NCryptVerifySignature(keyHandle,NULL,pbHash,cbHash,(PBYTE)符号,sizeof(sign),0)){
printf(“BCryptVerifySignature失败-错误=0x%x.\n”,状态);
返回FALSE;
}
返回TRUE;
}
int main(){
crypt_init(密钥,72);
}