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

Go实现ECDSA P384签名与OpenSSL兼容问题求助

Go ECDSA P384签名与OpenSSL兼容问题解决方法

问题根源

你的代码和OpenSSL命令存在两个关键不兼容点:

  • 哈希算法不匹配:OpenSSL用的是SHA-384,但你的Go代码用了SHA-512,P384椭圆曲线要求使用SHA-384作为哈希算法
  • S值未规范化:OpenSSL会自动将签名中的S值调整到曲线阶的一半以下(符合SEC 1标准),而Go原生ecdsa.Sign不会做这个处理

修正后的签名代码

import (
    "crypto/ecdsa"
    "crypto/rand"
    "crypto/sha384"
    "encoding/asn1"
    "math/big"
)

func signECDSA(privateKey *ecdsa.PrivateKey, data []byte) ([]byte, error) {
    // 改用SHA-384哈希,和OpenSSL命令保持一致
    hash := sha384.Sum384(data)

    r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:])
    if err != nil {
        return nil, err
    }

    // 规范化S值:确保S <= 曲线阶的一半
    curveOrder := privateKey.Curve.Params().N
    halfOrder := new(big.Int).Div(curveOrder, big.NewInt(2))
    if s.Cmp(halfOrder) > 0 {
        s.Sub(curveOrder, s)
    }

    // 序列化为ASN.1 DER格式
    sig := struct {
        R, S *big.Int
    }{r, s}
    signatureBytes, err := asn1.Marshal(sig)
    if err != nil {
        return nil, err
    }

    return signatureBytes, nil
}

关键改动说明

  • 哈希算法替换:将sha512.Sum512改为sha384.Sum384,匹配OpenSSL命令中的-sha384参数
  • S值规范化:检查S值是否大于曲线阶的一半,如果是则用曲线阶减去S值,生成符合SEC 1标准的签名,确保和OpenSSL行为一致

验证方法

用修正后的代码生成签名后,直接使用你原来的OpenSSL验证命令即可通过:

openssl dgst -sha384 -verify public_key.pem -signature signed_data input_data

内容的提问来源于stack exchange,提问作者M. Glushkin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:25:02