1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
// Copyright 2013 The Go Authors. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.
// Package ed25519 implements the Ed25519 signature algorithm. See
// http://ed25519.cr.yp.to/.
package ed25519
// This code is a port of the public domain, "ref10" implementation of ed25519
// from SUPERCOP.
import (
"bytes"
"crypto/sha512"
)
const (
// EntropySize is the number of bytes used as input to GenerateKey.
EntropySize = 32
// PublicKeySize is the size of the public key in bytes.
PublicKeySize = 32
// SecretKeySize is the size of the secret key in bytes.
SecretKeySize = 64
// SignatureSize is size of the signature in bytes.
SignatureSize = 64
)
type (
// PublicKey is used to verify signatures.
PublicKey *[PublicKeySize]byte
// SecretKey is used to sign messages.
SecretKey *[SecretKeySize]byte
// Signature is used to authenticate a message.
Signature *[SignatureSize]byte
)
// GenerateKey generates a public/secret key pair using randomness from rand.
func GenerateKey(entropy [EntropySize]byte) (sk SecretKey, pk PublicKey) {
sk = new([SecretKeySize]byte)
pk = new([PublicKeySize]byte)
copy(sk[:32], entropy[:])
h := sha512.New()
h.Write(sk[:32])
digest := h.Sum(nil)
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
A := geScalarMultBase(digest[:32])
A.ToBytes(sk[32:])
copy(pk[:], sk[32:])
return sk, pk
}
// Sign signs the message with secretKey and returns a signature.
func Sign(sk SecretKey, message []byte) (sig Signature) {
sig = new([SignatureSize]byte)
h := sha512.New()
h.Write(sk[:32])
digest := h.Sum(nil)
digest[0] &= 248
digest[31] &= 63
digest[31] |= 64
h.Reset()
h.Write(digest[32:])
h.Write(message)
messageDigest := h.Sum(nil)
messageDigestReduced := scReduce(messageDigest)
R := geScalarMultBase(messageDigestReduced[:])
R.ToBytes(sig[:32])
h.Reset()
h.Write(sig[:32])
h.Write(sk[32:])
h.Write(message)
hramDigest := h.Sum(nil)
hramDigestReduced := scReduce(hramDigest)
scMulAdd(sig[32:], hramDigestReduced, digest[:32], messageDigestReduced)
return sig
}
// Verify returns true iff sig is a valid signature of message by publicKey.
func Verify(pk PublicKey, message []byte, sig Signature) bool {
if sig[63]&224 != 0 {
return false
}
var A extendedGroupElement
if !A.FromBytes(pk[:]) {
return false
}
h := sha512.New()
h.Write(sig[:32])
h.Write(pk[:])
h.Write(message)
digest := h.Sum(nil)
hReduced := scReduce(digest[:])
R := geDoubleScalarMultVartime(hReduced, &A, sig[32:])
var checkR [32]byte
R.ToBytes(&checkR)
return bytes.Equal(sig[:32], checkR[:])
}
|