Golang中椭圆曲线标量乘法的实现与应用

Golang中椭圆曲线标量乘法的实现与应用 关于 ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) 的问题:

例如:

我有一个椭圆曲线上的点 (x, y)。

  1. x1, y1 := ScalarMult(x, y, g)
  2. gm = big.NewInt(0).ModInverse(g, elliptic.Params().P) // gm = [g -1 Mod P] x2, y2 := ScalarMult(x1, y1, gm)

因为 g * gm mod p = 1;所以 (x2, y2) 应该等于 (x, y),但实际结果并非如此。

有人能帮我吗?


更多关于Golang中椭圆曲线标量乘法的实现与应用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

谢谢大家,我明白了。

更多关于Golang中椭圆曲线标量乘法的实现与应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


hongyuefan:

但事实并非如此

那么实际情况是怎样的呢?

请展示更多能说明你实际问题的代码。请使用 官方 Go Playground 来创建这样的示例。请确保其输出的值与你得到的一致。

尤其要确保你的代码包含 ScalarMult() 方法!

在椭圆曲线密码学中,标量乘法 ScalarMult 是核心操作,但你的使用方式存在误解。ScalarMult 执行的是椭圆曲线上的点乘,而不是模乘。你混淆了标量乘法的数学定义。

问题分析

你的代码试图通过乘以模逆来还原点,但这是错误的:

  • g 是标量(整数),gmg 在模 P 下的模逆
  • ScalarMult 计算的是 [k] * (x, y),其中 k 是标量,(x, y) 是曲线上的点
  • 椭圆曲线标量乘法不直接支持模逆操作还原

正确实现

package main

import (
    "crypto/elliptic"
    "fmt"
    "math/big"
)

func main() {
    curve := elliptic.P256()
    
    // 原始点
    x, y := curve.ScalarBaseMult(big.NewInt(5).Bytes())
    fmt.Printf("原始点: (%s, %s)\n", x.Text(16), y.Text(16))
    
    // 标量 g
    g := big.NewInt(7)
    
    // 第一次标量乘法: Q = [g] * P
    x1, y1 := curve.ScalarMult(x, y, g.Bytes())
    fmt.Printf("乘以 g 后: (%s, %s)\n", x1.Text(16), y1.Text(16))
    
    // 计算 g 的模逆(在曲线阶数 N 下)
    N := curve.Params().N
    gInv := new(big.Int).ModInverse(g, N)
    
    // 还原点: P = [gInv] * Q
    x2, y2 := curve.ScalarMult(x1, y1, gInv.Bytes())
    fmt.Printf("还原后点: (%s, %s)\n", x2.Text(16), y2.Text(16))
    
    // 验证是否相等
    if x.Cmp(x2) == 0 && y.Cmp(y2) == 0 {
        fmt.Println("成功还原到原始点")
    }
}

关键点说明

  1. 椭圆曲线标量乘法[k] * P 表示将点 P 加自身 k
  2. 还原操作:要还原 [g] * P,需要计算 [g^{-1} mod N] * ([g] * P),其中 N 是曲线阶数
  3. 模数选择:使用曲线阶数 N,而不是基域素数 P

实际应用示例

// ECDH 密钥交换示例
func ecdhKeyExchange() {
    curve := elliptic.P256()
    
    // 生成私钥和公钥
    privateKey, _ := rand.Int(rand.Reader, curve.Params().N)
    x, y := curve.ScalarBaseMult(privateKey.Bytes())
    
    // 另一方公钥
    otherPrivate, _ := rand.Int(rand.Reader, curve.Params().N)
    otherX, otherY := curve.ScalarBaseMult(otherPrivate.Bytes())
    
    // 计算共享密钥
    sharedX, sharedY := curve.ScalarMult(otherX, otherY, privateKey.Bytes())
    fmt.Printf("共享密钥点: (%s, %s)\n", 
        sharedX.Text(16)[:16], 
        sharedY.Text(16)[:16])
}

你的错误在于使用了错误的模数(基域素数 P 而不是曲线阶数 N),并且误解了标量乘法的数学含义。

回到顶部