You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BouncyCastle与.NET间Curve25519公钥导入失败问题排查

解决.NET与BouncyCastle Curve25519密钥交换的公钥导入异常问题

问题背景

自定义.NET的Curve25519曲线参数后,尝试导入BouncyCastle生成的公钥时,抛出System.Security.Cryptography.CryptographicException,错误提示“Key is not a valid public or private key”,无法确定是参数配置错误还是密钥格式不兼容。

问题原因分析

  1. 自定义曲线参数不符合.NET规范:手动定义的Curve25519参数可能存在字节序错误、参数缺失或与.NET内置解析逻辑不匹配的问题,导致.NET无法识别对应的曲线。
  2. 密钥格式不匹配:BouncyCastle导出的DER编码SPKI公钥,与.NET对Curve25519公钥的解析要求存在差异;或者手动传递的参数导致OID(对象标识符)不匹配,无法完成导入。

解决步骤

1. 放弃自定义曲线,使用.NET内置的X25519曲线

.NET Core 3.0+及.NET 5+已经内置了X25519的标准曲线参数,无需手动定义,直接调用内置曲线即可避免参数配置错误。

2. 调整公钥传递格式

BouncyCastle的X25519PublicKeyParameters可以直接导出原始32字节公钥,.NET通过ImportRawPublicKey方法直接导入该原始字节,避免SPKI格式的解析问题。

完整修正代码

// 移除自定义的Curve25519参数定义,直接使用.NET内置曲线

public void CrossCheck25519UsingBouncyCastleAndDotNet()
{
    // Step 1: Bob使用BouncyCastle生成密钥
    var randomGenerator = new SecureRandom();
    var bobPrivateKeyBouncy = new X25519PrivateKeyParameters(randomGenerator);
    X25519PublicKeyParameters bobPublicKeyBouncy = bobPrivateKeyBouncy.GeneratePublicKey();

    // Step 2: Bob发送原始32字节公钥给Alice
    byte[] bobPublicKeyBytes = bobPublicKeyBouncy.GetEncoded(); // 获取原始公钥字节

    // Step 3: Alice使用.NET内置X25519曲线生成密钥并导入公钥
    using(var alice = ECDiffieHellman.Create(ECCurve.NamedCurves.X25519))
    {
        // 导入原始公钥(替代ImportSubjectPublicKeyInfo)
        alice.ImportRawPublicKey(bobPublicKeyBytes, out _);

        // Alice计算共享密钥(修正参数:传入对方公钥而非自身公钥)
        byte[] aliceSharedSecret = alice.DeriveKeyFromHash(
            ECDiffieHellmanPublicKey.FromByteArray(bobPublicKeyBytes, ECCurve.NamedCurves.X25519), 
            HashAlgorithmName.SHA256
        );

        // Step 4: Alice导出自己的原始公钥给Bob
        byte[] alicePublicKeyBytes = alice.PublicKey.ExportRawPublicKey();

        // Step 5: Bob导入Alice的原始公钥
        var alicePublicKeyBouncy = new X25519PublicKeyParameters(alicePublicKeyBytes, 0);

        // Step 6: Bob计算共享密钥
        var bobAgreement = new X25519Agreement();
        bobAgreement.Init(bobPrivateKeyBouncy);
        byte[] bobSharedSecret = new byte[bobAgreement.AgreementSize];
        bobAgreement.CalculateAgreement(alicePublicKeyBouncy, bobSharedSecret, 0);

        // Step 7: 对比共享密钥(使用SequenceEqual做逐字节比较)
        Assert.True(bobSharedSecret.SequenceEqual(aliceSharedSecret));
    }
}

额外说明

  • 如果必须使用SPKI格式传递公钥,确保两端使用相同的OID(X25519的OID为1.3.101.110),BouncyCastle的SubjectPublicKeyInfoFactory生成的SPKI包含正确OID,此时.NET使用内置曲线后可直接用ImportSubjectPublicKeyInfo导入。
  • 原代码中DeriveKeyFromHash传入自身公钥是逻辑错误,需修正为对方的公钥。
  • 字节数组比较需用SequenceEqual,Assert.Equal默认对字节数组做引用比较,会导致断言失败。

内容的提问来源于stack exchange,提问作者Veksi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 14:00:53