CNG 关于 Key 相关的操作

章节目录

  1. 简介
  2. 创建 Key
  3. 查看系统中的 Key
  4. 从 Windows Store 导出 key
  5. 导入 Key 到 Windows Store

<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!</b>

简介

CNG 全称 Cryptography API: Next Generation (CNG). 是 windows 平台下一代加密相关 API 的总称, 它是 Crypto API 的替代. 比较与 CryptoAPI, 它的功能更加强大.

本文将以实例的形式给出使用 CNG 操作 Key 的方法以及相关的 API.

请注意, 文章中我们使用 RSA key 作为示例, DSA 和 ECC key 也是同样适用的.

创建 Key

CNG 当前版本支持了 RSA, DSA, ECC 算法, 这里我们来创建一个 key 长度 为 2048 bits 的 RSA key. 注意, 当你尝试创建 2048 的 DSA key 时, 请确保你的系统是否支持, 本人的 Win7 是不支持的, 而 Win10 是支持的(亲测).

这里我们依次使用了以下API:
<code>NCryptOpenStorageProvider</code> 该方法用于加载和初始化一个已经存在 CNG Key Storage Provider. 当前 Windows 系统中内置了两个 KSP:MS_KEY_STORAGE_PROVIDER,MS_SMART_CARD_KEY_STORAGE_PROVIDER. 我们例子中使用 MS_KEY_STORAGE_PROVIDER.
<code>NCryptCreatePersistedKey</code> 该方法用于常见一个特定算法的 Key, 并把它存在指定的 KSP 中. 注意, 这个方法创建的 key 会以文件形式存储在 Windows 系统中.
<code>NCryptSetProperty</code> 该方法用于设置 key 的属性. 例子中我们将使用它设置 key 的长度为 2048 bits.
<code>NCryptFinalizeKey</code> 该方法用于通知 Windows 我们创建 key 的操作已经完成, 调用该方法后, 我们创建的 Key 将可以被用于签名加密等操作, 否则不能.
<code>NCryptFreeObject</code> 该方法用于释放前面操作中我们所使用到系统 Handle.

int Create2048RSAKey() {int errCode = 0;NCRYPT_PROV_HANDLE prov = NULL;NCRYPT_KEY_HANDLE  key = NULL;DWORD keyLength = 2048;DWORD policy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;if (errCode = NCryptOpenStorageProvider(&prov, MS_KEY_STORAGE_PROVIDER, 0)) goto done;if (errCode = NCryptCreatePersistedKey(prov, &key, NCRYPT_RSA_ALGORITHM, L"TestRSAKey", 0, NCRYPT_OVERWRITE_KEY_FLAG)) goto done;if (errCode = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (PBYTE)(&keyLength), sizeof(keyLength), NCRYPT_PERSIST_FLAG)) goto done;if (errCode = NCryptSetProperty(key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)(&policy), sizeof(policy), NCRYPT_PERSIST_FLAG)) goto done;if (errCode = NCryptFinalizeKey(key, 0)) goto done;done:if (prov) NCryptFreeObject(prov);if (key) NCryptFreeObject(key);return errCode;
}

当你在你的 Windows 电脑上执行了该方法之后, 你的系统中就会存有我们刚刚创建的 Key 了.
下一节, 我们将使用 CNG API 来查看我们创建的 Key 的信息.

查看系统中的 Key

这里我们将会使用到的 CNG API 有:
<code>NCryptEnumKeys</code> 该方法用于遍历保存在当前 KSP 中的所有 Key.
这里我们解释一下它的几个参数:
<code>NCryptKeyName **ppKeyName</code> 该参数作为方法的返回值, 其中保存了当前 Key 的名称, key 算法等重要信息. name 尤为重要, 比如我们例子中会使用 name 来获取该 key 的 handle, 依次来使用该 key 做更多的操作.
<code>PVOID *ppEnumState</code> 该参数也作为方法的返回值. 但是它的值对于调用者来说是没有任何意义的. 它存储了遍历 key 的中间信息, 是我们下一次调用 NCryptEnumKeys 方法的入参. 如果将该参数设置为 NULL, 遍历总是会返回当前 KSP 的第一个 Key 的信息.
<code>return value</code> 当该方法返回值为 NTE_NO_MORE_ITEMS, 代表已经遍历完了当前 KSP 中所有的 Key.
<code>NCryptOpenKey</code> 该方法用于获取执行 KSP 中指定名称的 Key Handle.
<code>NCryptGetProperty</code> 该方法用于获取 Key 的属性.

