如何在 WinCrypt 中生成和使用公钥加密

发布于 2024-10-15 08:50:45 字数 1873 浏览 5 评论 0原文

我目前正在尝试 Windows 加密 API,并遇到了公钥加密的一些问题。我可以找到很多有关如何加密项目的示例,但没有直接解决从开始到结束的公钥模型的问题。

以下是我当前的代码如何生成加密密钥对的粗略概述,为了可读性,我删除了错误检查代码。

// MAKE AN RSA PUBLIC/PRIVATE KEY:
    CryptGenKey(hProv, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &hKey);

// NOW LET'S EXPORT THE PUBLIC KEY:
    DWORD keylen;
    CryptExportKey(hKey,0,PUBLICKEYBLOB,0,NULL,&keylen);
    LPBYTE KeyBlob;
    KeyBlob = (LPBYTE)malloc(keylen);
    CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,KeyBlob,&keylen);
    ofstream outputkey;
    outputkey.open("TestPublicKey.txt", ios_base::out | ios_base::binary);
    for(size_t i=0; i < keylen; ++i)
        outputkey<<KeyBlob[i];
    outputkey.close();
    free(KeyBlob);

// NOW LET'S EXPORT THE PRIVATE KEY:
    CryptExportKey(hKey, 0, PRIVATEKEYBLOB,0,NULL,&keylen);
    KeyBlob = (LPBYTE)malloc(keylen);
    CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,KeyBlob,&keylen)
    outputkey.open("TestPrivateKey.txt", ios_base::out | ios_base::binary);
    for(size_t i=0;i<keylen;++i)
        outputkey<<KeyBlob[i];
    outputkey.close();
    free(KeyBlob);

// ENCRYPT A (SHORT) TEST MESSAGE [SHOULD JUST BE ANOTHER ALG'S KEY LATER]:
    DWORD encryptBufferLen=0;
    CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0); // how much space?
    BYTE* encryptionBuffer = (BYTE*)malloc(encryptBufferLen);
    memcpy(encryptionBuffer, TestMessage, TestMessageLen); // move for in-place-encrypt
    CryptEncrypt(hKey,0,true,0, encryptionBuffer, &bufferlen, encryptBufferLen );

    ofstream message;
    message.open("Message.txt", ios_base::out | ios_base::binary);
    for(size_t i=0;i<encryptBufferLen;++i)
        message<<encryptionBuffer[i];
    message.close();

我的两个导出的密钥不同,但都能够在不加载另一个密钥的情况下解密消息。此外,如果我在加载导出的公钥的新会话中加密新消息,我仍然可以使用任一密钥对其进行解密。

谁能告诉我我可能做错或错过了什么?我完全走错路了吗?

I'm currently experimenting with the Windows Cryptography API and running into some problems with Public-Key-Cryptography. I can find lots of examples of how to encrypt items, but nothing directly addressing a start-to-finish public key model.

Here's a rough outline of how my current code looks to generate an encryption key pair, I've removed the error checking code for readability

// MAKE AN RSA PUBLIC/PRIVATE KEY:
    CryptGenKey(hProv, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &hKey);

// NOW LET'S EXPORT THE PUBLIC KEY:
    DWORD keylen;
    CryptExportKey(hKey,0,PUBLICKEYBLOB,0,NULL,&keylen);
    LPBYTE KeyBlob;
    KeyBlob = (LPBYTE)malloc(keylen);
    CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,KeyBlob,&keylen);
    ofstream outputkey;
    outputkey.open("TestPublicKey.txt", ios_base::out | ios_base::binary);
    for(size_t i=0; i < keylen; ++i)
        outputkey<<KeyBlob[i];
    outputkey.close();
    free(KeyBlob);

// NOW LET'S EXPORT THE PRIVATE KEY:
    CryptExportKey(hKey, 0, PRIVATEKEYBLOB,0,NULL,&keylen);
    KeyBlob = (LPBYTE)malloc(keylen);
    CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,KeyBlob,&keylen)
    outputkey.open("TestPrivateKey.txt", ios_base::out | ios_base::binary);
    for(size_t i=0;i<keylen;++i)
        outputkey<<KeyBlob[i];
    outputkey.close();
    free(KeyBlob);

// ENCRYPT A (SHORT) TEST MESSAGE [SHOULD JUST BE ANOTHER ALG'S KEY LATER]:
    DWORD encryptBufferLen=0;
    CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0); // how much space?
    BYTE* encryptionBuffer = (BYTE*)malloc(encryptBufferLen);
    memcpy(encryptionBuffer, TestMessage, TestMessageLen); // move for in-place-encrypt
    CryptEncrypt(hKey,0,true,0, encryptionBuffer, &bufferlen, encryptBufferLen );

    ofstream message;
    message.open("Message.txt", ios_base::out | ios_base::binary);
    for(size_t i=0;i<encryptBufferLen;++i)
        message<<encryptionBuffer[i];
    message.close();

