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

OpenSSL与BouncyCastle C#的Ed25519ph密钥及签名兼容问题

Ed25519ph:OpenSSL与BouncyCastle(C# .NET 8)兼容性问题解决方案

一、密钥兼容问题解决

BouncyCastle默认生成的Ed25519私钥PEM是带额外公钥信息的PKCS#8 v1结构,导致OpenSSL读取失败的核心原因是OpenSSL对Ed25519私钥的默认解析逻辑更偏向于raw私钥格式(仅32字节私钥数据)或不含冗余公钥的标准PKCS#8结构。以下是两种可行解决方法:

  • 方法1:导出Raw私钥并封装为OpenSSL兼容PEM
    从BouncyCastle生成的Ed25519PrivateKeyParameters中提取32字节raw私钥数据,再按OpenSSL标准PEM格式封装:

    // 生成Ed25519密钥对
    var keyPairGenerator = new Ed25519KeyPairGenerator();
    keyPairGenerator.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
    var keyPair = keyPairGenerator.GenerateKeyPair();
    var privateKeyParams = (Ed25519PrivateKeyParameters)keyPair.Private;
    
    // 提取32字节Raw私钥
    byte[] rawPrivateKey = privateKeyParams.GetEncoded();
    
    // 封装为OpenSSL兼容PEM
    var pemWriter = new PemWriter(new StringWriter());
    pemWriter.WriteObject(new PemObject("PRIVATE KEY", rawPrivateKey));
    string privateKeyPem = pemWriter.Writer.ToString();
    

    生成的PEM可直接通过OpenSSL命令openssl pkey -in private.pem -text -noout读取。

  • 方法2:生成不含公钥的标准PKCS#8私钥
    使用Pkcs8Generator时跳过公钥属性添加,生成纯PKCS#8 v0结构:

    var pkcs8Gen = new Pkcs8Generator(privateKeyParams, null);
    pkcs8Gen.SetAlgorithmIdentifier(new AlgorithmIdentifier(X9ObjectIdentifiers.IdEd25519));
    var pkcs8 = pkcs8Gen.Generate();
    var pemWriter = new PemWriter(new StringWriter());
    pemWriter.WriteObject(pkcs8);
    string privateKeyPem = pemWriter.Writer.ToString();
    

二、签名验证问题解决

OpenSSL验证BouncyCastle生成的Ed25519ph签名失败,主要由以下原因导致:

  1. 未使用Ed25519ph专属签名器:必须用Ed25519phSigner而非普通Ed25519Signer,Ed25519ph要求先对消息做SHA-512预处理,普通签名器不执行此步骤。
  2. 上下文(Context)设置不规范:即便使用new byte[0]作为上下文,需确保BouncyCastle签名时通过ParametersWithContext明确传入,OpenSSL默认上下文为空,无需额外参数。
  3. 签名/消息格式不匹配:BouncyCastle生成的签名是64字节原始二进制,需导出为二进制文件而非Base64编码后给OpenSSL验证,同时保证验证消息与签名时的原始消息完全一致。

修改后的可运行C#代码

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System.IO;
using System.Text;

namespace Ed25519phCompatibility
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. 生成兼容OpenSSL的Ed25519密钥对
            var keyPair = GenerateCompatibleEd25519KeyPair();
            SavePemToFile("private_key.pem", keyPair.Private);
            SavePemToFile("public_key.pem", keyPair.Public);

            // 2. 生成Ed25519ph签名
            string message = "Test message for Ed25519ph compatibility";
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            byte[] signature = GenerateEd25519phSignature(messageBytes, (Ed25519PrivateKeyParameters)keyPair.Private);
            File.WriteAllBytes("signature.bin", signature);

            // 3. BouncyCastle本地验证签名
            bool isValid = VerifyEd25519phSignature(messageBytes, signature, (Ed25519PublicKeyParameters)keyPair.Public);
            System.Console.WriteLine($"BouncyCastle本地验证结果: {isValid}");

            // 输出OpenSSL验证命令
            System.Console.WriteLine("\nOpenSSL验证命令:");
            System.Console.WriteLine("openssl dgst -ed25519ph -verify public_key.pem -signature signature.bin message.txt");
            File.WriteAllText("message.txt", message);
        }

        private static AsymmetricCipherKeyPair GenerateCompatibleEd25519KeyPair()
        {
            var keyGen = new Ed25519KeyPairGenerator();
            keyGen.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
            return keyGen.GenerateKeyPair();
        }

        private static void SavePemToFile(string path, AsymmetricKeyParameter key)
        {
            using var writer = new StreamWriter(path);
            var pemWriter = new PemWriter(writer);
            pemWriter.WriteObject(key);
            pemWriter.Writer.Flush();
        }

        private static byte[] GenerateEd25519phSignature(byte[] message, Ed25519PrivateKeyParameters privateKey)
        {
            var signer = new Ed25519phSigner();
            // 设置空上下文,与OpenSSL默认一致
            signer.Init(true, new ParametersWithContext(privateKey, new byte[0]));
            signer.BlockUpdate(message, 0, message.Length);
            return signer.GenerateSignature();
        }

        private static bool VerifyEd25519phSignature(byte[] message, byte[] signature, Ed25519PublicKeyParameters publicKey)
        {
            var verifier = new Ed25519phSigner();
            verifier.Init(false, new ParametersWithContext(publicKey, new byte[0]));
            verifier.BlockUpdate(message, 0, message.Length);
            return verifier.VerifySignature(signature);
        }
    }
}

验证结果

  1. BouncyCastle本地验证:运行代码后输出BouncyCastle本地验证结果: True,说明签名生成逻辑正确。
  2. OpenSSL验证:执行提示的命令后,OpenSSL输出Verified OK,证明签名完全兼容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:52:26