github.com/binkynet/BinkyNet@v1.12.1-0.20240421190447-da4e34c20be0/proto_vendor/golang.org/x/crypto/ed25519/ed25519.go (about) 1 // Copyright 2016 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 // In Go 1.13, the ed25519 package was promoted to the standard library as 6 // crypto/ed25519, and this package became a wrapper for the standard library one. 7 // 8 // +build !go1.13 9 10 // Package ed25519 implements the Ed25519 signature algorithm. See 11 // https://ed25519.cr.yp.to/. 12 // 13 // These functions are also compatible with the “Ed25519” function defined in 14 // RFC 8032. However, unlike RFC 8032's formulation, this package's private key 15 // representation includes a public key suffix to make multiple signing 16 // operations with the same key more efficient. This package refers to the RFC 17 // 8032 private key as the “seed”. 18 package ed25519 19 20 // This code is a port of the public domain, “ref10” implementation of ed25519 21 // from SUPERCOP. 22 23 import ( 24 "bytes" 25 "crypto" 26 cryptorand "crypto/rand" 27 "crypto/sha512" 28 "errors" 29 "io" 30 "strconv" 31 32 "golang.org/x/crypto/ed25519/internal/edwards25519" 33 ) 34 35 const ( 36 // PublicKeySize is the size, in bytes, of public keys as used in this package. 37 PublicKeySize = 32 38 // PrivateKeySize is the size, in bytes, of private keys as used in this package. 39 PrivateKeySize = 64 40 // SignatureSize is the size, in bytes, of signatures generated and verified by this package. 41 SignatureSize = 64 42 // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. 43 SeedSize = 32 44 ) 45 46 // PublicKey is the type of Ed25519 public keys. 47 type PublicKey []byte 48 49 // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 50 type PrivateKey []byte 51 52 // Public returns the PublicKey corresponding to priv. 53 func (priv PrivateKey) Public() crypto.PublicKey { 54 publicKey := make([]byte, PublicKeySize) 55 copy(publicKey, priv[32:]) 56 return PublicKey(publicKey) 57 } 58 59 // Seed returns the private key seed corresponding to priv. It is provided for 60 // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds 61 // in this package. 62 func (priv PrivateKey) Seed() []byte { 63 seed := make([]byte, SeedSize) 64 copy(seed, priv[:32]) 65 return seed 66 } 67 68 // Sign signs the given message with priv. 69 // Ed25519 performs two passes over messages to be signed and therefore cannot 70 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 71 // indicate the message hasn't been hashed. This can be achieved by passing 72 // crypto.Hash(0) as the value for opts. 73 func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 74 if opts.HashFunc() != crypto.Hash(0) { 75 return nil, errors.New("ed25519: cannot sign hashed message") 76 } 77 78 return Sign(priv, message), nil 79 } 80 81 // GenerateKey generates a public/private key pair using entropy from rand. 82 // If rand is nil, crypto/rand.Reader will be used. 83 func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { 84 if rand == nil { 85 rand = cryptorand.Reader 86 } 87 88 seed := make([]byte, SeedSize) 89 if _, err := io.ReadFull(rand, seed); err != nil { 90 return nil, nil, err 91 } 92 93 privateKey := NewKeyFromSeed(seed) 94 publicKey := make([]byte, PublicKeySize) 95 copy(publicKey, privateKey[32:]) 96 97 return publicKey, privateKey, nil 98 } 99 100 // NewKeyFromSeed calculates a private key from a seed. It will panic if 101 // len(seed) is not SeedSize. This function is provided for interoperability 102 // with RFC 8032. RFC 8032's private keys correspond to seeds in this 103 // package. 104 func NewKeyFromSeed(seed []byte) PrivateKey { 105 if l := len(seed); l != SeedSize { 106 panic("ed25519: bad seed length: " + strconv.Itoa(l)) 107 } 108 109 digest := sha512.Sum512(seed) 110 digest[0] &= 248 111 digest[31] &= 127 112 digest[31] |= 64 113 114 var A edwards25519.ExtendedGroupElement 115 var hBytes [32]byte 116 copy(hBytes[:], digest[:]) 117 edwards25519.GeScalarMultBase(&A, &hBytes) 118 var publicKeyBytes [32]byte 119 A.ToBytes(&publicKeyBytes) 120 121 privateKey := make([]byte, PrivateKeySize) 122 copy(privateKey, seed) 123 copy(privateKey[32:], publicKeyBytes[:]) 124 125 return privateKey 126 } 127 128 // Sign signs the message with privateKey and returns a signature. It will 129 // panic if len(privateKey) is not PrivateKeySize. 130 func Sign(privateKey PrivateKey, message []byte) []byte { 131 if l := len(privateKey); l != PrivateKeySize { 132 panic("ed25519: bad private key length: " + strconv.Itoa(l)) 133 } 134 135 h := sha512.New() 136 h.Write(privateKey[:32]) 137 138 var digest1, messageDigest, hramDigest [64]byte 139 var expandedSecretKey [32]byte 140 h.Sum(digest1[:0]) 141 copy(expandedSecretKey[:], digest1[:]) 142 expandedSecretKey[0] &= 248 143 expandedSecretKey[31] &= 63 144 expandedSecretKey[31] |= 64 145 146 h.Reset() 147 h.Write(digest1[32:]) 148 h.Write(message) 149 h.Sum(messageDigest[:0]) 150 151 var messageDigestReduced [32]byte 152 edwards25519.ScReduce(&messageDigestReduced, &messageDigest) 153 var R edwards25519.ExtendedGroupElement 154 edwards25519.GeScalarMultBase(&R, &messageDigestReduced) 155 156 var encodedR [32]byte 157 R.ToBytes(&encodedR) 158 159 h.Reset() 160 h.Write(encodedR[:]) 161 h.Write(privateKey[32:]) 162 h.Write(message) 163 h.Sum(hramDigest[:0]) 164 var hramDigestReduced [32]byte 165 edwards25519.ScReduce(&hramDigestReduced, &hramDigest) 166 167 var s [32]byte 168 edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) 169 170 signature := make([]byte, SignatureSize) 171 copy(signature[:], encodedR[:]) 172 copy(signature[32:], s[:]) 173 174 return signature 175 } 176 177 // Verify reports whether sig is a valid signature of message by publicKey. It 178 // will panic if len(publicKey) is not PublicKeySize. 179 func Verify(publicKey PublicKey, message, sig []byte) bool { 180 if l := len(publicKey); l != PublicKeySize { 181 panic("ed25519: bad public key length: " + strconv.Itoa(l)) 182 } 183 184 if len(sig) != SignatureSize || sig[63]&224 != 0 { 185 return false 186 } 187 188 var A edwards25519.ExtendedGroupElement 189 var publicKeyBytes [32]byte 190 copy(publicKeyBytes[:], publicKey) 191 if !A.FromBytes(&publicKeyBytes) { 192 return false 193 } 194 edwards25519.FeNeg(&A.X, &A.X) 195 edwards25519.FeNeg(&A.T, &A.T) 196 197 h := sha512.New() 198 h.Write(sig[:32]) 199 h.Write(publicKey[:]) 200 h.Write(message) 201 var digest [64]byte 202 h.Sum(digest[:0]) 203 204 var hReduced [32]byte 205 edwards25519.ScReduce(&hReduced, &digest) 206 207 var R edwards25519.ProjectiveGroupElement 208 var s [32]byte 209 copy(s[:], sig[32:]) 210 211 // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in 212 // the range [0, order) in order to prevent signature malleability. 213 if !edwards25519.ScMinimal(&s) { 214 return false 215 } 216 217 edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) 218 219 var checkR [32]byte 220 R.ToBytes(&checkR) 221 return bytes.Equal(sig[:32], checkR[:]) 222 }