github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/crypto/ecdh/x25519.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ecdh 6 7 import ( 8 "crypto/internal/edwards25519/field" 9 "crypto/internal/randutil" 10 "errors" 11 "io" 12 ) 13 14 var ( 15 x25519PublicKeySize = 32 16 x25519PrivateKeySize = 32 17 x25519SharedSecretSize = 32 18 ) 19 20 // X25519 returns a [Curve] which implements the X25519 function over Curve25519 21 // (RFC 7748, Section 5). 22 // 23 // Multiple invocations of this function will return the same value, so it can 24 // be used for equality checks and switch statements. 25 func X25519() Curve { return x25519 } 26 27 var x25519 = &x25519Curve{} 28 29 type x25519Curve struct{} 30 31 func (c *x25519Curve) String() string { 32 return "X25519" 33 } 34 35 func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) { 36 key := make([]byte, x25519PrivateKeySize) 37 randutil.MaybeReadByte(rand) 38 if _, err := io.ReadFull(rand, key); err != nil { 39 return nil, err 40 } 41 return c.NewPrivateKey(key) 42 } 43 44 func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) { 45 if len(key) != x25519PrivateKeySize { 46 return nil, errors.New("crypto/ecdh: invalid private key size") 47 } 48 return &PrivateKey{ 49 curve: c, 50 privateKey: append([]byte{}, key...), 51 }, nil 52 } 53 54 func (c *x25519Curve) privateKeyToPublicKey(key *PrivateKey) *PublicKey { 55 if key.curve != c { 56 panic("crypto/ecdh: internal error: converting the wrong key type") 57 } 58 k := &PublicKey{ 59 curve: key.curve, 60 publicKey: make([]byte, x25519PublicKeySize), 61 } 62 x25519Basepoint := [32]byte{9} 63 x25519ScalarMult(k.publicKey, key.privateKey, x25519Basepoint[:]) 64 return k 65 } 66 67 func (c *x25519Curve) NewPublicKey(key []byte) (*PublicKey, error) { 68 if len(key) != x25519PublicKeySize { 69 return nil, errors.New("crypto/ecdh: invalid public key") 70 } 71 return &PublicKey{ 72 curve: c, 73 publicKey: append([]byte{}, key...), 74 }, nil 75 } 76 77 func (c *x25519Curve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { 78 out := make([]byte, x25519SharedSecretSize) 79 x25519ScalarMult(out, local.privateKey, remote.publicKey) 80 if isZero(out) { 81 return nil, errors.New("crypto/ecdh: bad X25519 remote ECDH input: low order point") 82 } 83 return out, nil 84 } 85 86 func x25519ScalarMult(dst, scalar, point []byte) { 87 var e [32]byte 88 89 copy(e[:], scalar[:]) 90 e[0] &= 248 91 e[31] &= 127 92 e[31] |= 64 93 94 var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element 95 x1.SetBytes(point[:]) 96 x2.One() 97 x3.Set(&x1) 98 z3.One() 99 100 swap := 0 101 for pos := 254; pos >= 0; pos-- { 102 b := e[pos/8] >> uint(pos&7) 103 b &= 1 104 swap ^= int(b) 105 x2.Swap(&x3, swap) 106 z2.Swap(&z3, swap) 107 swap = int(b) 108 109 tmp0.Subtract(&x3, &z3) 110 tmp1.Subtract(&x2, &z2) 111 x2.Add(&x2, &z2) 112 z2.Add(&x3, &z3) 113 z3.Multiply(&tmp0, &x2) 114 z2.Multiply(&z2, &tmp1) 115 tmp0.Square(&tmp1) 116 tmp1.Square(&x2) 117 x3.Add(&z3, &z2) 118 z2.Subtract(&z3, &z2) 119 x2.Multiply(&tmp1, &tmp0) 120 tmp1.Subtract(&tmp1, &tmp0) 121 z2.Square(&z2) 122 123 z3.Mult32(&tmp1, 121666) 124 x3.Square(&x3) 125 tmp0.Add(&tmp0, &z3) 126 z3.Multiply(&x1, &z2) 127 z2.Multiply(&tmp1, &tmp0) 128 } 129 130 x2.Swap(&x3, swap) 131 z2.Swap(&z3, swap) 132 133 z2.Invert(&z2) 134 x2.Multiply(&x2, &z2) 135 copy(dst[:], x2.Bytes()) 136 }