main
Raw Download raw file
 1// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in
 2// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
 3package eddsa
 4
 5import (
 6	"errors"
 7	"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
 8	"io"
 9)
10
11type PublicKey struct {
12	X     []byte
13	curve ecc.EdDSACurve
14}
15
16type PrivateKey struct {
17	PublicKey
18	D []byte
19}
20
21func NewPublicKey(curve ecc.EdDSACurve) *PublicKey {
22	return &PublicKey{
23		curve: curve,
24	}
25}
26
27func NewPrivateKey(key PublicKey) *PrivateKey {
28	return &PrivateKey{
29		PublicKey: key,
30	}
31}
32
33func (pk *PublicKey) GetCurve() ecc.EdDSACurve {
34	return pk.curve
35}
36
37func (pk *PublicKey) MarshalPoint() []byte {
38	return pk.curve.MarshalBytePoint(pk.X)
39}
40
41func (pk *PublicKey) UnmarshalPoint(x []byte) error {
42	pk.X = pk.curve.UnmarshalBytePoint(x)
43
44	if pk.X == nil {
45		return errors.New("eddsa: failed to parse EC point")
46	}
47	return nil
48}
49
50func (sk *PrivateKey) MarshalByteSecret() []byte {
51	return sk.curve.MarshalByteSecret(sk.D)
52}
53
54func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
55	sk.D = sk.curve.UnmarshalByteSecret(d)
56
57	if sk.D == nil {
58		return errors.New("eddsa: failed to parse scalar")
59	}
60	return nil
61}
62
63func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) {
64	priv = new(PrivateKey)
65	priv.PublicKey.curve = c
66	priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand)
67	return
68}
69
70func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) {
71	sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message)
72	if err != nil {
73		return nil, nil, err
74	}
75
76	r, s = priv.PublicKey.curve.MarshalSignature(sig)
77	return
78}
79
80func Verify(pub *PublicKey, message, r, s []byte) bool {
81	sig := pub.curve.UnmarshalSignature(r, s)
82	if sig == nil {
83		return false
84	}
85
86	return pub.curve.Verify(pub.X, message, sig)
87}
88
89func Validate(priv *PrivateKey) error {
90	return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D)
91}