...

Source file src/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.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/subtle"
     6  	"io"
     7  
     8  	"github.com/ProtonMail/go-crypto/openpgp/errors"
     9  	x448lib "github.com/cloudflare/circl/dh/x448"
    10  )
    11  
    12  type x448 struct{}
    13  
    14  func NewX448() *x448 {
    15  	return &x448{}
    16  }
    17  
    18  func (c *x448) GetCurveName() string {
    19  	return "x448"
    20  }
    21  
    22  // MarshalBytePoint encodes the public point from native format, adding the prefix.
    23  // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
    24  func (c *x448) MarshalBytePoint(point []byte) []byte {
    25  	return append([]byte{0x40}, point...)
    26  }
    27  
    28  // UnmarshalBytePoint decodes a point from prefixed format to native.
    29  // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
    30  func (c *x448) UnmarshalBytePoint(point []byte) []byte {
    31  	if len(point) != x448lib.Size+1 {
    32  		return nil
    33  	}
    34  
    35  	return point[1:]
    36  }
    37  
    38  // MarshalByteSecret encoded a scalar from native format to prefixed.
    39  // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
    40  func (c *x448) MarshalByteSecret(d []byte) []byte {
    41  	return append([]byte{0x40}, d...)
    42  }
    43  
    44  // UnmarshalByteSecret decodes a scalar from prefixed format to native.
    45  // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
    46  func (c *x448) UnmarshalByteSecret(d []byte) []byte {
    47  	if len(d) != x448lib.Size+1 {
    48  		return nil
    49  	}
    50  
    51  	// Store without prefix
    52  	return d[1:]
    53  }
    54  
    55  func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) {
    56  	if _, err = rand.Read(sk[:]); err != nil {
    57  		return
    58  	}
    59  
    60  	x448lib.KeyGen(&pk, &sk)
    61  	return
    62  }
    63  
    64  func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
    65  	priv, pub, err := c.generateKeyPairBytes(rand)
    66  	if err != nil {
    67  		return
    68  	}
    69  
    70  	return pub[:], priv[:], nil
    71  }
    72  
    73  func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
    74  	var pk, ss x448lib.Key
    75  	seed, e, err := c.generateKeyPairBytes(rand)
    76  	if err != nil {
    77  		return nil, nil, err
    78  	}
    79  	copy(pk[:], point)
    80  	x448lib.Shared(&ss, &seed, &pk)
    81  
    82  	return e[:], ss[:], nil
    83  }
    84  
    85  func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
    86  	var ss, sk, e x448lib.Key
    87  
    88  	copy(sk[:], secret)
    89  	copy(e[:], ephemeral)
    90  	x448lib.Shared(&ss, &sk, &e)
    91  
    92  	return ss[:], nil
    93  }
    94  
    95  func (c *x448) ValidateECDH(point []byte, secret []byte) error {
    96  	var sk, pk, expectedPk x448lib.Key
    97  
    98  	copy(pk[:], point)
    99  	copy(sk[:], secret)
   100  	x448lib.KeyGen(&expectedPk, &sk)
   101  
   102  	if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 {
   103  		return errors.KeyInvalidError("ecc: invalid curve25519 public point")
   104  	}
   105  
   106  	return nil
   107  }
   108  

View as plain text