Windows XP 与 Vista/7 上的 MS Crypto API 行为

2023-11-25

我试图了解如何在 XP、Vista 和 Windows 7 上从 PEM 格式(示例包含在下面的代码中)导入公钥。示例代码将在 XP 和 Windows Vista/7 上导入密钥,但不会一样的方法。

在 Windows XP 上,字符串“(原型)”加密提供者的名称中必需的,并允许传递对 CryptImportPublicKeyInfo 的调用。

在 Windows 7 上,“(原型)”提供程序显然存在,但不支持对 CryptImportPublicKeyInfo 的调用,这令人困惑。

这些操作系统之间的正确实现是什么样的?是否有必要检测XP并请求名称“(原型)”,并且对于其他操作系统没有它?是否有可能在某些 XP 系统上仍然会失败?

或者,有没有办法检测这种令人困惑的行为并选择哪个加密提供程序将支持必要的调用?

Windows 7 上的输出:

ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo success.
     SUCCESS.
ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo FAILED****.

Windows XP 上的输出:

ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo FAILED****.
ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo success.
     SUCCESS.

产生该输出的 C++ 源代码:(需要 crypt32.lib)

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

bool windowsAcquireProviderContext(HCRYPTPROV *pHandleProv, LPCTSTR pProviderName);
bool analyzeCryptographicSupport(LPCTSTR pProviderName);

int _tmain(int argc, _TCHAR* argv[])
{
    analyzeCryptographicSupport(MS_ENH_RSA_AES_PROV);
    analyzeCryptographicSupport(L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)");
    return 0;
}

bool windowsAcquireProviderContext(HCRYPTPROV *pHandleProv, LPCTSTR pProviderName) {
    WCHAR *pContainerName = L"blah blah blah";
    if(!CryptAcquireContext(pHandleProv, pContainerName, pProviderName, PROV_RSA_AES, CRYPT_SILENT)) {
        if(GetLastError() == NTE_BAD_KEYSET) {
            if(CryptAcquireContext(pHandleProv, pContainerName, pProviderName, PROV_RSA_AES, CRYPT_NEWKEYSET|CRYPT_SILENT)) {
                return true;
            }
        } 
    }
    return true;
}

LPCWSTR pwszPemPublicKey = 
    L"-----BEGIN PUBLIC KEY-----\r\n"
    L"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6GUVcbn92bahlwOskKi8XkG9q\r\n"
    L"Vq863+C4cOWC6HzJojc011pJFFIBu8/pG1EI8FZJdBmTrFaJTriYw1/SpbOH0QqE\r\n"
    L"eHanT8qWn+S5m9xgDJoWTBJKcnu3OHOvJJU3c8jOHQQnRWLfghJH4vnwStdiwUUY\r\n"
    L"SMWpwuHObsNelGBgEQIDAQAB\r\n"
    L"-----END PUBLIC KEY-----\r\n";
int pemPublicKeySize = wcslen(pwszPemPublicKey);

