...

Source file src/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/internal/ecc

     1  // Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
     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  	// the public point should not be at infinity (0,0)
   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  	// re-derive the public point Q' = (X,Y) = dG
   129  	// to compare to declared Q in public key
   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