Files
crypto/curve25519/curve25519.go
T

137 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// We have a implementation in amd64 assembly so this code is only run on
// non-amd64 platforms. The amd64 assembly does not support gccgo.
// +build !amd64 gccgo
package curve25519
import (
"math/big"
)
// p is the prime order of the underlying field: 2^255-19
var p *big.Int
// pMinus2 is p-2
var pMinus2 *big.Int
// a is a parameter of the elliptic curve: 486662
var a *big.Int
func init() {
p, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
pMinus2, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb", 16)
a = new(big.Int).SetInt64(486662)
}
// context contains state shared throughout the computation, including scratch
// variables to save on allocation.
type context struct {
tmp1, tmp2, tmp3, tmp4 *big.Int
x1 *big.Int
}
// add sets (outx, outz) to the sum of two points in the elliptic curve group.
// See http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m
// outx and outz should not alias any of the other inputs.
func (c *context) add(outx, outz, xn, zn, xm, zm *big.Int) {
// x₃ = 4(x·x′ - z·z′)² · z1
// (z1 == 1 here)
c.tmp1.Mul(xn, xm)
c.tmp2.Mul(zn, zm)
c.tmp3.Sub(c.tmp1, c.tmp2)
outx.Mul(c.tmp3, c.tmp3)
outx.Lsh(outx, 2)
outx.Mod(outx, p)
// z₃ = 4(x·z′ - z·x′)² · x1
// (x1 == 1 here)
c.tmp1.Mul(xm, zn)
c.tmp2.Mul(zm, xn)
c.tmp3.Sub(c.tmp1, c.tmp2)
outz.Mul(c.tmp3, c.tmp3)
outz.Mul(outz, c.x1)
outz.Lsh(outz, 2)
outz.Mod(outz, p)
return
}
// double sets (outx, outz) to 2*(x,z) in the elliptic curve group. See
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m
// outx and outz should not alias any of the other inputs.
func (c *context) double(outx, outz, x, z *big.Int) {
// x₂ = (x² - z²)²
c.tmp1.Mul(x, x)
c.tmp2.Mul(z, z)
c.tmp3.Sub(c.tmp1, c.tmp2)
outx.Mul(c.tmp3, c.tmp3)
outx.Mod(outx, p)
// z₂ = 4xz·(x² + Axz + z²)
c.tmp3.Add(c.tmp1, c.tmp2)
c.tmp1.Mul(x, z)
c.tmp2.Mul(c.tmp1, a)
outz.Add(c.tmp3, c.tmp2)
c.tmp2.Lsh(c.tmp1, 2)
outz.Mul(outz, c.tmp2)
outz.Mod(outz, p)
return
}
func scalarMult(out, in, base *[32]byte) {
var baseReversed, inCopy [32]byte
for i := 0; i < 32; i++ {
baseReversed[31-i] = base[i]
inCopy[i] = in[i]
}
inCopy[31] &= 127
inCopy[31] |= 64
inCopy[0] &= 248
c := &context{new(big.Int), new(big.Int), new(big.Int), new(big.Int), nil}
c.x1 = new(big.Int).SetBytes(baseReversed[:])
x1 := new(big.Int).SetInt64(1)
z1 := new(big.Int)
x2 := new(big.Int).Set(c.x1)
z2 := new(big.Int).SetInt64(1)
outx := new(big.Int)
outz := new(big.Int)
for i := 0; i < 32; i++ {
b := inCopy[31-i]
for j := 0; j < 8; j++ {
if b&0x80 != 0 {
c.add(outx, outz, x1, z1, x2, z2)
x1, z1, outx, outz = outx, outz, x1, z1
c.double(outx, outz, x2, z2)
x2, z2, outx, outz = outx, outz, x2, z2
} else {
c.add(outx, outz, x1, z1, x2, z2)
x2, z2, outx, outz = outx, outz, x2, z2
c.double(outx, outz, x1, z1)
x1, z1, outx, outz = outx, outz, x1, z1
}
b <<= 1
}
}
c.tmp1.Exp(z1, pMinus2, p)
c.tmp2.Mul(x1, c.tmp1)
c.tmp3.Mod(c.tmp2, p)
outReversed := c.tmp3.Bytes()
for i := 0; i < len(outReversed); i++ {
out[i] = outReversed[len(outReversed)-(1+i)]
}
for i := len(outReversed); i < 32; i++ {
out[i] = 0
}
}