- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 ECDSA 算法(这部分看起来没问题)在 C# 中签署数据,并使用 Windows 加密 API 在 C 中验证签名。
签名部分:
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));
此时我可以创建签名 key 并将其导出到文件中的字节缓冲区。
当我尝试使用 Windows 加密 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());
}
返回
Error 0x80090007 in importing the key
这是(相信 winerror.h):
//
// MessageId: NTE_BAD_VER
//
// MessageText:
//
// Bad Version of provider.
//
#define NTE_BAD_VER _HRESULT_TYPEDEF_(0x80090007L)
我做错了什么?
最佳答案
多亏了这个很棒的网站,我才发现:referencesouce.microsoft.com ,我已经能够反汇编 C# API 在验证签名和导入 key 时所做的事情。
显然我需要 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);
}
关于c# - ECDSA 登录 c# 在 c 中验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50445252/
我正在尝试为我的用户提供使用 Google 或 Facebook 登录的选项。到目前为止,我找到了一个实现 Google 登录流程的示例,但如果我可以在同一 Activity 中实现类似的 Faceb
我有一个网页,它对用户是否登录很敏感。我使用的是 Google 登录 Javascript SDK。当用户到达此页面时,我想显示一个插页式广告(“正在加载...”),然后 1)如果用户已登录则呈现页面
我用 digitalocean 创建了一个 droplet,并使用 apt install mariadb-server 命令安装了 mariadb。现在我想使用 php 连接到我的服务器,我使用这个
这个问题在这里已经有了答案: Inno Setup - Signing fails with "Sign Tool failed with exit code 0x1" (2 个回答) 3年前关闭。
我正在尝试使用他们的新 API 实现 google 登录:https://developers.google.com/identity/sign-in/web/ 登录和注销工作正常。我的问题是我不知道
我的应用程序具有谷歌登录、Facebook 登录和 braintree 集成。 我已将以下代码放入 appdelegate.swift 中: func application(_ applicatio
我有一个 Flask 应用程序,最近在我的登录/退出表单中实现了 Flask-Login: @account.route('/sign-in', methods=['POST', 'GET']) de
friend 们,我是初学者级别的 ios swift 学习者。我一直在尝试在我的试用应用程序中进行谷歌登录。根据来自谷歌开发人员和其他教程的资源,我成功地使用 UIView 进行了登录。然后我试图在
我正在使用 Ionic 在 Codeigniter/Ion_Auth/codeigniter-restclient 之上构建登录系统,当我尝试从“ionic 服务器”登录时,登录可以正常工作,但对 L
在 Docker 文件中我有这个 FROM ubuntu RUN apt update && apt -y upgrade RUN apt install -y sudo # Setup ops us
对于 Java 开发,我使用 Slf4j 和 Logback。 Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.de
在 Scala 应用程序中进行日志记录的好方法是什么?与语言哲学一致的东西,不会使代码困惑,并且维护成本低且不引人注目。以下是基本要求列表: 简单 不会使代码困惑。 Scala 以其简洁而著称。我不希
我正在尝试将我的登录名转换为 Retrofit2 我的旧 LoginActivity: public class LoginActivity extends Activity { private st
我正在尝试让 google+ 登录在 android 上运行。我的问题是,每当我使用 eclipse 运行它时,google 开发站点上提供的示例都能完美运行。当我签署 apk 并在我的设备上手动安装
这个问题已经有答案了: JS Simple but Safe Login? [closed] (1 个回答) 已关闭 6 年前。 我正在尝试使用 JavaScript 创建登录页面。它实际上只是一个带
其他章节请看: react 高效高质量搭建后台系统 系列 登录 本篇将完成 登录模块 。效果和 spug 相同: 需求 如下:
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 1 年前。
我在使用 ReactJs 中的 facebook-login 组件时遇到问题,代码与文档中的完全一样,但仍然无法正常工作。你能帮我找出我做错了什么吗? import React, { Componen
我有一个项目,其中包含许多具有自己的日志记录的“工具”类。这些日志文件是在应用程序启动时创建的,但在使用之前一直为空。 是否可以告诉logback在启动时不应该创建空文件?但是仅在使用它们时? 不知何
我正在创建一个需要用户授权才能访问某些功能的网站。我目前正在研究用户如何创建帐户以及如何利用 session 来授权他们的登录。用户信息存储在名为 user 的 MySQL 表中,其中可能包括用户名和
我是一名优秀的程序员,十分优秀!