File: eddsa.go

package info (click to toggle)
golang-github-protonmail-go-crypto 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,932 kB
  • sloc: makefile: 10
file content (91 lines) | stat: -rw-r--r-- 1,936 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// 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 {
	X     []byte
	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)
}