使用 RSA AES 提供程序生成自签名 1024 位 X509Certificate2 时出现问题

2024-03-26

我正在尝试使用以下命令生成 X509Certificate2 对象Microsoft AES 加密提供程序 https://msdn.microsoft.com/en-us/library/windows/desktop/aa386979%28v=vs.85%29.aspx:

CALG_AES_256 (0x00006610) 256 位 AES。该算法的支持 Microsoft AES 加密提供程序。

我的问题是我打电话给CryptGenKey(providerContext, 0x6610, 0x4000001, out cryptKey)失败并出现以下错误:

未处理的类型异常 mscorlib.dll 中发生“System.Runtime.InteropServices.COMException”

附加信息:指定的标志无效。 (例外情况来自 H结果:0x80090009)

我正在使用的标志是(1024 << 16) | 1)。除非我弄错了,否则这不会产生 1024 位可导出密钥吗根据MSDN上的文档 https://msdn.microsoft.com/en-us/library/windows/desktop/aa379941(v=vs.85).aspx?我这里的方法有什么问题吗?

我的代码如下:

using System;
using System.Security;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;

namespace WebSockets
{
    public struct SystemTime
    {
        public short Year;
        public short Month;
        public short DayOfWeek;
        public short Day;
        public short Hour;
        public short Minute;
        public short Second;
        public short Milliseconds;
    }

    public static class MarshalHelper
    {
        public static void CheckReturnValue(bool nativeCallSucceeded)
        {
            if (!nativeCallSucceeded)
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    }

    public static class DateTimeExtensions
    {

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool FileTimeToSystemTime(ref long fileTime, out SystemTime systemTime);

        public static SystemTime ToSystemTime(this DateTime dateTime)
        {
            long fileTime = dateTime.ToFileTime();
            SystemTime systemTime;
            MarshalHelper.CheckReturnValue(FileTimeToSystemTime(ref fileTime, out systemTime));
            return systemTime;
        }
    }

    class X509Certificate2Helper
    {

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool CryptAcquireContextW(out IntPtr providerContext, string container, string provider, uint providerType, uint flags);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool CryptReleaseContext(IntPtr providerContext, int flags);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool CryptGenKey(IntPtr providerContext, int algorithmId, int flags, out IntPtr cryptKeyHandle);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool CryptDestroyKey(IntPtr cryptKeyHandle);

        [DllImport("crypt32.dll", SetLastError = true)]
        static extern bool CertStrToNameW(int certificateEncodingType, IntPtr x500, int strType, IntPtr reserved, byte[] encoded, ref int encodedLength, out IntPtr errorString);

        [DllImport("crypt32.dll", SetLastError = true)]
        static extern IntPtr CertCreateSelfSignCertificate(IntPtr providerHandle, ref CryptoApiBlob subjectIssuerBlob, int flags, ref CryptKeyProviderInformation keyProviderInformation, IntPtr signatureAlgorithm, ref SystemTime startTime, ref SystemTime endTime, IntPtr extensions);

        [DllImport("crypt32.dll", SetLastError = true)]
        static extern bool CertFreeCertificateContext(IntPtr certificateContext);

        [DllImport("crypt32.dll", SetLastError = true)]
        static extern bool CertSetCertificateContextProperty(IntPtr certificateContext, int propertyId, int flags, ref CryptKeyProviderInformation data);

