ECDSA 和 ed25519

image.png

Speck256k1 签名

20241106-210707.jpeg

Schnoor 签名

image.png

ECDSA

r = k * G的x坐标, (k是随机数)
s = (H(m) + d * r) * k^−1 mod n,其中(H(m) 是消息 m 的哈希值,k^−1是 k 的模 n 的乘法逆元。
签名结果是 r,s

func sign(privateKey *PrivateKey, hash []byte,nonce int) (*Signature, error) {

    // - 椭圆曲线的阶
    N := S256().N
    halfOrder := S256().halfOrder
    // - 随机数 k
    k := nonceRFC6979(privkey.D, hash,nonce)

    // - k^-1
    inv := new(big.Int).ModInverse(k, N)

    // - k*G = R, r为椭圆曲线上R的x坐标
    r, _ := privkey.Curve.ScalarBaseMult(k.Bytes())
    if r.Cmp(N) == 1 {
        r.Sub(r, N)
    }

    if r.Sign() == 0 {
        return nil, errors.New("calculated R is zero")
    }

    // - prvKey * r
    e := hashToInt(hash, privkey.Curve)
    s := new(big.Int).Mul(privkey.D, r)

    // - prvKey * r + e
    s.Add(s, e)

    // - (prvKey * r + e) * k^-1
    s.Mul(s, inv)

    // - ((prvKey * r + e) * k^-1) mod n
    s.Mod(s, N)

    if s.Cmp(halfOrder) == 1 {
        s.Sub(N, s)
    }
    if s.Sign() == 0 {
        return nil, errors.New("calculated S is zero")
    }
    return &Signature{R: r, S: s}, nil
}

func verify(pub *PublicKey, hash []byte, sig []byte) bool {
    // - 解析 r,s
    rBytes, sBytes, err := parseSignature(sig)
    if err != nil {
        return false
    }
    r, s := new(big.Int).SetBytes(rBytes), new(big.Int).SetBytes(sBytes)

    c := pub.Curve
    N := c.Params().N

    if r.Sign() <= 0 || s.Sign() <= 0 {
        return false
    }
    if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
        return false
    }

    //  - 将c转成整数
    e := hashToInt(hash, c)

     // -  s^-1
    w := new(big.Int).ModInverse(s, N)

    // - e * s^-1
    u1 := e.Mul(e, w)
    u1.Mod(u1, N)

    // - r * s^-1
    u2 := w.Mul(r, w)
    u2.Mod(u2, N)
    // - u1*G, u1在椭圆曲线上的点
    x1, y1 := c.ScalarBaseMult(u1.Bytes())

    // -  u2*pub = u2(pub.x, pub.y)
    x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())

    // - x1+x2, y1+y2
    /*  e * s^-1 * G +  r * s^-1 * pub 
    =   e * s^-1 * G +  r * s^-1 *(prv * G) 
    =  (e + r *prv)*s^-1 * G
    = k*G
    k*G 表示点k在椭圆曲线上的坐标, 即签名时候的R, 所以,如果 (k*G).x 为签名信息中的 r;

*/
    x, y := c.Add(x1, y1, x2, y2)

    if x.Sign() == 0 && y.Sign() == 0 {
        return false
    }
    x.Mod(x, N)

    // - s == r, 验证成功
    return x.Cmp(r) == 0
}
image.png

ed25519

R=r×G (r是随机数)
s = r + H(R,A,m) * k mod l H(R,A,m) 是将点 R、公钥A 和消息哈希 H(m) 连接起来并哈希得到的值,
l 是 edwards25519 曲线的阶数。

func sign(signature, privateKey, message []byte, domPrefix, context string) {
    if l := len(privateKey); l != PrivateKeySize {
        panic("ed25519: bad private key length: " + strconv.Itoa(l))
    }

    // - 加工原私钥(这里的原私钥不是导入的字符串私钥, 而是经过处理的原私钥, 即ed25519.NewKeyFromSeed(util.GetRawKeySeed(c.PrvKey.D)) 的结果 而 c.PrvKey.D的计算是 ), 得到签名使用的私钥 s
    seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]
    h := sha512.Sum512(seed)
    s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    if err != nil {
        panic("ed25519: internal error: setting scalar failed")
    }

    // - 生成随机数 r
    prefix := h[32:]
    mh := sha512.New()
    if domPrefix != domPrefixPure {
        mh.Write([]byte(domPrefix))
        mh.Write([]byte{byte(len(context))})
        mh.Write([]byte(context))
    }
    mh.Write(prefix)
    mh.Write(message)
    messageDigest := make([]byte, 0, sha512.Size)
    messageDigest = mh.Sum(messageDigest)
    r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
    if err != nil {
        panic("ed25519: internal error: setting scalar failed")
    }

    // - 随机数 r 在椭圆曲线上的点 R
    R := (&edwards25519.Point{}).ScalarBaseMult(r)

    // - 将点 R、公钥A 和消息哈希 H(m) 连接起来并哈希得到的值
    kh := sha512.New()
    if domPrefix != domPrefixPure {
        kh.Write([]byte(domPrefix))
        kh.Write([]byte{byte(len(context))})
        kh.Write([]byte(context))
    }
    kh.Write(R.Bytes())
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
    if err != nil {
        panic("ed25519: internal error: setting scalar failed")
    }

    // - S = r + H(R,A,m) * k mod l, 代码中的k是 H(R,A,m) , s 是私钥. r 是 随机数
    S := edwards25519.NewScalar().MultiplyAdd(k, s, r)

    copy(signature[:32], R.Bytes())
    copy(signature[32:], S.Bytes())
}

