【问题标题】:How to use BouncyCastle's Diffie-Hellman in C#?如何在 C# 中使用 BouncyCastle 的 Diffie-Hellman?
【发布时间】:2021-10-14 09:16:40
【问题描述】:

我正在编写一个在手机和 Windows PC 之间交换数据的应用程序,我想保护使用 Diffie-Hellman 交换生成的密钥发送的数据。

我正在尝试为此使用 BouncyCastle,但几乎不存在的 C# 实现文档让我感到困惑。

我想知道的是:当收到对方的密钥时,生成DH密钥和计算共享密钥的工作流程是什么? (我假设我可以将我的密钥作为字符串发送,并且我可以将另一方的密钥作为字符串使用。)为此我在 C# 中使用哪些对象/方法?

【问题讨论】:

    标签: c# bouncycastle diffie-hellman


    【解决方案1】:

    好的,经过大量的试验,我得到了它的工作。发布答案以防其他人需要。

    我假设读者 (1) 知道 Diffie-Hellman 是什么以及它有什么用处(详情请阅读 here)并且 (2) 已经通过 NuGet 将 Bouncycastle 导入到 .NET 项目中。

    您需要的进口商品:

    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Generators;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    

    如何生成g和p:

    public DHParameters GenerateParameters()
    {
        var generator = new DHParametersGenerator();
        generator.Init(BitSize, DefaultPrimeProbability, new SecureRandom());
        return generator.GenerateParameters();
    }
    

    想要将 g 和 p 作为字符串?

    public string GetG(DHParameters parameters)
        {
            return parameters.G.ToString();
        }
    
    public string GetP(DHParameters parameters)
        {
            return parameters.P.ToString();
        }
    

    如何生成a和A:

    public AsymmetricCipherKeyPair GenerateKeys(DHParameters parameters)
        {
        var keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
        var kgp = new DHKeyGenerationParameters(new SecureRandom(), parameters);
        keyGen.Init(kgp);
        return keyGen.GenerateKeyPair();
    }
    

    想将 a 和 A 读取为字符串吗?

    // This returns A
    public string GetPublicKey(AsymmetricCipherKeyPair keyPair)
    {
        var dhPublicKeyParameters = _generatedKey.Public as DHPublicKeyParameters;
        if (dhPublicKeyParameters != null)
        {
            return dhPublicKeyParameters.Y.ToString();
        }
        throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
    }
    
    // This returns a
    public string GetPrivateKey(AsymmetricCipherKeyPair keyPair)
    {
        var dhPrivateKeyParameters = _generatedKey.Private as DHPrivateKeyParameters;
        if (dhPrivateKeyParameters != null)
        {
            return dhPrivateKeyParameters.X.ToString();
        }
        throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
    }
    

    要从字符串中导入参数,只需这样做:

    var importedParameters = new DHParameters(p, g);
    

    要生成 b 和 B,只需使用 GenerateKeys()importedParameters,而不是生成的 parameters

    假设您生成了 b 和 B,并且已经得到了 p、g 和 A。要计算共享密钥:

    public BigInteger ComputeSharedSecret(string A, AsymmetricKeyParameter bPrivateKey, DHParameters internalParameters)
    {
        var importedKey = new DHPublicKeyParameters(new BigInteger(A), internalParameters);
        var internalKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
        internalKeyAgree.Init(bPrivateKey);
        return internalKeyAgree.CalculateAgreement(importedKey);
    }
    

    对 A 重复操作,现在您在 2 个客户端之间拥有了一个共享密钥,可用于加密通信。

    希望这是有用的。

    【讨论】:

    • 恭喜你有一些唯一不错的东西,因为有人试图用这么少的文档来做一些基本的东西......你是一位绅士和学者,你将这些细节添加到你自己的问题:-)
    • 如何生成openssl dhparam -out dhparam.pem 2048的等价物?
    【解决方案2】:

    基于PEM文件格式BouncyCastle.Diffie-hellman的Diffie-Hellman密钥协议实现

    Example
    // Public Key Alice
    var pubAlice = @"-----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOkLo3q6MN3XS5xlY3OowqMkvPrYz
    j4hLVJ2Wkuob3KQb1QidaAQsJ6Azy0yTuBanL4iy+dewA3YjejBMZEoh6w==
    -----END PUBLIC KEY-----
    ";
    // EC-Private Key Alice
    var priAlice = @"-----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIC9LMxwIwKThjtaUAJbJBCU0vFa+H8G98p/Z9JLYmEehoAoGCCqGSM49
    AwEHoUQDQgAEOkLo3q6MN3XS5xlY3OowqMkvPrYzj4hLVJ2Wkuob3KQb1QidaAQs
    J6Azy0yTuBanL4iy+dewA3YjejBMZEoh6w==
    -----END EC PRIVATE KEY-----
    ";
    
    // Public Key Bob
    var pubBob = @"-----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnDMGlBFH7jbHHAYgdPR7247xqzRF
    Y1HFy4HfejSgUKBxgj6biZUwSbNKuino7ObZnqrnJayWJZ7f4Eb6XuT6yQ==
    -----END PUBLIC KEY-----
    ";
    
    // EC-Private Key Bob
    var priBob = @"-----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIGqA4f7o5oBF5FgEQtNmz6fWKg/OcPPUORMX3uRc7sduoAoGCCqGSM49
    AwEHoUQDQgAEnDMGlBFH7jbHHAYgdPR7247xqzRFY1HFy4HfejSgUKBxgj6biZUw
    SbNKuino7ObZnqrnJayWJZ7f4Eb6XuT6yQ==
    -----END EC PRIVATE KEY-----
    ";
    
    var secretAlice = DiffieHellmanKeyAgreementUtil.GetPairKey(priAlice, pubBob);
    var secretBob = DiffieHellmanKeyAgreementUtil.GetPairKey(priBob, pubAlice);
    
    Console.WriteLine($"secretAlice: {secretAlice}");
    Console.WriteLine($"secretBob: {secretBob}");
    

    输出 秘密爱丽丝:RGZcMLnsXJqbQ/JGIIl61l/XpIgSL43Ync+16YKyMuQ= 秘密鲍勃:RGZcMLnsXJqbQ/JGIIl61l/XpIgSL43Ync+16YKyMuQ=

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多