        public static X509Certificate2 GenerateSelfSignedCertificate(String name = "", DateTime? startTime = null, DateTime? endTime = null)
        {
            if (startTime == null || (DateTime)startTime < DateTime.FromFileTimeUtc(0))
                startTime = DateTime.FromFileTimeUtc(0);
            var startSystemTime = ((DateTime)startTime).ToSystemTime();
            if (endTime == null)
                endTime = DateTime.MaxValue;
            var endSystemTime = ((DateTime)endTime).ToSystemTime();
            string containerName = Guid.NewGuid().ToString();
            GCHandle dataHandle = new GCHandle();
            IntPtr providerContext = IntPtr.Zero;
            IntPtr cryptKey = IntPtr.Zero;
            IntPtr certificateContext = IntPtr.Zero;
            IntPtr algorithmPointer = IntPtr.Zero;
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                MarshalHelper.CheckReturnValue(CryptAcquireContextW(out providerContext, containerName, null, 0x18, 0x8));
                MarshalHelper.CheckReturnValue(CryptGenKey(providerContext, 0x6610, 0x4000001, out cryptKey));
                IntPtr errorStringPtr;
                int nameDataLength = 0;
                byte[] nameData;
                dataHandle = GCHandle.Alloc(name, GCHandleType.Pinned);
                if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, null, ref nameDataLength, out errorStringPtr))
                {
                    string error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }
                nameData = new byte[nameDataLength];
                if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, nameData, ref nameDataLength, out errorStringPtr))
                {
                    string error = Marshal.PtrToStringUni(errorStringPtr);
                    throw new ArgumentException(error);
                }
                dataHandle.Free();
                dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);
                CryptoApiBlob nameBlob = new CryptoApiBlob { cbData = (uint)nameData.Length, pbData = dataHandle.AddrOfPinnedObject() };
                dataHandle.Free();
                CryptKeyProviderInformation keyProvider = new CryptKeyProviderInformation { pwszContainerName = containerName, dwProvType = 1, dwKeySpec = 1 };
                CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier { pszObjId = "1.2.840.113549.1.1.13", Parameters = new CryptoApiBlob() };
                algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm));
                Marshal.StructureToPtr(algorithm, algorithmPointer, false);
                certificateContext = CertCreateSelfSignCertificate(providerContext, ref nameBlob, 0, ref keyProvider, algorithmPointer, ref startSystemTime, ref endSystemTime, IntPtr.Zero);
                MarshalHelper.CheckReturnValue(certificateContext != IntPtr.Zero);
                return new X509Certificate2(certificateContext);
            }
            finally
            {
                if (dataHandle.IsAllocated)
                    dataHandle.Free();
                if (certificateContext != IntPtr.Zero)
                    CertFreeCertificateContext(certificateContext);
                if (cryptKey != IntPtr.Zero)
                    CryptDestroyKey(cryptKey);
                if (providerContext != IntPtr.Zero)
                    CryptReleaseContext(providerContext, 0);
                if (algorithmPointer != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(algorithmPointer, typeof(CryptAlgorithmIdentifier));
                    Marshal.FreeHGlobal(algorithmPointer);
                }
            }
        }

        struct CryptoApiBlob
        {
            public uint cbData;
            public IntPtr pbData;
        }

        struct CryptAlgorithmIdentifier {
            [MarshalAs(UnmanagedType.LPStr)]
            public String pszObjId;
            public CryptoApiBlob Parameters;
        }

        struct CryptKeyProviderInformation
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public String pwszContainerName;
            [MarshalAs(UnmanagedType.LPWStr)]
            public String pwszProvName;
            public uint dwProvType;
            public uint dwFlags;
            public uint cProvParam;
            public IntPtr rgProvParam;
            public uint dwKeySpec;
        }
    }
}

要调用它,您可以使用:X509Certificate2Helper.GenerateSelfSignedCertificate("CN = Example");.

Update:

如果我使用 0x1 作为标志:

CryptAcquireContextW(out providerContext, containerName, "Microsoft Enhanced RSA and AES Cryptographic Provider", 0x18, 0x8);
CryptGenKey(providerContext, 0x6610, 0x1, out cryptKey);

过去了CryptGenKey,但随后失败CertCreateSelfSignCertificate with:

未处理的类型异常 mscorlib.dll 中发生“System.Runtime.InteropServices.COMException”

附加信息:密钥不存在。 (HRESULT 的异常: 0x8009000D)

这个键集必须以不同的方式传入吗?我上面创建它的方式有什么问题吗?


问题在于CryptGenKey函数调用。在里面Algid参数,您应该传递 0x1(用于 RSA 密钥交换)或 0x2(RSA 数字签名)。您不需要其他值。密钥长度值应为 0x4000001(具有可导出密钥)。另外,我注意到您在实例化时传递了错误的提供程序类型CryptKeyProviderInformation目的。替换这一行:

CryptKeyProviderInformation keyProvider = new CryptKeyProviderInformation {
    pwszContainerName = containerName,
    dwProvType = 1,
    dwKeySpec = 1
};

用这一行:

