章节目录

  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!

CNG 关于 Key 相关的操作相关推荐

  1. Redis操作key相关API

    private Jedis jedis;@Beforepublic void before(){this.jedis = new Jedis("192.168.202.205", ...

  2. Redis key 相关命令

    其实本质上,Redis 就是一个Key---Value 数据库.这里我先介绍下Redis中关于的key的相关命令, 注意:key是字符串存储,但是不能使用 空格 或者 "\n",v ...

  3. php redis命令大全,redis中key相关命令详解

    一.概述: 本文将主要讲述与Key相关的Redis命令.学习这些命令对于学习Redis是非常重要的基础,也是能够充分挖掘Redis潜力的利器.(推荐:redis视频教程) 二.相关命令列表: 命令原型 ...

  4. java 面向对账 抽象_java开发银行支付、对账时证书相关的操作实例

    java 开发银行支付.对账时证书相关的操作总结. 证书的相关操作主要是在CMD窗口使用keytool工具Keytool 是一个Java数据证书的管理工具 ,Keytool将密钥(key)和证书(ce ...

  5. 算法—二叉查找树的相关一些操作及总结

    二叉查找树得以广泛应用的一个重要原因就是它能够保持键的有序性,因此它可以作为实现有序符号表API中的众多方法的基础.这使得符号表的用例不仅能够通过键还能通过键的相对顺序来访问键值对.下面,我们要研究有 ...

  6. Linux中和文件相关的操作

    Linux中和文件(/文件夹)相关的操作 1. 文件:删除.复制.移动.创建链接 2. 文件的解压 和 压缩 3. 文件:列举查看.大小查看.个数统计 3.1 `ls`:文件列举查看 3.2 `ls. ...

  7. Boost:与gz文件相关的操作实例

    Boost:与gz文件相关的操作实例 实现功能 C++实现代码 实现功能 与gz文件相关的操作实例,打开,关闭,读写. C++实现代码 #include "zstream.h" # ...

  8. 拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

     1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: ...

  9. TensorFlow(3)-与训练相关的操作

    与训练相关的操作 0 gpu版本的tensor flow安装 1. tf.control_dependencies(update_ops) 0 gpu版本的tensor flow安装 cuda10.2 ...

最新文章

  1. 面试官:连YOLO都搞不定,是自己走还是我送你
  2. MySQL学习(二)复制
  3. AI设计师“鲁班”进化史:每秒制作8000张双11海报,没一张雷同!
  4. 原生php实现账单功能
  5. CSDN活跃榜 2019-5-22
  6. php事件编程,PHP相应button中onclick事件的案例分析
  7. Netty工作笔记0034---Netty架构设计--线程模型
  8. 1.RESTful Web APIs中文版 --- 网上冲浪
  9. 如何用html放音乐播放器,如何用html+js实现音乐歌词同步播放器
  10. 使用安全浏览器将网页保存为pdf的方法步骤
  11. MySQL命令执行脚本文件
  12. 4.3检测CSRF漏洞
  13. 线程typedef UINT (_cdecl* AFX_THREADPROC)(LPVOID)类型转换无效
  14. 【翻唱】学习日语歌 (青鸟)火影忍者 OP
  15. 概率论_证明_伯努利大数定律
  16. day19-爬虫和前端
  17. Java调用热敏票据打印机打印小票
  18. spring开发_邮箱注册_激活_获取验证码
  19. 第二篇:java调用公共数据接口:上海市车辆基本信息查询(java调用soap接口)
  20. UGC发垃圾机制和内容审核

热门文章

  1. Pycharm简单配置及详细快捷键介绍
  2. Git中的bash与CMD的区别
  3. ABP文档翻译--值对象
  4. (算法)宝石升级问题
  5. winform TreeView树节点上下移动
  6. [唐胡璐]Excel技巧 - 使用Excel 2007完成多人协同录入工作
  7. 【数据采集】将16进制字符串转化为Double类型输出(依照IEEE754标准)
  8. golang 升级到新版本_Scikit-learn新版本发布,一行代码秒升级
  9. 6种java垃圾回收算法_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...
  10. 中希尔排序例题代码_超全面分析十大排序算法