+++ /dev/null
-// Package chainkd This is an extension to ed25519.Sign that is compatible with NaCl `crypto_sign`
-// function taking 64-byte expanded private key (where the left part is a pre-multiplied
-// scalar and the right part is "prefix" used for generating a nonce).
-//
-// Invariants:
-// 1) Expanded(PrivateKey).Sign() == PrivateKey.Sign()
-// 2) InnerSign(Expanded(PrivateKey)) == Sign(PrivateKey)
-package chainkd
-
-import (
- "crypto"
- "crypto/sha512"
- "errors"
- "io"
- "strconv"
-
- "github.com/vapor/crypto/ed25519"
- "github.com/vapor/crypto/ed25519/internal/edwards25519"
-)
-
-const (
- // ExpandedPrivateKeySize is the size, in bytes, of a "secret key" as defined in NaCl.
- ExpandedPrivateKeySize = 64
-)
-
-// ExpandedPrivateKey is the type of NaCl secret keys. It implements crypto.Signer.
-type ExpandedPrivateKey []byte
-
-// Public returns the PublicKey corresponding to secret key.
-func (priv ExpandedPrivateKey) Public() crypto.PublicKey {
- var A edwards25519.ExtendedGroupElement
- var scalar [32]byte
- copy(scalar[:], priv[:32])
- edwards25519.GeScalarMultBase(&A, &scalar)
- var publicKeyBytes [32]byte
- A.ToBytes(&publicKeyBytes)
- return ed25519.PublicKey(publicKeyBytes[:])
-}
-
-func expandEd25519PrivateKey(priv ed25519.PrivateKey) ExpandedPrivateKey {
- digest := sha512.Sum512(priv[:32])
- digest[0] &= 248
- digest[31] &= 127
- digest[31] |= 64
- return ExpandedPrivateKey(digest[:])
-}
-
-// Sign signs the given message with expanded private key.
-// 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 ExpandedPrivateKey) 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")
- }
-
- return Ed25519InnerSign(priv, message), nil
-}
-
-// Ed25519InnerSign signs the message with expanded private key and returns a signature.
-// It will panic if len(privateKey) is not ExpandedPrivateKeySize.
-func Ed25519InnerSign(privateKey ExpandedPrivateKey, message []byte) []byte {
- if l := len(privateKey); l != ExpandedPrivateKeySize {
- panic("ed25519: bad private key length: " + strconv.Itoa(l))
- }
-
- var messageDigest, hramDigest [64]byte
-
- h := sha512.New()
- h.Write(privateKey[32:])
- h.Write(message)
- h.Sum(messageDigest[:0])
-
- var messageDigestReduced [32]byte
- edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
- var R edwards25519.ExtendedGroupElement
- edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
-
- var encodedR [32]byte
- R.ToBytes(&encodedR)
-
- publicKey := privateKey.Public().(ed25519.PublicKey)
- h.Reset()
- h.Write(encodedR[:])
- h.Write(publicKey[:])
- h.Write(message)
- h.Sum(hramDigest[:0])
- var hramDigestReduced [32]byte
- edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
-
- var sk [32]byte
- copy(sk[:], privateKey[:32])
- var s [32]byte
- edwards25519.ScMulAdd(&s, &hramDigestReduced, &sk, &messageDigestReduced)
-
- signature := make([]byte, ed25519.SignatureSize)
- copy(signature[:], encodedR[:])
- copy(signature[32:], s[:])
-
- return signature
-}