int ListKeys() {int errCode = 0;NCRYPT_PROV_HANDLE prov        = NULL;NCRYPT_KEY_HANDLE  key         = NULL;NCryptKeyName*     pKeyName    = NULL;PVOID              pEnumState = NULL;if (errCode = NCryptOpenStorageProvider(&prov, MS_KEY_STORAGE_PROVIDER, 0)) goto done;do {errCode = NCryptEnumKeys(prov, 0, &pKeyName, &pEnumState, 0);if (errCode == NTE_NO_MORE_ITEMS) break; // all the keys are enumeratedif (!pKeyName) break; // should not happenLPCWSTR name = pKeyName->pszName;LPCWSTR alg  = pKeyName->pszAlgid;// get key length propertyDWORD keyLength = 0,  outLen = 0;if (errCode = NCryptOpenKey(prov, &key, name, 0, 0)) goto done;if (errCode = NCryptGetProperty(key, NCRYPT_LENGTH_PROPERTY, (PBYTE) (&keyLength), sizeof(keyLength), &outLen, 0)) goto done;wprintf(L"KeyName: %s, KeyAlgorithm: %s, KeyLength: %d", name, alg, keyLength);} while (!errCode);done:if (prov) NCryptFreeObject(prov);if (key) NCryptFreeObject(key);return errCode;
}

如果你在你的电脑上运行了第一小节的函数, 此时执行 ListKeys 函数, 你的命令行中肯定会包含这样的输出:

<code>KeyName: TestRSAKey, KeyAlgorithm: RSA, KeyLength: 2048</code>

从 Windows Store 导出 key

通过上述两个小节的描述, 我们已经成功的在 Windows 系统中创建了 Key, 并且可以查看 Key 的信息, 获取 Key handle. 使用 Key Handle 我们可以完成很多的工作.但是, 很多时候我们需要把 Key 到处到文件, 和同伴分享.

这一小节, 我们就来尝试把 Key 导出来.

<code>NCryptExportKey</code> 该方法用于将系统中的 Key 导出到 memory blob 中.
它有一个非常重要的参数:
<code>LPCWSTR pszBlobType</code> 用来控制导出的 memory blob 的格式. 例子中我们使用 NCRYPT_PKCS8_PRIVATE_KEY_BLOB. <b>相信我,这个格式将会是最方便我们做进一步处理的格式. 其他的格式, 比如 BCRYPT_DSA_PUBLIC_BLOB, LEGACY_DSA_PRIVATE_BLOB 等格式看起来很友善, 但是并不总是像你想象的那样工作. 他们的格式并不总是和 CryptExportKey 导出时的一致,当 Key 的长度变为 2048 或者更大时, 而且很难找到相应的文档来描述此时它的格式到底是什么样的. 而 PKCS8 工作的非常好.</b>

int ExportKey() {int errCode = 0;NCRYPT_PROV_HANDLE prov = NULL;NCRYPT_KEY_HANDLE  key = NULL;BYTE blob[0x1000] = {0};DWORD blobLen = 0x1000;if (errCode = NCryptOpenStorageProvider(&prov, MS_KEY_STORAGE_PROVIDER, 0)) goto done;if (errCode = NCryptOpenKey(prov, &key, L"TestRSAKey", 0, 0)) goto done;if (errCode = NCryptExportKey(key, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL, blob, blobLen, &blobLen, 0)) goto done;done:if (prov) NCryptFreeObject(prov);if (key) NCryptFreeObject(key);return errCode;
}

当你执行该函数与某个 Key Handle 时, 如果你得到错误码 0x80090029, 请确认你的 Key 的 NCRYPT_EXPORT_POLICY_PROPERTY 属性的值包含 NCRYPT_ALLOW_EXPORT_FLAG 和 NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG.(这就是为什么, 第一节中的代码中, 我们明确的将创建的 Key 属性设置为该值的原因了.)

如果你的 Key 不包含 NCRYPT_ALLOW_EXPORT_FLAG 和 NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG, 那意味着你的 Key 无法导出, 你只能使用该 Key 的 Handle 做其他的工作.

如果你的 key 的属性仅仅包含 NCRYPT_ALLOW_EXPORT_FLAG, 那意味着你不能将你的证书导出为明文. 此时,你需要将 NCryptExportKey 的第二个参数设置为一个非 NULL 的值. 个人觉得很麻烦, 如果您有相应的 code, 谢谢你分享给我!

一点儿个人经验, 如果你的 Key 是用户通过 CryptAPI 或者手工方式导入的 PFX, 在 Win10 平台上, 你的 Key 很可能只有 NCRYPT_ALLOW_EXPORT_FLAG 标记, 而不支持导出为明文. 如果我错了, 请告诉我!

导入 Key 到 Windows Store

很多时候, 我们不总是直接使用系统创建 Key, 而是使用我们现有的 Key. 那么, 当你想让你的 Key 和 CNG API 一起工作的时候, 导入你的 Key 到系统中将是一个必须的工作. 注意, 我们这里给出的例子会将 Key 保存到系统中. 如果你仅仅想要获取 Key Handle 而不将 Key 导入到 KSP 中, 只需要不设置 Key name 就行了.

这里我们将会将 PKCS8 格式的 Key 导入到系统中, 如果你的 Key 是另外的格式, 你有两个选择: 将他转换成 PKCS8 格式然后使用下面方法导入 或者 寻找其他可用的方法.

这里有两点值得一提:
<code>NCryptBufferDesc *pParameterList</code> 该参数可以用来设置 Key 的参数信息. 这里我们使用该参数来指定将要导入到系统中的 Key 的名称. 如果专门设置 Key 名称, 该 Key 将会是一个临时的 Key, 就不会被存储在 Window 中.
<code>DWORD dwFlags</code> 如果需要在导入 Key 之后设置 Key 的属性, 那你需要在这个参数中包含 NCRYPT_DO_NOT_FINALIZE_FLAG 标记. 例子中我们在导入 Key 之后, 需要设置 Key 的 NCRYPT_EXPORT_POLICY_PROPERTY 属性, 因此我们使用了 NCRYPT_DO_NOT_FINALIZE_FLAG 标记. 如果你未使用 NCRYPT_DO_NOT_FINALIZE_FLAG, 就不要额外的调用 NCryptFinalizeKey 方法, 否则, 请记得调用 NCryptFinalizeKey 方法.

int ImportKey() {BYTE blob[] = { 0x30,0x82,0x04,0xbd,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x82,0x04,0xa7,0x30,0x82,0x04,0xa3,0x02,0x01,
0x00,0x02,0x82,0x01,0x01,0x00,0xad,0xaa,0x8c,0x75,0x51,0x15,0x23,0x55,0xc7,0xec,0x7f,0x0b,0x85,0xf9,0x4b,0x18,0x10,0x60,0xdb,0x3d,0xc2,0xd2,0xcf,0xa6,0x8d,0x09,
0x8a,0xc9,0x7a,0x0e,0x80,0xb8,0x60,0x5a,0x20,0xe7,0xcb,0x52,0x33,0xc0,0xa3,0xc8,0x33,0x05,0xb0,0x45,0x34,0x49,0x59,0x0d,0xff,0xed,0xe5,0xe9,0x42,0xc4,0x05,0x82,
0x1a,0x92,0x67,0x24,0xea,0xc6,0x2a,0x07,0x67,0x07,0x65,0xa9,0xb8,0xe8,0x25,0xa2,0x16,0xe5,0x47,0xf2,0x79,0x98,0xcd,0x7c,0xce,0xbc,0x28,0x95,0x5f,0x9a,0xcd,0x70,
0x30,0xbb,0x7c,0xc9,0xc1,0x55,0xac,0x06,0x42,0xa8,0x86,0x78,0x47,0x69,0xa0,0xfb,0x5e,0x10,0x01,0xe4,0x3a,0xbc,0x09,0xb3,0xfd,0x3f,0x3d,0x3c,0x47,0xe7,0xd2,0x8f,
0xaf,0x2f,0x04,0x38,0x74,0xdc,0x3b,0x74,0x31,0xfb,0x55,0x39,0x94,0xeb,0xe3,0x7c,0x17,0x8d,0x51,0x50,0xa2,0x25,0x87,0x4b,0xfb,0xd2,0x3c,0xb6,0x70,0x45,0xd1,0x55,
0xb0,0x8e,0x9d,0x24,0xcb,0xd7,0xa0,0xc2,0xdd,0xfa,0x7b,0xa4,0x3f,0xd3,0xbe,0x7e,0x09,0x87,0x46,0x37,0xda,0x29,0x7c,0x95,0x85,0x0d,0x6d,0xfc,0xbf,0xbf,0x41,0xbe,
0x79,0x2c,0x83,0x87,0x1b,0x6f,0x24,0x8a,0x60,0x85,0x36,0xf6,0xcb,0x63,0x0c,0x66,0x16,0x0b,0x97,0x4a,0xdc,0xdb,0x91,0x0d,0xf9,0x1d,0x7e,0xae,0xbc,0xd9,0x77,0x39,
0x38,0x3e,0x7b,0x04,0x92,0x71,0x94,0x18,0x66,0xc8,0x77,0x5e,0x5c,0x42,0x16,0xc7,0x18,0x61,0x5a,0xdd,0x4f,0xaf,0x77,0x9a,0x14,0xba,0x39,0x98,0x22,0x73,0x49,0xfa,
0x73,0x2b,0x6d,0x0c,0x3b,0x27,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01,0x00,0x2b,0xd2,0xef,0xe2,0xe2,0xf5,0x2c,0x97,0x86,0xfd,0xdd,0x09,0x71,0x63,0x79,0x59,0xb7,
0x38,0x59,0xda,0xfa,0x00,0xec,0xb9,0xa0,0xb9,0x99,0xb6,0x42,0x00,0xca,0xe6,0xbc,0x19,0xc2,0x57,0xfb,0xec,0xe0,0x76,0x6a,0x5e,0x28,0xd1,0xf4,0xab,0x62,0x08,0x68,
0x5a,0xaa,0x0c,0xc4,0x89,0xda,0x79,0x50,0xd2,0x86,0x16,0x0f,0xc5,0x37,0x21,0x8e,0x95,0x93,0xa0,0x40,0x3d,0x56,0x15,0xee,0xf9,0x3a,0x41,0xdd,0xa8,0x08,0x9b,0x50,
0xaf,0x80,0x13,0xe7,0x41,0xda,0x80,0x5b,0xfb,0x45,0xb0,0xea,0x4a,0x97,0x69,0x21,0x21,0xeb,0x4c,0x4f,0xb2,0xa6,0x82,0xb7,0x46,0xf7,0x73,0x9e,0xa6,0x93,0x53,0xc4,
0x37,0x11,0x5f,0x15,0xfa,0xd2,0x42,0x63,0xd6,0x32,0x64,0xf0,0xf1,0xb6,0x3b,0x3a,0xb2,0xc8,0x25,0xc3,0x80,0xa1,0xa3,0xe7,0xb4,0x35,0xab,0x13,0xa9,0x3a,0x40,0xd1,
0x16,0xf6,0x63,0x62,0x62,0xeb,0x7c,0x58,0x4f,0x56,0x94,0xde,0x28,0x8a,0x48,0xc6,0xf0,0x3b,0x88,0x01,0xd3,0x8b,0xc6,0x0b,0x17,0x01,0x10,0x28,0x00,0x9c,0xd0,0x80,
0xc2,0xe8,0x00,0xdc,0x6b,0x37,0x39,0x1c,0xef,0x78,0x34,0x1d,0x49,0x12,0xd4,0x66,0x88,0x20,0x87,0xe2,0x1e,0x2b,0x05,0x26,0x8a,0xa7,0xd0,0x3d,0xe7,0xd0,0x47,0xed,
0xbe,0x1f,0xec,0xd6,0xa1,0xd3,0xe2,0x0e,0xb5,0xe5,0x3c,0xc2,0x83,0x69,0x77,0x36,0x9d,0x80,0x2b,0xe9,0xe1,0x14,0xe0,0xd5,0x27,0x62,0x35,0xc1,0x40,0xc6,0xf2,0x6e,
0xdb,0xc1,0x58,0xb8,0x9c,0xbc,0x83,0x36,0x81,0xfb,0x70,0xae,0x0c,0x5c,0xc1,0x02,0x81,0x81,0x00,0xd2,0x5f,0x19,0x94,0x11,0xb8,0xdc,0x77,0x2e,0x93,0x15,0x50,0x09,
0xa9,0x20,0xf0,0x1b,0xd1,0x3d,0x4a,0x1d,0x2c,0xb6,0x98,0xec,0x11,0xf1,0xe8,0xa0,0x85,0x4c,0xf8,0x14,0x27,0x80,0x26,0xff,0x78,0xa1,0x17,0x52,0xa3,0xbf,0xf6,0xc6,
0x86,0xab,0xca,0x5f,0x1e,0x5e,0x8f,0x78,0x5e,0x71,0x7d,0x2c,0x57,0xbe,0xda,0x80,0xa2,0x8b,0x6a,0x88,0xab,0xcd,0x78,0xc3,0x67,0xf6,0xb5,0x60,0x96,0x5c,0x24,0xac,
0x8c,0x4b,0x77,0x36,0xe2,0x97,0x16,0x87,0x6a,0x03,0xa7,0x36,0x4a,0xdf,0x5d,0xc3,0x6f,0x1f,0x60,0xfd,0x40,0x60,0x0e,0xca,0xb9,0x25,0x37,0xfa,0x50,0xc3,0x82,0x2f,
0x3a,0xeb,0x1b,0xd5,0xe0,0x6f,0x13,0x17,0x7d,0xa4,0xd2,0x97,0xe7,0xd7,0xbb,0x32,0x84,0x1e,0x77,0x02,0x81,0x81,0x00,0xd3,0x55,0x62,0x53,0x35,0x29,0xa5,0x68,0x65,
0x28,0x74,0x16,0x30,0x66,0x3e,0x95,0x8e,0xc6,0xb1,0xdd,0x37,0xae,0x69,0xe7,0xc8,0x62,0x81,0x11,0x57,0x57,0x92,0x2b,0xd8,0x21,0x98,0xf4,0x3f,0xe6,0x6e,0xd1,0x5d,
0xff,0x6f,0x90,0x6b,0x9e,0x68,0x47,0x50,0x6e,0xdf,0x5a,0x12,0x49,0x04,0xe9,0x42,0x7f,0xe1,0x3e,0x05,0x0a,0xa3,0xee,0xca,0xeb,0x40,0x4b,0x89,0x2a,0xa1,0x3c,0x2e,
0xa5,0xad,0xa8,0xc9,0x5e,0xa7,0x70,0x55,0x3f,0x04,0x1d,0x17,0xcb,0xca,0x21,0xf5,0xc3,0x68,0x68,0xb9,0x50,0x98,0xd3,0x3a,0x2c,0x29,0x21,0x3b,0x42,0x12,0x92,0x34,
0xda,0xc5,0xbb,0x0c,0xb2,0xb4,0x86,0x6a,0x4e,0x3f,0x43,0x99,0xc4,0xb7,0x85,0x97,0x36,0x75,0x61,0x28,0xd6,0x84,0xd1,0x02,0x81,0x80,0x36,0x9b,0xa1,0x14,0x22,0x95,
0x8e,0x05,0x11,0xfd,0xf4,0x26,0x56,0x9b,0xa4,0x85,0x2f,0x73,0x5d,0x29,0x83,0xf1,0x3b,0x64,0xee,0xc2,0xa9,0xbc,0xed,0x0e,0x2d,0x30,0xa8,0x6a,0xa8,0x85,0x77,0x03,
0x65,0x2d,0x9c,0xb2,0x0c,0xfe,0x8e,0x02,0x1f,0x4d,0xe4,0xeb,0x09,0x38,0xcc,0xd2,0x17,0x3b,0x9a,0xeb,0x1c,0x0b,0xb4,0x20,0x7d,0x78,0x26,0x0a,0x12,0xc8,0x2a,0x51,
0x2e,0x65,0x5e,0xb1,0x29,0x32,0x0b,0xe8,0x4f,0x1e,0x9f,0x0c,0xaa,0x93,0x9a,0x8b,0x16,0x6f,0xad,0x54,0x3a,0x2f,0x28,0xb0,0x0b,0xc1,0x2d,0x7c,0x2c,0x73,0x2a,0x84,
0x6c,0xf8,0xde,0xed,0x60,0x12,0xc7,0x17,0xd0,0x37,0xe5,0x88,0xe0,0xcc,0x5f,0xe8,0xa9,0x84,0x51,0x12,0x49,0x99,0xba,0x3f,0x39,0x79,0x02,0x81,0x80,0x74,0x65,0x92,
0xc2,0x41,0x85,0xae,0x94,0xd1,0x22,0x76,0xcd,0xc1,0xda,0x8e,0x9d,0xd1,0x05,0x9e,0xf1,0x38,0xb9,0xd7,0x9a,0xd1,0xc3,0x6f,0x53,0x1d,0xc8,0x1d,0xba,0x08,0x50,0x78,
0xee,0x0e,0x43,0xdc,0xc5,0x74,0x00,0x3c,0x72,0x4e,0xd3,0xf0,0x9b,0x56,0xb1,0xba,0x52,0xe1,0xbf,0x55,0xf5,0x23,0xab,0x4b,0x63,0xdd,0x62,0xfe,0xe7,0x86,0xdc,0x0b,
0x8d,0x8e,0xfe,0xeb,0xcf,0x39,0xe2,0x06,0xc3,0xf0,0x25,0x32,0x13,0xac,0xe0,0x08,0x63,0xfd,0xb7,0x40,0x9d,0x73,0xbf,0x2c,0xc2,0x81,0x4e,0xe2,0xdd,0x74,0x2c,0xde,
0x7a,0x6f,0x28,0xf5,0x11,0x92,0x0a,0xec,0xdd,0x19,0x21,0x54,0x4c,0xb4,0x40,0x64,0x97,0xd7,0x19,0x81,0xfb,0x12,0x4d,0xec,0x58,0x97,0x25,0x90,0x01,0x02,0x81,0x81,
0x00,0x9d,0xf3,0x78,0x3e,0x39,0xb6,0x45,0x97,0x2d,0xb2,0xf2,0xdb,0xe3,0xa8,0xe9,0x8e,0x58,0xd7,0x6b,0xfb,0x11,0x25,0x77,0x6b,0xd5,0xd6,0x61,0x39,0xbb,0x04,0x15,
0xc2,0x7d,0xf9,0xc7,0xf1,0x1a,0xce,0xe5,0x40,0x84,0x26,0x83,0x13,0xb4,0x41,0x49,0xa2,0x42,0x71,0x3c,0xed,0x72,0x17,0xa9,0x2a,0x85,0x25,0xea,0x5b,0xf3,0x6e,0xd6,
0x5b,0x49,0xc8,0xda,0xe4,0xaa,0xa4,0xa5,0x96,0x31,0xaa,0x7e,0x10,0xd7,0x8a,0xf8,0x16,0xe0,0xe0,0x21,0x64,0x22,0xfb,0x1c,0x74,0x27,0xbe,0xf7,0x0f,0x0c,0x94,0x4b,
0x47,0xf4,0xfe,0x58,0xe1,0x72,0xb1,0x08,0xac,0x93,0xb5,0x06,0x29,0x78,0xb8,0xb3,0xf8,0xd4,0x2f,0x4e,0x43,0x3a,0x0c,0x14,0x8b,0x00,0xd2,0xd5,0x21,0x93,0x8c,0x5d,
0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };DWORD blobLen = 0x4c1;int errCode = 0;NCRYPT_PROV_HANDLE prov = NULL;NCRYPT_KEY_HANDLE  key = NULL;DWORD policy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;LPCWSTR name = L"ImportedKey";BCryptBuffer cb[1];cb[0].BufferType = NCRYPTBUFFER_PKCS_KEY_NAME;cb[0].pvBuffer = (void*)name;cb[0].cbBuffer = lstrlenW(name) * 2 + 2;NCryptBufferDesc desc;desc.ulVersion = 0;desc.pBuffers = cb;desc.cBuffers = 1;if (errCode = NCryptOpenStorageProvider(&prov, MS_KEY_STORAGE_PROVIDER, 0)) goto done;if (errCode = NCryptImportKey(prov, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, &desc, &key, blob, blobLen, NCRYPT_DO_NOT_FINALIZE_FLAG)) goto done;if (errCode = NCryptSetProperty(key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)(&policy), sizeof(policy), NCRYPT_PERSIST_FLAG)) goto done;if (errCode = NCryptFinalizeKey(key, 0)) goto done;done:if (prov) NCryptFreeObject(prov);if (key) NCryptFreeObject(key);return errCode;
}