func verify(publicKey PublicKey, message, sig []byte, domPrefix, context string) bool {
    if l := len(publicKey); l != PublicKeySize {
        panic("ed25519: bad public key length: " + strconv.Itoa(l))
    }

    if len(sig) != SignatureSize || sig[63]&224 != 0 {
        return false
    }

    // - A 公钥在椭圆曲线的坐标
    A, err := (&edwards25519.Point{}).SetBytes(publicKey)
    if err != nil {
        return false
    }

    // - 将点 R、公钥A 和消息哈希 H(m) 连接起来并哈希得到的值
    kh := sha512.New()
    if domPrefix != domPrefixPure {
        kh.Write([]byte(domPrefix))
        kh.Write([]byte{byte(len(context))})
        kh.Write([]byte(context))
    }
    kh.Write(sig[:32])
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
    if err != nil {
        panic("ed25519: internal error: setting scalar failed")
    }

    // - S的字节数组转成整数
    S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
    if err != nil {
        return false
    }

    // [S]B = R + [k]A --> [k](-A) + [S]B = R
    minusA := (&edwards25519.Point{}).Negate(A)
    R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)

    //  - R相等表示验证通过
    return bytes.Equal(sig[:32], R.Bytes())
}
image.png

ed25519的公私钥生成流程

ed25519 生成的是一个种子, 使用这个种子生成公钥, 私钥, 地址

// - 1. 取导入的私钥的前32字节
func GetRawKeySeed(D *big.Int) []byte {
    maxLen:=32
    srcBytes:= D.Bytes()
    srcLen := len(srcBytes)
    if srcLen >= maxLen {
        return srcBytes
    }
    dest := make([]byte, maxLen)
    copy(dest[maxLen-srcLen:], srcBytes)
    return dest
}

// - 2 计算前32字节的sha512, 并只取结果的前32字节然后修剪作为私钥
func NewKeyFromSeed(seed []byte) PrivateKey {
    // Outline the function body so that the returned key can be stack-allocated.
    privateKey := make([]byte, PrivateKeySize)
    newKeyFromSeed(privateKey, seed)
    return privateKey
}
func newKeyFromSeed(privateKey, seed []byte) {
    if l := len(seed); l != SeedSize {
        panic("ed25519: bad seed length: " + strconv.Itoa(l))
    }

    // - 私钥
    h := sha512.Sum512(seed)
    s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    if err != nil {
        panic("ed25519: internal error: setting scalar failed")
    }
    A := (&edwards25519.Point{}).ScalarBaseMult(s)

    // - 公钥
    publicKey := A.Bytes()

    copy(privateKey, seed)
    copy(privateKey[32:], publicKey)
}

/* 1. 取导入的私钥的前32字节
   2.计算前32字节的sha512, 并只取结果的前32字节然后修剪作为私钥
   公钥 : 私钥在椭圆曲线上的点
   地址 : 公钥的base58
*/ 

prvKey := ed25519.NewKeyFromSeed(util.GetRawKeySeed(c.PrvKey.D))

// - 解析输入字符串的私钥转成  prvKey.D 
func (priv PrivateKey) Seed() []byte {
    return bytes.Clone(priv[:32])
}
func ParseWifOrHexForPrivateKey(key string) (prvKey *btcec.PrivateKey) {
     b, err := base58.Decode(key)
     priKey := ed25519.PrivateKey(key)
     ac := Account{
        PublicKey:  common.PublicKeyFromBytes(priKey.Public().(ed25519.PublicKey)),
        PrivateKey: priKey,
    }
    prvKey.D = new(big.Int).SetBytes(ac.PrivateKey.Seed())
}
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容