CNG:何时使用 BCrypt* 与 NCrypt* 函数系列

CNG: When to use BCrypt* vs NCrypt* family of functions

在 Microsoft CNG API(密码学 API:下一代)中,有两组函数看起来做同样的事情。

以下函数以BCrypt开头并执行密钥import/export、encryption/decryption、sign/verify和Diffe-Helman密钥交换

BCryptExportKey
BCryptImportKey
BCryptEncrypt
BCryptDecrypt
BCryptSignHash
BCryptVerifySignature
BCryptSecretAgreement
BCryptDeriveKey

但存在以 NCrypt:

开头的同一组函数
NCryptExportKey
NCryptImportKey
NCryptEncrypt
NCryptDecrypt
NCryptSignHash
NCryptVerifySignature
NCryptSecretAgreement
NCryptDeriveKey

这两组函数有什么区别,分别应该在什么时候使用?

BCrypt 函数族分类为 Cryptographic Primitives, while the NCrypt family of functions are classified as Key Storage and Retrieval.

主要区别在于 BCrypt 函数仅在处理临时键时使用,而 NCrypt 函数在需要持久键时使用。

实际上,BCrypt函数通常用于散列和对称加密,而NCrypt函数用于public/private密钥加密和解密,public/private密钥签名和验证,以及共享秘密(例如 DH 和 ECDH)协商。

虽然一些 public/private 键操作可以用 BCrypt 函数完成,但它们只能与临时键一起使用,因此用途有限。

永久密钥存储在特定于每个用户(或系统)的密钥容器中。这是一项安全措施,可确保用户无法查看彼此的私钥。

一般来说,您需要使用以下函数进行以下操作:

  • BCryptHashData:用于哈希和HMAC(MD5、SHA1、SHA256、SHA384、SHA512)
    • 相关:BCryptCreateHashBCryptFinishHashBCryptDestroyHash
  • BCryptEncrypt:对称密钥加密(DES、3DES、AES)。
    • 相关:BCryptGenerateSymmetricKeyBCryptDestroyKey
  • BCryptDecrypt:对称密钥解密(DES、3DES、AES)。
    • 相关:BCryptGenerateSymmetricKeyBCryptDestroyKey
  • NCryptEncrypt: 非对称密钥加密 (RSA)
  • NCryptDecrypt:非对称密钥解密(RSA)
  • NCryptSignHash:非对称密钥签名(RSA、DSA、ECDSA)
  • NCryptVerifySignature:非对称密钥签名验证(RSA、DSA、ECDSA)
  • NCryptSecretAgreement:非对称密钥秘密共享(DH、ECDH)
    • 相关:NCryptDeriveKey

MSDN 上提供了其中几个案例的示例。

举个真实的例子,我在 UFTP 源代码中实现了所有这些,特别是 encrypt_cng.c 文件(有 typedef,在 encryption.h 中定义, 以允许此文件中的函数实现通用应用程序级别 API 以允许使用其他加密库,例如 CryptoAPI 和 OpenSSL)。

当您的应用程序内存中有密钥时,请使用 BCrypt* 函数。

将密钥存储在 KSP(密钥存储提供程序)中时使用 NCrypt* 函数。

NCrypt* 函数做了很多额外的工作并且效率较低,因此如果您不将密钥存储在 KSP 中,最好使用 BCrypt* 函数。

由于大多数长期存储的密钥都是非对称(RSA、ECDSA 等)密钥,因此 NCrypt* 函数更常用于非对称算法。 BCrypt* 通常用于非对称和对称算法。