导入完成之后, 可以使用 ListKeys 检查你的导入是否成功了.

END!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang 词法分析器浅析

浅析 Go 语言的词法分析器 章节目录 简介TokenScanner例子 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介## 在本文我们将简单的走读 Go 语言的词法分析器实现(go/scanner/scanner.go). 本文基于 G…

如何读懂 C 语言复杂的声明

如何读懂 C 语言复杂的声明 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 参考<<C专家编程>> 废话 虽说 C 语言相比于其他更高级的语言来讲&#xff0c;有着非常精简的语法结构&#xff0c;对…

C 语言笔记: 链表节点实现技巧--struct的妙用

链表节点实现技巧–struct的妙用 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 废话 C 语言虽然只提供了非常简单的语法&#xff0c;但是丝毫不影响 C 语言程序员使用 C 来实现很多让人叹为观止的高级功能…

协议簇: Media Access Control(MAC) Frame 解析

Media Access Control(MAC) Frame 解析 前言 千里之行&#xff0c;始于足下。 因为个人从事网络协议开发&#xff0c;一直想深入的学习一下协议族&#xff0c;从这篇开始&#xff0c;我将开始记录分享我学习到的网络协议相关的知识 简介 引用百度百科的描述&#xff1a; 数…

协议簇:Ethernet Address Resolution Protocol (ARP) 解析

