1
2 package ecc
3
4 import (
5 "crypto/ecdsa"
6 "crypto/elliptic"
7 "fmt"
8 "github.com/ProtonMail/go-crypto/openpgp/errors"
9 "io"
10 "math/big"
11 )
12
13 type genericCurve struct {
14 Curve elliptic.Curve
15 }
16
17 func NewGenericCurve(c elliptic.Curve) *genericCurve {
18 return &genericCurve{
19 Curve: c,
20 }
21 }
22
23 func (c *genericCurve) GetCurveName() string {
24 return c.Curve.Params().Name
25 }
26
27 func (c *genericCurve) MarshalBytePoint(point []byte) []byte {
28 return point
29 }
30
31 func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte {
32 return point
33 }
34
35 func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte {
36 return elliptic.Marshal(c.Curve, x, y)
37 }
38
39 func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) {
40 return elliptic.Unmarshal(c.Curve, point)
41 }
42
43 func (c *genericCurve) MarshalByteSecret(d []byte) []byte {
44 return d
45 }
46
47 func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte {
48 return d
49 }
50
51 func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte {
52 return d.Bytes()
53 }
54
55 func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int {
56 return new(big.Int).SetBytes(d)
57 }
58
59 func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) {
60 secret, x, y, err := elliptic.GenerateKey(c.Curve, rand)
61 if err != nil {
62 return nil, nil, err
63 }
64
65 point = elliptic.Marshal(c.Curve, x, y)
66 return point, secret, nil
67 }
68
69 func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) {
70 priv, err := ecdsa.GenerateKey(c.Curve, rand)
71 if err != nil {
72 return
73 }
74
75 return priv.X, priv.Y, priv.D, nil
76 }
77
78 func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
79 xP, yP := elliptic.Unmarshal(c.Curve, point)
80 if xP == nil {
81 panic("invalid point")
82 }
83
84 d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
85 if err != nil {
86 return nil, nil, err
87 }
88
89 vsG := elliptic.Marshal(c.Curve, x, y)
90 zbBig, _ := c.Curve.ScalarMult(xP, yP, d)
91
92 byteLen := (c.Curve.Params().BitSize + 7) >> 3
93 zb := make([]byte, byteLen)
94 zbBytes := zbBig.Bytes()
95 copy(zb[byteLen-len(zbBytes):], zbBytes)
96
97 return vsG, zb, nil
98 }
99
100 func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
101 x, y := elliptic.Unmarshal(c.Curve, ephemeral)
102 zbBig, _ := c.Curve.ScalarMult(x, y, secret)
103 byteLen := (c.Curve.Params().BitSize + 7) >> 3
104 zb := make([]byte, byteLen)
105 zbBytes := zbBig.Bytes()
106 copy(zb[byteLen-len(zbBytes):], zbBytes)
107
108 return zb, nil
109 }
110
111 func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) {
112 priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}}
113 return ecdsa.Sign(rand, priv, hash)
114 }
115
116 func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool {
117 pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}
118 return ecdsa.Verify(pub, hash, r, s)
119 }
120
121 func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error {
122
123 zero := new(big.Int)
124 if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 {
125 return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name))
126 }
127
128
129
130 expectedX, expectedY := c.Curve.ScalarBaseMult(secret)
131 if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 {
132 return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
133 }
134
135 return nil
136 }
137
138 func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error {
139 return c.validate(xP, yP, secret)
140 }
141
142 func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error {
143 xP, yP := elliptic.Unmarshal(c.Curve, point)
144 if xP == nil {
145 return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
146 }
147
148 return c.validate(xP, yP, secret)
149 }
150
View as plain text