OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / ed25519 / ed25519.go
1 // Copyright 2013 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 // http://ed25519.cr.yp.to/.
7 package ed25519
8
9 // This code is a port of the public domain, "ref10" implementation of ed25519
10 // from SUPERCOP.
11
12 import (
13         "crypto/sha512"
14         "crypto/subtle"
15         "io"
16
17         "github.com/tendermint/ed25519/edwards25519"
18 )
19
20 const (
21         PublicKeySize  = 32
22         PrivateKeySize = 64
23         SignatureSize  = 64
24 )
25
26 // GenerateKey generates a public/private key pair using randomness from rand.
27 func GenerateKey(rand io.Reader) (publicKey *[PublicKeySize]byte, privateKey *[PrivateKeySize]byte, err error) {
28         privateKey = new([64]byte)
29         _, err = io.ReadFull(rand, privateKey[:32])
30         if err != nil {
31                 return nil, nil, err
32         }
33
34         publicKey = MakePublicKey(privateKey)
35         return
36 }
37
38 // MakePublicKey makes a publicKey from the first half of privateKey.
39 func MakePublicKey(privateKey *[PrivateKeySize]byte) (publicKey *[PublicKeySize]byte) {
40         publicKey = new([32]byte)
41
42         h := sha512.New()
43         h.Write(privateKey[:32])
44         digest := h.Sum(nil)
45
46         digest[0] &= 248
47         digest[31] &= 127
48         digest[31] |= 64
49
50         var A edwards25519.ExtendedGroupElement
51         var hBytes [32]byte
52         copy(hBytes[:], digest)
53         edwards25519.GeScalarMultBase(&A, &hBytes)
54         A.ToBytes(publicKey)
55
56         copy(privateKey[32:], publicKey[:])
57         return
58 }
59
60 // Sign signs the message with privateKey and returns a signature.
61 func Sign(privateKey *[PrivateKeySize]byte, message []byte) *[SignatureSize]byte {
62         h := sha512.New()
63         h.Write(privateKey[:32])
64
65         var digest1, messageDigest, hramDigest [64]byte
66         var expandedSecretKey [32]byte
67         h.Sum(digest1[:0])
68         copy(expandedSecretKey[:], digest1[:])
69         expandedSecretKey[0] &= 248
70         expandedSecretKey[31] &= 63
71         expandedSecretKey[31] |= 64
72
73         h.Reset()
74         h.Write(digest1[32:])
75         h.Write(message)
76         h.Sum(messageDigest[:0])
77
78         var messageDigestReduced [32]byte
79         edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
80         var R edwards25519.ExtendedGroupElement
81         edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
82
83         var encodedR [32]byte
84         R.ToBytes(&encodedR)
85
86         h.Reset()
87         h.Write(encodedR[:])
88         h.Write(privateKey[32:])
89         h.Write(message)
90         h.Sum(hramDigest[:0])
91         var hramDigestReduced [32]byte
92         edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
93
94         var s [32]byte
95         edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
96
97         signature := new([64]byte)
98         copy(signature[:], encodedR[:])
99         copy(signature[32:], s[:])
100         return signature
101 }
102
103 // Verify returns true iff sig is a valid signature of message by publicKey.
104 func Verify(publicKey *[PublicKeySize]byte, message []byte, sig *[SignatureSize]byte) bool {
105         if sig[63]&224 != 0 {
106                 return false
107         }
108
109         var A edwards25519.ExtendedGroupElement
110         if !A.FromBytes(publicKey) {
111                 return false
112         }
113         edwards25519.FeNeg(&A.X, &A.X)
114         edwards25519.FeNeg(&A.T, &A.T)
115
116         h := sha512.New()
117         h.Write(sig[:32])
118         h.Write(publicKey[:])
119         h.Write(message)
120         var digest [64]byte
121         h.Sum(digest[:0])
122
123         var hReduced [32]byte
124         edwards25519.ScReduce(&hReduced, &digest)
125
126         var R edwards25519.ProjectiveGroupElement
127         var b [32]byte
128         copy(b[:], sig[32:])
129         edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
130
131         var checkR [32]byte
132         R.ToBytes(&checkR)
133         return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
134 }