简介 前面的文章中&#xff0c;我们介绍了 MAC Frame 的帧格式。我们知道&#xff0c;在每个 Ethernet Frame 中都分别包含一个 48 bit 的源物理地址和目的物理地址. 对于源地址很容易理解&#xff0c;该地址可以直接从硬件上读取. 但是对于一个网络节点&#xff0c;他怎么知道…

协议簇:IPv4 解析

简介 IP 是一种无连接的协议. 操作在使用分组交换的链路层&#xff08;如以太网&#xff09;上。此协议会尽最大努力交付数据包。 尽最大努力意味着&#xff1a; IP 协议不保证数据的可靠传输, 没有流量控制机制, 不保证传输序列(意味着 IP 数据包会在传输过程中乱序), 没有…

协议簇:ICMP 解析

简介 ICMP 是 Internet Control Message Protocol 的简写. 它主要用来调试网络通信环境中存在的问题. 比如&#xff0c;当 IP 数据包总是无法正常的发送到目的地址, 当网关没有足够的 buffer 来转发对应的数据包 等问题. 值得一提的是&#xff0c;它属于网络层&#xff0c;不属…

协议簇:TCP 解析: 基础

简介 本文我们将从 RFC 学习一下 RFC793 中描述的 TCP 协议. 这将区别于通常讲解计算机网络书籍中所描述的 TCP. 但他们必然是相统一的&#xff0c;不会互相冲突. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: 建立连接

