~juju-qa/ubuntu/xenial/juju/2.0-rc2

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/ed25519/ed25519.go

  • Committer: Nicholas Skaggs
  • Date: 2016-09-30 14:39:30 UTC
  • mfrom: (1.8.1)
  • Revision ID: nicholas.skaggs@canonical.com-20160930143930-vwwhrefh6ftckccy
import upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
// http://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
}