ed25519.go 6.5 KB

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