简介 接前文 协议簇&#xff1a;TCP 解析: 基础&#xff0c; 我们这篇文章来看看 TCP 连接建立的过程&#xff0c;也就是众所周知的”三次握手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议簇&a…

协议簇:TCP 解析: 连接断开

简介 接前文 协议簇&#xff1a;TCP 解析: 建立连接&#xff0c; 我们这篇文章来看看 TCP 连接断开的过程&#xff0c;也就是众所周知的”四次挥手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: Sequence Number

简介 序列号&#xff08;Sequence Number&#xff09; 是 TCP 协议中非常重要的一个概念&#xff0c;以至于不得不专门来学习一下。这篇文章我们就来解开他的面纱. 在 TCP 的设计中&#xff0c;通过TCP协议发送的每个字节都对应于一个序列号. 由于每个字节都有自己的序列号&a…

协议簇:TCP 解析:TCP 数据传输

简介 前面&#xff0c;我们分别介绍了 TCP 基础知识以及连接的建立和关闭&#xff0c;以及最重要的 Sequence Number 的概念. 本篇文章&#xff0c;我们来介绍一下 TCP 如何传输数据. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&…

CodeTank iOS App Technical Support

CodeTank iOS App Technical Support For All Email: z253951598outlook.com TEL: 86-17782749061 App Screen Shoots