CryptKeyProviderInformation keyProvider = new CryptKeyProviderInformation {
    pwszContainerName = containerName,
    dwProvType = 0x18,
    dwKeySpec = 1
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 RSA AES 提供程序生成自签名 1024 位 X509Certificate2 时出现问题 的相关文章

  • 对 ExecuteNonQuery() 的单次调用是原子的

    对 ExecuteNonQuery 的单次调用是否是原子的 或者如果单个 DbCommand 中有多个 sql 语句 那么使用事务是否有意义 请参阅我的示例以进行说明 using var ts new TransactionScope us
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • C# 中 PKCS11Interop 库的线程安全使用 [已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 PKCS11Interop 在 HSM 内执行密钥管理操作 我使用的 HSM 是 Thales PCI Express 下面是
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 预编译头和 Visual Studio

    有没有办法设置 Visual Studio 解决方案参数 以便它只创建预编译头而不构建整个解决方案 具体来说 它是一个巨大的 C 解决方案 本身有许多项目 谢谢 仅选择 pch 创建者源文件 通常是 stdafx cpp 然后编译该文件 C
  • 无法将参数从 `const char *` 转换为 `char *`

    鉴于此代码 void group build int size std string ips Build the LL after receiving the member list from bootstrap head new memb
  • 选择initializer_list迭代器定义

    Why std initializer list
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • QSpinBox 输入 NaN 作为有效值

    我正在尝试扩展 QSpinBox 以能够输入 NaN 或 nan 作为有效值 根据文档 我应该使用 textFromValue valueFromText 和 validate 函数来完成此操作 但我无法让它工作 因为它仍然不允许我输入除数
  • FluentAssertions ShouldNotThrow 无法识别异步方法/Func

    我正在尝试检查异步方法是否抛出具体异常 为此 我使用 MSTEST 和 FluentAssertions 2 0 1 我已经检查过这个关于 Codeplex 的讨论 http fluentassertions codeplex com wo
  • 您认为 ASP.NET MVC 会与 ASP.NET Webforms 竞争吗?

    您认为 ASP NET MVC 会在 Microsoft Web 开发市场中占据重要份额吗 还是会占市场的 10 15 哦是的 它将让 Web 表单脱颖而出 我们已经看到了真正的 MVC 框架在 Java 世界中的价值 在 MS 世界中 这
  • ASP.NET MVC 动作过滤器

    有谁知道即使在 CATCH 块中 ActionFilterAttribute 类的 OnResultExecuted 方法是否也会执行 ie CookiesActions public ActionResult Login Usuarios
  • 在 C# .NET 中对非 ASCII 字符进行编码

    我想向我的应用程序发送的电子邮件添加自定义标头 标头名称只能包含 ASCII 字符 但对于值和用户可能会输入 UTF 8 字符 我必须对它们进行 Base64 编码 此外 我还必须将它们解码回 UTF 8 以便在 UI 中向用户显示它们 最
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 意外的 const 引用行为

    include
  • 如何在控制台程序中获取鼠标位置?

    如何在 Windows 控制台程序中用 C 获取鼠标单击位置 点击时返回鼠标位置的变量 我想用简单的文本命令绘制一个菜单 这样当有人点击时 游戏就会注册它并知道位置 我知道如何做我需要做的一切 除了单击时获取鼠标位置 您需要使用 Conso
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • 为什么 C++ 标准没有将 sizeof(bool) 定义为 1?

    Size of char signed char and unsigned char由 C 标准本身定义为 1 个字节 我想知道为什么它没有定义sizeof bool also C 03 标准 5 3 3 1 说 sizeof char s
  • 在 C# 中使用自定义千位分隔符

    在显示字符串时 我尝试不使用 字符作为千位分隔符 而是使用空格 我想我需要定义一种自定义文化 但我似乎做得不对 有什么指点吗 例如 将 1000000 显示为 1 000 000 而不是 1 000 000 no String Replac
  • 创建进程默认浏览器

    我目前正在使用 ShellExecute 打开 在用户浏览器中打开 URL 但在 Win7 和 Vista 中遇到了一些麻烦 因为该程序作为服务运行提升 我想获取线程 id 因此 ShellExecute 无法获取线程 id 因此我开始使用

随机推荐

  • MySQL存储过程中用于选择数据的if语句

    我有下面的 SQL 代码 DELIMITER CREATE PROCEDURE test new procedure queryString VARCHAR 255 BEGIN SELECT tempValue COUNT FROM tes
  • 被类覆盖的扩展方法不会给出警告

    我在另一个线程中进行了讨论 发现类方法优先于具有相同名称和参数的扩展方法 这很好 因为扩展方法不会劫持方法 但假设您已向第三方库添加了一些扩展方法 public class ThirdParty public static class Th
  • pdf-writer 无效的多字节字符 (US-ASCII) 期望 keywords_end 内容 = "%PDF-#{@version}\n%âãÏÓ\n" Rails 3

    我在尝试运行的协作项目中遇到了 pdf writer gem 的问题 我正在使用RVM Ruby 1 9 2p180 Rails 3 1 0 on Ubuntu 10 10 我创建了一个新的gemset使用 Bundler 安装所需的 ge
  • 如何模拟 Object.getClass?

    我正在开发一个 Java 项目 想要为 DTO 中的 equals 方法编写单元测试 在 equals 方法中 有一个 getClass 方法由两个被测试对象调用 我想模拟这个 但我不知道它想要什么类型的对象 我试过 when mockRo
  • 带有窗口服务的网络打印

    我有一个朋友用窗口窗体做了同样的事情 我需要的是将其作为窗口服务 Window 服务程序 打印控制器服务 将用作中央打印机控制器 根据情况 我将打印作业发送到网络上的不同打印机 打印机安装在USB上 已经可以进行测试打印 但是当我列出已安装
  • HttpContext.Current.User.Identity.Name 始终为 string.Empty

    您好 我使用自定义 MembershipProvider 我想在应用程序场景中知道当前用户名 但是当我尝试访问 HttpContext Current User Identity Name 时 它 总是返回 string Empty if
  • 限制事件队列中的事件

    In a 最近的问题 https stackoverflow com questions 36492268 nodejs running out of memory processing csv files 我概述了在处理大量 csv 文件
  • 用于搜索某个单词/字符串是否包含在实体字段之一的 JPQL 查询

    基本上 这类似于查看句子中是否存在某个单词 有实体帖子 public class Post implements Serializable Id GeneratedValue strategy IDENTITY Column name po
  • 将公式向下填充到列中的最后一行

    我试图将单元格 M3 中的公式绘制到数据集的末尾 我使用 L 列作为基础来确定最后一个包含数据的单元格 我的公式是两个单元格的串联 它们之间有一个文本逗号 我的公式是 G3 L3 我希望Excel能画出这个公式 单元格 M4 将是 G4 L
  • 注释 Lambda 表达式的函数接口

    Java 8 引入了两者拉姆达表达式 http docs oracle com javase tutorial java javaOO lambdaexpressions html and 类型注释 http docs oracle com
  • 正斜杠还是反斜杠?

    我希望分别向与我的程序不同的目录写入和读取文本文件 当我指定要写入或读取的目录时 是否应该使用正斜杠或反斜杠来标识文件路径 使用正斜杠将使其与系统无关 为了简单起见 我会坚持这一点 考虑使用java io File separator ht
  • 如果在 JQuery 中未选中所有子节点,则取消选中父节点

    如果所有子节点都未选中 我想取消选中父节点 ul li li ul
  • 判断服务器是否支持resume get请求

    如何确定服务器是否支持恢复文件传输或获取请求 我的想法是设置标头以在字节 2 而不是 0 处启动 get 请求 如果给出正确的结果 则立即关闭 http 请求 但我想知道服务器对另一种探针的响应是否会向我透露此信息 要探测服务器的下载恢复功
  • VB.Net Excel Automation如何处理敏感度标签

    当我在 VB Net 中为用户创建 Excel 文件时 当我尝试保存文件时出现错误 当文件为只读时 您无法执行此操作 并且似乎是因为尚未选择敏感度标签 我无法找到任何有关在执行 Excel 自动化时处理敏感度标签的文档 因此我想知道是否有人
  • 服务器端处理的数据表上的“列索引”

    有谁知道如何添加列索引 to a 服务器端处理数据表 http www datatables net 基本上喜欢http www datatables net examples api counter columns html http w
  • 用c#在asp.net中发送邮件脚本

    请建议我一个代码发送邮件asp net 中的脚本C 我想建造调查表我想发送我的电子邮件 ID 上的所有信息 包括附件 主题和正文 try Assign a sender recipient and subject to new mail m
  • Windows XP 上的 Java 最大内存

    我一直能够为在 32 位 Windows XP Java 1 4 1 5 和 1 6 上运行的 Java SE 分配 1400 MB 的空间 java Xmx1400m 今天 我在使用 Java 1 5 16 和 1 6 0 07 的新 W
  • Javascript字符串nodejs流实现

    我需要一个将数据发送到字符串的nodejs 流 http nodejs org api stream html 实现 你认识什么人吗 直接地说 我正在尝试通过管道传输请求响应 如下所示 请求 http google com doodle p
  • 检查字符串变量是否具有整数值

    我正在开发一个项目 允许孩子们向圣诞老人发送消息 不幸的是 如果他们在 AGE 字段中输入字符串而不是整数 则程序会崩溃并返回 Conversion from string exampleString to type Double is n
  • 使用 RSA AES 提供程序生成自签名 1024 位 X509Certificate2 时出现问题

    我正在尝试使用以下命令生成 X509Certificate2 对象Microsoft AES 加密提供程序 https msdn microsoft com en us library windows desktop aa386979 28