OSDN Git Service

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