CentOS 7 防火墙命令

查看防火墙状态 systemctl status firewalld如果已经开启&#xff0c;状态为 active 如果未开启&#xff0c;状态为 inactive 开启防火墙 systemctl start firewalld关闭防火墙 systemctl stop firewalld查看当前防火墙的配置 firewall-cmd --list-all这里&#xff0c;我…

Go Concurrency Patterns: Context

Go Concurrency Patterns: Context 原文地址&#xff1a;https://blog.golang.org/context Introduction 在 Go 语言实现的服务器上&#xff0c;我们总是使用 goroutine 来处理与客户端建立的连接&#xff0c; 给每个连接分配一个独立的 goroutine. 在请求的 handler 中也通常…

Go Concurrency Patterns: Timing out, moving on

原文地址&#xff1a;https://blog.golang.org/concurrency-timeouts 并发变成有它自己的风格. 一个非常好的例子就是 timeout. 虽然 go 的 channel 没有直接支持 timeout 机制&#xff0c;但是要实现它非常容易. 比如说&#xff0c;我们想从一个 channel ch 中接收数据&#…

Go Concurrency Patterns: Pipelines and cancellation

原文地址&#xff1a; https://blog.golang.org/pipelines 简介 Go 语言提供的并发原语使得可以很方便的构建数据流 pipeline&#xff0c;使用这样的 pipeline 可以高效的利用 I/O 和多 cpu 的优势. 这篇文章我们将展示如何构建并使用 pipeline. 什么是 pipeline ? 在 go 语…

QTcpSocket connectToHost 建立连接速度慢问题

问题场景 在使用 QT 开发一个客户端 App 的时候&#xff0c;我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题&#xff1a; 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候&#xff0c;发现连接速度非常慢&#xff08;肉眼可见的慢&#x…

WinSock I/O 模型 -- Select 模型

简介 Select 模型是 WinSock 中最常见的 I/O 模型&#xff0c;这篇文章我们就来看看如何使用 Select api 来实现一个简单的 TCP 服务器. API 基础 Select 模型依赖 WinSock API Select 来检查当前 Socket 是否可写或者可读。 使用这个 API 的优点是我们不需要使用阻塞的 So…

WinSock I/O 模型 -- WSAEventSelect 模型

简介 WSAEventSelect 模型也是 WinSock 中最常见的异步 I/O 模型。 这篇文章我们就来看看如何使用 WSAEventSelect api 来实现一个简单的 TCP 服务器. API 基础 WSAEventSelect WSAEventSelect 用来把一个 SOCKET 对象和一个 WSAEVENT 对象关联起来。 lNetworkEvents 表示…