OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / crypto / ed25519 / ed25519.go
index f702255..530b08b 100644 (file)
@@ -9,11 +9,10 @@ package ed25519
 // from SUPERCOP.
 
 import (
-       "crypto"
        cryptorand "crypto/rand"
        "crypto/sha512"
        "crypto/subtle"
-       "errors"
+       "encoding/hex"
        "io"
        "strconv"
 
@@ -27,6 +26,8 @@ const (
        PrivateKeySize = 64
        // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
        SignatureSize = 64
+       // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
+       SeedSize = 32
 )
 
 // PublicKey is the type of Ed25519 public keys.
@@ -36,23 +37,23 @@ type PublicKey []byte
 type PrivateKey []byte
 
 // Public returns the PublicKey corresponding to priv.
-func (priv PrivateKey) Public() crypto.PublicKey {
+func (priv PrivateKey) Public() PublicKey {
        publicKey := make([]byte, PublicKeySize)
        copy(publicKey, priv[32:])
        return PublicKey(publicKey)
 }
 
-// Sign signs the given message with priv.
-// Ed25519 performs two passes over messages to be signed and therefore cannot
-// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
-// indicate the message hasn't been hashed. This can be achieved by passing
-// crypto.Hash(0) as the value for opts.
-func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
-       if opts.HashFunc() != crypto.Hash(0) {
-               return nil, errors.New("ed25519: cannot sign hashed message")
-       }
+// Seed returns the private key seed corresponding to priv. It is provided for
+// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
+// in this package.
+func (priv PrivateKey) Seed() []byte {
+       seed := make([]byte, SeedSize)
+       copy(seed, priv[:32])
+       return seed
+}
 
-       return Sign(priv, message), nil
+func (priv PrivateKey) String() string {
+       return hex.EncodeToString(priv)
 }
 
 // GenerateKey generates a public/private key pair using entropy from rand.
@@ -87,6 +88,34 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er
        return publicKey, privateKey, nil
 }
 
+// NewKeyFromSeed calculates a private key from a seed. It will panic if
+// len(seed) is not SeedSize. This function is provided for interoperability
+// with RFC 8032. RFC 8032's private keys correspond to seeds in this
+// package.
+func NewKeyFromSeed(seed []byte) PrivateKey {
+       if l := len(seed); l != SeedSize {
+               panic("ed25519: bad seed length: " + strconv.Itoa(l))
+       }
+
+       digest := sha512.Sum512(seed)
+       digest[0] &= 248
+       digest[31] &= 127
+       digest[31] |= 64
+
+       var A edwards25519.ExtendedGroupElement
+       var hBytes [32]byte
+       copy(hBytes[:], digest[:])
+       edwards25519.GeScalarMultBase(&A, &hBytes)
+       var publicKeyBytes [32]byte
+       A.ToBytes(&publicKeyBytes)
+
+       privateKey := make([]byte, PrivateKeySize)
+       copy(privateKey, seed)
+       copy(privateKey[32:], publicKeyBytes[:])
+
+       return privateKey
+}
+
 // Sign signs the message with privateKey and returns a signature. It will
 // panic if len(privateKey) is not PrivateKeySize.
 func Sign(privateKey PrivateKey, message []byte) []byte {