bool analyzeCryptographicSupport(LPCTSTR pProviderName) {

    printf("ANALYZING CRYPTOGRAPHIC SUPPORT FOR:\r\n");
    wprintf(L"\t \"%s\"\r\n", pProviderName);

    HCRYPTPROV hProv;
    if(!windowsAcquireProviderContext(&hProv, pProviderName)) {
        wprintf(L"\t CryptAcquireContext FAILED.\r\n");
        return false;
    }
    wprintf(L"\t CryptAcquireContext success.\r\n");

    DWORD blobSize;

    if(!CryptStringToBinary(pwszPemPublicKey, pemPublicKeySize, CRYPT_STRING_BASE64_ANY,  NULL, &blobSize, NULL, NULL)) {
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptStringToBinary.1 FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptAcquireContext.1 success.\r\n");

    BYTE *pBlob = (BYTE *)malloc(blobSize);

    if(!CryptStringToBinary(pwszPemPublicKey, pemPublicKeySize, CRYPT_STRING_BASE64_ANY,  pBlob, &blobSize, NULL, NULL)) {
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptStringToBinary.2 FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptStringToBinary.2 success.\r\n");

    CERT_PUBLIC_KEY_INFO *publicKeyInfo;
    DWORD publicKeyInfoLen;
    HCRYPTKEY hPublicKey;

    if(!CryptDecodeObjectEx(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pBlob, blobSize, CRYPT_DECODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen)) {
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptDecodeObjectEx FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptDecodeObjectEx success.\r\n");

    if(!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, publicKeyInfo, &hPublicKey)) {
        LocalFree(publicKeyInfo);
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptImportPublicKeyInfo FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptImportPublicKeyInfo success.\r\n");

    CryptDestroyKey(hPublicKey);
    LocalFree(publicKeyInfo);
    free(pBlob);
    CryptReleaseContext(hProv, 0);

    wprintf(L"\t SUCCESS.\r\n");
    return true;
}

你所描述的问题的原因很简单:Microsoft 更名为 AES 加密提供商 from

  • "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"在 Windows XP 中
  • "Microsoft Enhanced RSA and AES Cryptographic Provider"在更高版本的操作系统中。

In WinCrypt.h定义相应的常数为MS_ENH_RSA_AES_PROV and MS_ENH_RSA_AES_PROV_XP您可以使用它。

如果您不想测试操作系统的版本,您可以使用地穴获取上下文 with NULL as pszProvider(并继续使用PROV_RSA_AES as the dwProvType)。在您的代码中您可以包含analyzeCryptographicSupport(NULL);.

您还可以检查注册表项的“名称”值

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider Types\Type 024

查看默认名称PROV_RSA_AES提供者。

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

Windows XP 与 Vista/7 上的 MS Crypto API 行为 的相关文章

  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • 使用 GCP 的数据存储区时如何区分代码是在模拟器中运行还是在 GKE 中运行

    按照中给出的说明进行操作后 我不确定是否遗漏了任何内容https cloud google com datastore docs tools datastore emulator https cloud google com datasto
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • IQueryable 单元或集成测试

    我有一个 Web api 并且公开了一个端点 如下所示 api 假期 name name 这是 Web api 的控制器 get 方法 public IQueryable
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • 我可以在“字节数”设置为零的情况下调用 memcpy() 和 memmove() 吗?

    当我实际上没有什么可以移动 复制的时候 我是否需要处理这些情况memmove memcpy 作为边缘情况 int numberOfBytes if numberOfBytes 0 memmove dest source numberOfBy
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone

随机推荐

  • 内存泄漏调试

    如果没有跟踪工具 有哪些检测 调试内存泄漏的技术 拦截所有分配和释放内存的函数 根据平台的不同 列表可能如下所示 malloc calloc realloc strdup getcwd free 除了执行这些函数最初执行的操作之外 还将有关
  • 如何强制 ssh 从命令行接受新的主机指纹?

    我得到了标准 WARNING REMOTE HOST IDENTIFICATION HAS CHANGED IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY Someone could
  • 使下拉菜单可滚动

    我正在尝试使用 CSS 和 jquery 在 HTML 页面中实现下拉菜单 以下是 HTML 和 JavaScript 代码的示例
  • Chrome tabs.onActivated.addListener 抛出“未定义”TypeError

    我正在做一个 chrome 扩展 文档中有这个说法 about chrome tabs onActivated 每当我尝试放置chrome tabs onActivated addListener 它说Uncaught TypeError
  • 使用 HTMLAgilityPack 仅提取页面文本

    好的 我对 HTMLAgilityPack 中使用的 XPath 查询非常陌生 所以让我们考虑这个页面http health yahoo net articles healthcare what your favorite flavor s
  • Qt - 没有这样的信号错误

    我试图在双击可拖动小部件之一时触发信号冰箱贴示例 以下是我对示例源代码所做的更改 拖动标签 class DragLabel public QLabel public DragLabel const QString text QWidget
  • 如何在Python中使用BeautifulSoup解析google搜索结果

    我正在尝试解析谷歌搜索结果的第一页 具体来说 是提供的标题和小摘要 这是我到目前为止所拥有的 from urllib request import urlretrieve import urllib parse from urllib pa
  • 获取特定用户的last_login时间? (姜戈)

    我有代码User objects values list last login flat True 这为我提供了所有用户最后一次登录的列表 但我不确定您如何精简对特定用户所做的操作 我尝试了以下代码User objects get user
  • 将浮点数序列化为 32 位整数的可移植方法

    我一直在努力寻找一种可移植的方法来序列化 C 和 C 中的 32 位浮点变量 以便将其发送到微控制器或从微控制器发送 我希望格式定义得足够好 以便序列化 反序列化也可以从其他语言完成 而不需要太多的努力 相关问题有 C 中 double f
  • PDO 多重查询

    从 PHP 版本 5 3 开始PDO MYSQL驱动程序已被替换为有利于PDO MYSQLND 它引入了对多个查询的支持 不过 如果有多个结果集 我不知道如何获得两个结果集SELECT查询已通过 两个查询都已执行 不可能是第二个查询刚刚被转
  • 删除 UICollectionView 边缘的单元格 - 滚动后单元格不会立即出现

    考虑一个标准的垂直滚动流布局 其中填充了足够的单元格以引起滚动 当滚动到底部时 如果删除一个项目 使得集合视图的内容大小必须缩小以容纳新的项目数 即删除底行的最后一个项目 则从滚动到底部的单元格行顶部被隐藏 在删除动画结束时 顶行出现时没有
  • 如何在angularjs中将html数据导出为pdf

    这是我渲染所有内容的 html 代码json数据来自 js文件但得到 类型错误 无法将未定义或 null 转换为对象 在Function keys 处 在 DocMeasure measureNode pdfmake js 15647 在
  • matlab中的3D体素显示

    我有一个网格 它是 3D 的并且存储一个数字 这是我的网格的示例 如果它是 2 2 2 1 gt 0 0 0 0 2 gt 0 0 0 0 如果那里不存在体素 数字 0 通常是我想用颜色或 nan 表示的数字 我想做的是用 matlab 显
  • 是否可以使 display:table-cell 布局响应式?

    在我的代码中 有一个表 其中有一个分区 其中的表行由水平的复选框组成 这是我的示例代码 完整的代码在小提琴中Here HTML table cellpadding 0 border 0 width 100 cellspacing 0 tr
  • BouncyCastle 上的椭圆曲线与数字签名算法 (ECDSA) 实施

    我正在尝试实现 ECDSA 椭圆曲线数字签名算法 但我在 Java 中找不到任何使用 Bouncy Castle 的示例 我创建了密钥 但我真的不知道应该使用什么样的函数来创建签名并验证它 public static KeyPair Gen
  • numpy.rint 可以返回 Int32 吗?

    我正在做 ret np rint y 4 return ret 我希望它回来Int32 我尝试添加dtype Int32 但它错误地说 TypeError No loop matching the specified signature a
  • 如何使用 OpenCV 制作反向填充透明矩形?

    我想在这张图片中制作一个反向填充的矩形 我的代码 import cv2 lena cv2 imread lena png output lena copy cv2 rectangle lena 100 100 200 200 0 0 255
  • ReportLab 图片链接

    有没有办法在 ReportLab 中向 Platypus 图像对象添加 href 链接 我知道如何在段落中的文本上添加链接 但我似乎找不到有关添加图像链接的任何信息 这可以通过以下方式轻松实现超链接图像类米斯梅利提出 from report
  • C 中允许的静态数组的最大大小是多少?

    在我的算法中 我知道使用静态数组 而不是动态数组 但我有时 达到堆栈的极限 我对吗 静态数组存储在堆栈中 哪些参数会影响一个 C 程序的最大堆栈大小 是否有许多系统参数影响最大数组大小 最大没有 元素的数量取决于数组类型 它取决于系统 RA
  • Windows XP 与 Vista/7 上的 MS Crypto API 行为

    我试图了解如何在 XP Vista 和 Windows 7 上从 PEM 格式 示例包含在下面的代码中 导入公钥 示例代码将在 XP 和 Windows Vista 7 上导入密钥 但不会一样的方法 在 Windows XP 上 字符串 原