My two exported keys are different, but both are able to decrypt message without the other key being loaded. Additionally, if I encrypt a new message in a new session that loads the exported public key, I can still decrypt it with either key.

Can anyone advise me on what I might be doing wrong or missing? Am I on completely the wrong path?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感性 2024-10-22 08:50:45

我不完全理解你的询问。但通常

  1. 您不会直接使用公钥加密数据。

  2. 加密期间:您使用会话/对称/私钥来加密数据。然后,该会话密钥将通过 AT_EXCHANGE 公钥进行加密。

  3. 解密期间:AT_EXCHANGE 私钥将解密会话密钥。反过来,该会话密钥将用于解密实际数据。

I do not fully understand your query. But generally

  1. You do not encrypt data directly using a public key.

  2. During Encryption: You use a session/symmetric/private key to encrypt data. This session key is then being encrypted by the AT_EXCHANGE public key.

  3. During Decryption: The AT_EXCHANGE private key will decrypt the session key. In turn this session key will be used to decrypt the actual data.

晨曦慕雪 2024-10-22 08:50:45

我还不是加密方面的专家!但我现在正在处理这个问题,所以可以感受到你的痛苦...

加密位看起来有些不对劲

// ENCRYPT A (SHORT) TEST MESSAGE [SHOULD JUST BE ANOTHER ALG'S KEY LATER]:
DWORD encryptBufferLen=0;
CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0); // how much space?
BYTE* encryptionBuffer = (BYTE*)malloc(encryptBufferLen);
memcpy(encryptionBuffer, TestMessage, TestMessageLen); // move for in-place-encrypt
CryptEncrypt(hKey,0,true,0, encryptionBuffer, &bufferlen, encryptBufferLen );

你似乎要求该函数给你加密消息的大小,以便你可以分配它的内存,即大小...但是除了密钥本身之外,您没有传递任何内容,因此我认为它无法肯定地提供该信息。

您有 CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0) ; // 但是当你实际上应该传入包含要加密的字符串的缓冲区时为什么要使用“NULL”,以便它可以计算出大小并为你返回它!然后您可以继续其余的操作。我知道这就是导出位的工作原理(因为您在该上下文中使用键),而在这里您正在处理实际的消息。尝试传入参数,看看效果如何?

我想你会发现你实际上无法用两个密钥解密,因为你还没有真正加密任何东西???我认为您将消息加密到零大小的缓冲区中。

正如我所说,不是专家,但它对我来说确实看起来不对......最奇怪的是我前几天发现了你的帖子并收获了工作片段来帮助我理解它,所以我真的希望这些信息对你有帮助!

I am not an expert with this encryption stuff just yet! but I am working with this at the moment so can feel your pain...

Something looks amiss with the encrypt bit

// ENCRYPT A (SHORT) TEST MESSAGE [SHOULD JUST BE ANOTHER ALG'S KEY LATER]:
DWORD encryptBufferLen=0;
CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0); // how much space?
BYTE* encryptionBuffer = (BYTE*)malloc(encryptBufferLen);
memcpy(encryptionBuffer, TestMessage, TestMessageLen); // move for in-place-encrypt
CryptEncrypt(hKey,0,true,0, encryptionBuffer, &bufferlen, encryptBufferLen );

It appears that you are asking the function to give you the size of the encrypted message so that you can assign its memory i.e. size... BUT you are not passing anything in apart from the key itself so I dont think it would be able to give that information surely..

You have CryptEncrypt(hKey, 0, true, 0, NULL, &encryptBufferLen, 0); // but why "NULL" when you actually should pass in the buffer containing the string to be encrypted, so that it can work out the size and return it for you! Then you can move on with the rest.. I know thats how the export bit works (because your working with the keys in that context), whereas here you are dealing with the actual message. Try passing in the parameter and see how that goes?

I think you'll find that your not actually able to decrypt with both keys, as you haven't actually encrypted anything yet???? Your encrypting a message into a zero sized buffer I think.

As I said not an expert but it does look wrong to me... Strangest thing is I found your post the other day and harvested the working bits to help me understand it, so I really hope that this info helps you!

仄言 2024-10-22 08:50:45

您是否在两个密钥上都使用 CryptImportKey ?看来您的加密只是使用您生成的密钥的句柄。要正确进行公共/私有对,您应该使用 CryptExportKey 仅导出公共密钥并将其提供给需要它的任何人。尽管这不是真正的“加密”,但它是让该人知道它来自您的一种方式。

Are you using CryptImportKey on both keys? It looks like your encrypt is just using the handle to thekey you generated. To do Public/Private pairs correctly you should export just the public key with CryptExportKey and give it to whomever needs it. Although this isn't true "encryption" its a way for that person to know it is from you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文