- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因此,我正在考虑使用哪个加密 C++ 库(我已经弄清楚如何在 C# 中执行等效操作)来验证许可文件签名哈希。
阅读 Microsoft 的 CNG 文档似乎无法从字节流生成代码中的 ECDSA key ,尽管这对于 RSA key 是可能的(我认为,不是 100% 确定)。
因为我想要生成代码字节流,所以我查看了 crypto++ 并设法编译了测试套件,但 cryptolib.lib 是一个 90 兆字节的超大文件,我只是试图做一些基本的事情而面临大量链接错误。所以我现在不太热衷于 crypto++。
所以我想回到使用 Microsoft 在其桌面 Windows 操作系统中提供的东西,但我又回到了我最初的问题,即代码字节流中没有生成 key 。
专家能否确认这真的不可能?另外,他们可以建议替代方案吗?我很乐意使用长(2048?) key 回退到 RSA。
以下代码为我编译和运行。它可以在 MSDN article - Signing Data with CNG 找到.我想知道它是否可以改编。此代码是否 (a) 即时创建 ECDSA key (b) 签署哈希 (c) 将 key 保存到证书存储 (d) 检索 key 并验证签名的哈希。如果是这样,那么我想这是演示代码。我需要的是一个硬编码的 ECDSA key 示例,而不是即时创建的。
// 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);
}
}
明确一点,我的目标是 384 位,为了与 OpenSsl 和 C# 兼容,曲线名称是 NIST 推荐的曲线 secp384r1 – {1.3.132.0.34}
我将使用 SHA256 哈希两次(就像比特币一样)。
最佳答案
Does this code (a) create an ECDSA key on the fly (b) sign a hash (c) save key to a certificate store (d) retrieve the key and verify signed hash. If so then I guess it's demo code.
A) 是的。
B) 是的。
C) 是的。它将 key 保存为名为“my ec key”的持久对象。但由于它再也没有通过名称请求它,所以可以传递 nullptr
/NULL
以使其成为临时 key 。 (并将其保存到“ keystore ”,而不是“证书库”。
D) 是验证,否检索。
获取您的公钥数据(这是将 openssl ec -in eckey.pem -pubout -outform der | xxd -g1
转换为 C 数组的输出)和签名(采用 IEEE P1363 格式) ) 是留给读者的练习。
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;
}
关于c++ - Microsoft Cryptographic API 是否允许从字节流创建 ECDSA key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45695170/
我想执行一堆 WebRequest,但设置了可以同时启动的阈值。 我遇到了这个LimitedConcurrencyTaskScheduler example并尝试像这样使用它 scheduler =
初始情况 我正在开发 .NET Framework 4.0、C#、Winform 应用程序。应用程序将在 GridView 中列出(并测试)WebServiceOperations(目前有 60 个
我有一个具有 5 个读取和 5 个写入容量的发电机表。在这张表中,我有两条记录。 然后我决定通过一次推送大量写入(一次突发大约 4000 条记录)看看我会得到什么样的错误响应。蓝色的“已消耗”线直接越
我在限制作业和“挂起”或“失败”的作业方面遇到了麻烦。这基本上就是我正在尝试做的事情。 $allServers = Import-Csv "C:\temp\input.csv" $job = $all
我正在编写一个运行微 Controller 仿真器的C++程序。运行模拟器的线程在这样的循环中这样做: while(should_run) { simulator->RunSingleClockC
我有这个简单的代码,它: 创建 IObservable 采样半秒 使用 ThreadPool 调度程序订阅它 使用 SynchronizationContext 观察它 代码如下: private v
我正在尝试翻译一些 C# 代码,它一次创建 N 个线程并在每个线程中运行一个函数。 我有两个问题: -如何限制一次N个线程? -当我在我的主要方法中引用静态整数 FastestMemory 和 Slo
我有一个splitpane我的 React 项目中的组件,在调整 Pane 大小时将对其宽度使用react并更改内容。拆分 Pane 组件具有以下事件监听器... componentDidMo
使用 urllib2 时是否可以轻松限制 kbps?如果是,如果您能指导我使用任何代码示例或资源,我们将不胜感激。 最佳答案 urllib 模块中有urlretrieve(url, filename=
使用 urllib2 时是否可以轻松限制 kbps?如果是,如果您能指导我使用任何代码示例或资源,我们将不胜感激。 最佳答案 urllib 模块中有urlretrieve(url, filename=
我正在为 Android Phone 构建应用程序,但遇到了一些奇怪的“节流”。我相信这是因为正在调用信号量来停止应用程序正在做的任何事情来处理手机中的其他内容。虽然我不是积极的。 我很好奇是否有一种
我使用 Charles (4.0.2) 作为代理服务器来测试我的移动应用程序,它依赖于 WKWebView 内部的 WebSockets。我正在尝试模拟一种情况,在这种情况下,用户会短暂地体验到他们的
我有一个 request-promise向 API 发出请求的函数。我受此 API 的速率限制,并且不断收到错误消息: Exceeded 2 calls per second for api clie
我正在使用网络服务发送 100 个 http 帖子。但是,该服务每秒只允许 5 个。我想知道 usleep 命令是否是执行此操作的最佳方法。例如: foreach($JSONarray['DATABA
我在随机时间以高频率接收数据对象,并且需要使用这些更新 JavaFX GUI。但是,我不想用大量的可运行对象填充 javafx 事件队列(我使用 Platform.RunLater)。 我一直在思考如
假设我有一个即时消息应用程序,每次收到消息时它都会发出哔声。我想 debounce 哔哔声,但我想在第一条消息到达时播放哔哔声,而不是为后续消息播放(在时间跨度内,比如 2 秒)。 另一个示例可能是:
所以我现在有: App.html import { debounce } from 'lodash' export default { data () { na
我将 Highstock.js 更新到 1.3 并注意到 afterSetExtemes 事件在每次拖动事件时触发,而不是 dragend/mouseup。我正在通过 ajax 更新主要系列,但现在这
我已经在我的 pod 的所有容器上设置了 CPU 和 Memory Requests=Limits,以使其符合保证服务质量类的资格。现在,查看过去 6 小时同一 Pod 的这些 CPU 使用率和 CP
我将 Highstock.js 更新到 1.3 并注意到 afterSetExtemes 事件在每次拖动事件时触发,而不是 dragend/mouseup。我正在通过 ajax 更新主要系列,但现在这
我是一名优秀的程序员,十分优秀!