0

我正在尝试使用 CryptoAPI (CAPI) 来执行 Diffie Hellman 密钥交换。我正在使用 MSDN 文档。

        // Step 0) Acquire context
        if (!CAPI.CryptAcquireContext(ref this._cryptographicProvider, null, null, CAPI.PROV_DSS_DH, CAPI.CRYPT_VERIFYCONTEXT))
            HandleWin32Error("Unable to acquire cryptographic context");

        // Setp 1) Generate private key
        if (!CAPI.CryptGenKey(this._cryptographicProvider, CAPI.CALG_DH_EPHEM, DHKEYSIZE << 16 | CAPI.CRYPT_EXPORTABLE | CAPI.CRYPT_PREGEN, ref this._privateKeyPointer))
            HandleWin32Error("Unable to generate private cryptographic key");

        uint gSize = 0;
        CAPI.CryptGetKeyParam(this._privateKeyPointer, CAPI.KP_G, null, ref gSize, (uint)0);

        byte[] g = new byte[gSize];
        var res = CAPI.CryptGetKeyParam(this._privateKeyPointer, CAPI.KP_G, g, ref gSize, (uint)0);

第一次调用 CryptGetKeyParam 完美运行,即成功返回 g 的大小,为 64。

然后代码在最后一行失败,要么通过 res = true 不向 g 缓冲区返回任何内容(如该示例中的情况),要么在我使用以下调用时使用 AccessViolationException:

var res = CAPI.CryptGetKeyParam(this._privateKeyPointer, CAPI.KP_G, ref g, ref gSize, (uint)0);

是的,我已经重载了 P\Invoke 方法:

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptGetKeyParam(IntPtr hKey, uint dwParam, ref byte[] pbData, ref uint pdwDataLen, uint dwFlags);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptGetKeyParam(IntPtr hKey, uint dwParam, byte[] pbData, ref uint pdwDataLen, uint dwFlags);

对此有任何想法/想法吗?

*有趣的是,我已经设法让一个完整的 Diffie Hellman 密钥交换工作,即成功地在两方之间同意相同的秘密 (s1)。但这是使用预定义的 P 和 G 参数。我正在重新编写代码,因为有些东西似乎不正确,因为每次密钥交换的派生秘密都是相同的,这意味着 X 是一致的。(即 Bob 和 Alice 每次都同意 s1!?) - 在这里,我再次遇到了 CryptGetKeyParam 的问题,因为我在使用 KP_KEYLEN 时无法确定会话密钥的大小?!*

4

1 回答 1

1

啊哈!

它是上下文标志和重载方法的组合......现在可以工作了!

如果没有预定义 P & G,则不要设置 CRYPT_PREGEN 标志......并且只需要两个重载方法之一(这个):

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptGetKeyParam(IntPtr hKey, uint dwParam, byte[] pbData, ref uint pdwDataLen, uint dwFlags);
于 2010-08-03T09:36:56.347 回答