package ed25519
import (
)
const (
seedSize = 32
publicKeySize = 32
privateKeySize = seedSize + publicKeySize
signatureSize = 64
sha512Size = 64
)
type PrivateKey struct {
seed [seedSize]byte
pub [publicKeySize]byte
s edwards25519.Scalar
prefix [sha512Size / 2]byte
}
func ( *PrivateKey) () []byte {
:= make([]byte, 0, privateKeySize)
= append(, .seed[:]...)
= append(, .pub[:]...)
return
}
func ( *PrivateKey) () []byte {
:= .seed
return [:]
}
func ( *PrivateKey) () []byte {
:= .pub
return [:]
}
type PublicKey struct {
a edwards25519.Point
aBytes [32]byte
}
func ( *PublicKey) () []byte {
:= .aBytes
return [:]
}
func () (*PrivateKey, error) {
:= &PrivateKey{}
return generateKey()
}
func ( *PrivateKey) (*PrivateKey, error) {
fips140.RecordApproved()
drbg.Read(.seed[:])
precomputePrivateKey()
if := fipsPCT(); != nil {
panic()
}
return , nil
}
func ( []byte) (*PrivateKey, error) {
:= &PrivateKey{}
return newPrivateKeyFromSeed(, )
}
func ( *PrivateKey, []byte) (*PrivateKey, error) {
fips140.RecordApproved()
if := len(); != seedSize {
return nil, errors.New("ed25519: bad seed length: " + strconv.Itoa())
}
copy(.seed[:], )
precomputePrivateKey()
if := fipsPCT(); != nil {
panic()
}
return , nil
}
func ( *PrivateKey) {
:= sha512.New()
.Write(.seed[:])
:= .Sum(make([]byte, 0, sha512Size))
, := .s.SetBytesWithClamping([:32])
if != nil {
panic("ed25519: internal error: setting scalar failed")
}
:= (&edwards25519.Point{}).ScalarBaseMult()
copy(.pub[:], .Bytes())
copy(.prefix[:], [32:])
}
func ( []byte) (*PrivateKey, error) {
:= &PrivateKey{}
return newPrivateKey(, )
}
func ( *PrivateKey, []byte) (*PrivateKey, error) {
fips140.RecordApproved()
if := len(); != privateKeySize {
return nil, errors.New("ed25519: bad private key length: " + strconv.Itoa())
}
copy(.seed[:], [:32])
:= sha512.New()
.Write(.seed[:])
:= .Sum(make([]byte, 0, sha512Size))
if , := .s.SetBytesWithClamping([:32]); != nil {
panic("ed25519: internal error: setting scalar failed")
}
copy(.pub[:], [32:])
copy(.prefix[:], [32:])
if := fipsPCT(); != nil {
return nil,
}
return , nil
}
func ( []byte) (*PublicKey, error) {
:= &PublicKey{}
return newPublicKey(, )
}
func ( *PublicKey, []byte) (*PublicKey, error) {
if := len(); != publicKeySize {
return nil, errors.New("ed25519: bad public key length: " + strconv.Itoa())
}
if , := .a.SetBytes(); != nil {
return nil, errors.New("ed25519: bad public key")
}
copy(.aBytes[:], )
return , nil
}
const (
domPrefixPure = ""
domPrefixPh = "SigEd25519 no Ed25519 collisions\x01"
domPrefixCtx = "SigEd25519 no Ed25519 collisions\x00"
)
func ( *PrivateKey, []byte) []byte {
:= make([]byte, signatureSize)
return sign(, , )
}
func ( []byte, *PrivateKey, []byte) []byte {
fipsSelfTest()
fips140.RecordApproved()
return signWithDom(, , , domPrefixPure, "")
}
func ( *PrivateKey, []byte, string) ([]byte, error) {
:= make([]byte, signatureSize)
return signPH(, , , )
}
func ( []byte, *PrivateKey, []byte, string) ([]byte, error) {
fipsSelfTest()
fips140.RecordApproved()
if := len(); != sha512Size {
return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa())
}
if := len(); > 255 {
return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa())
}
return signWithDom(, , , domPrefixPh, ), nil
}
func ( *PrivateKey, []byte, string) ([]byte, error) {
:= make([]byte, signatureSize)
return signCtx(, , , )
}
func ( []byte, *PrivateKey, []byte, string) ([]byte, error) {
fipsSelfTest()
fips140.RecordNonApproved()
if := len(); > 255 {
return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa())
}
return signWithDom(, , , domPrefixCtx, ), nil
}
func ( []byte, *PrivateKey, []byte, , string) []byte {
:= sha512.New()
if != domPrefixPure {
.Write([]byte())
.Write([]byte{byte(len())})
.Write([]byte())
}
.Write(.prefix[:])
.Write()
:= make([]byte, 0, sha512Size)
= .Sum()
, := edwards25519.NewScalar().SetUniformBytes()
if != nil {
panic("ed25519: internal error: setting scalar failed")
}
:= (&edwards25519.Point{}).ScalarBaseMult()
:= sha512.New()
if != domPrefixPure {
.Write([]byte())
.Write([]byte{byte(len())})
.Write([]byte())
}
.Write(.Bytes())
.Write(.pub[:])
.Write()
:= make([]byte, 0, sha512Size)
= .Sum()
, := edwards25519.NewScalar().SetUniformBytes()
if != nil {
panic("ed25519: internal error: setting scalar failed")
}
:= edwards25519.NewScalar().MultiplyAdd(, &.s, )
copy([:32], .Bytes())
copy([32:], .Bytes())
return
}
func ( *PublicKey, , []byte) error {
return verify(, , )
}
func ( *PublicKey, , []byte) error {
fipsSelfTest()
fips140.RecordApproved()
return verifyWithDom(, , , domPrefixPure, "")
}
func ( *PublicKey, []byte, []byte, string) error {
fipsSelfTest()
fips140.RecordApproved()
if := len(); != sha512Size {
return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa())
}
if := len(); > 255 {
return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa())
}
return verifyWithDom(, , , domPrefixPh, )
}
func ( *PublicKey, []byte, []byte, string) error {
fipsSelfTest()
fips140.RecordNonApproved()
if := len(); > 255 {
return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa())
}
return verifyWithDom(, , , domPrefixCtx, )
}
func ( *PublicKey, , []byte, , string) error {
if := len(); != signatureSize {
return errors.New("ed25519: bad signature length: " + strconv.Itoa())
}
if [63]&224 != 0 {
return errors.New("ed25519: invalid signature")
}
:= sha512.New()
if != domPrefixPure {
.Write([]byte())
.Write([]byte{byte(len())})
.Write([]byte())
}
.Write([:32])
.Write(.aBytes[:])
.Write()
:= make([]byte, 0, sha512Size)
= .Sum()
, := edwards25519.NewScalar().SetUniformBytes()
if != nil {
panic("ed25519: internal error: setting scalar failed")
}
, := edwards25519.NewScalar().SetCanonicalBytes([32:])
if != nil {
return errors.New("ed25519: invalid signature")
}
:= (&edwards25519.Point{}).Negate(&.a)
:= (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(, , )
if !bytes.Equal([:32], .Bytes()) {
return errors.New("ed25519: invalid signature")
}
return nil
}