main
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}