2022-08-26 22:26:53 +02:00
|
|
|
// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in
|
|
|
|
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
|
|
|
|
package eddsa
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
|
|
|
type PublicKey struct {
|
2023-12-13 14:29:02 +01:00
|
|
|
X []byte
|
2022-08-26 22:26:53 +02:00
|
|
|
curve ecc.EdDSACurve
|
|
|
|
}
|
|
|
|
|
|
|
|
type PrivateKey struct {
|
|
|
|
PublicKey
|
|
|
|
D []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPublicKey(curve ecc.EdDSACurve) *PublicKey {
|
|
|
|
return &PublicKey{
|
|
|
|
curve: curve,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPrivateKey(key PublicKey) *PrivateKey {
|
|
|
|
return &PrivateKey{
|
|
|
|
PublicKey: key,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pk *PublicKey) GetCurve() ecc.EdDSACurve {
|
|
|
|
return pk.curve
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pk *PublicKey) MarshalPoint() []byte {
|
|
|
|
return pk.curve.MarshalBytePoint(pk.X)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pk *PublicKey) UnmarshalPoint(x []byte) error {
|
|
|
|
pk.X = pk.curve.UnmarshalBytePoint(x)
|
|
|
|
|
|
|
|
if pk.X == nil {
|
|
|
|
return errors.New("eddsa: failed to parse EC point")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sk *PrivateKey) MarshalByteSecret() []byte {
|
|
|
|
return sk.curve.MarshalByteSecret(sk.D)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
|
|
|
|
sk.D = sk.curve.UnmarshalByteSecret(d)
|
|
|
|
|
|
|
|
if sk.D == nil {
|
|
|
|
return errors.New("eddsa: failed to parse scalar")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) {
|
|
|
|
priv = new(PrivateKey)
|
|
|
|
priv.PublicKey.curve = c
|
|
|
|
priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) {
|
|
|
|
sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r, s = priv.PublicKey.curve.MarshalSignature(sig)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func Verify(pub *PublicKey, message, r, s []byte) bool {
|
|
|
|
sig := pub.curve.UnmarshalSignature(r, s)
|
|
|
|
if sig == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return pub.curve.Verify(pub.X, message, sig)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Validate(priv *PrivateKey) error {
|
|
|
|
return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D)
|
|
|
|
}
|