...

Package hpke

import "github.com/cloudflare/circl/hpke"
Overview
Index
Examples

Overview ▾

Package hpke implements the Hybrid Public Key Encryption (HPKE) standard specified by draft-irtf-cfrg-hpke-07.

HPKE works for any combination of a public-key encapsulation mechanism (KEM), a key derivation function (KDF), and an authenticated encryption scheme with additional data (AEAD).

Specification in https://datatracker.ietf.org/doc/draft-irtf-cfrg-hpke

BUG(cjpatton): This package does not implement the "Export-Only" mode of the HPKE context. In particular, it does not recognize the AEAD codepoint reserved for this purpose (0xFFFF).

Example

Code:

// import "github.com/cloudflare/circl/hpke"
// import "crypto/rand"

// HPKE suite is a domain parameter.
kemID := hpke.KEM_P384_HKDF_SHA384
kdfID := hpke.KDF_HKDF_SHA384
aeadID := hpke.AEAD_AES256GCM
suite := hpke.NewSuite(kemID, kdfID, aeadID)
info := []byte("public info string, known to both Alice and Bob")

// Bob prepares to receive messages and announces his public key.
publicBob, privateBob, err := kemID.Scheme().GenerateKeyPair()
if err != nil {
    panic(err)
}
Bob, err := suite.NewReceiver(privateBob, info)
if err != nil {
    panic(err)
}

// Alice gets Bob's public key.
Alice, err := suite.NewSender(publicBob, info)
if err != nil {
    panic(err)
}
enc, sealer, err := Alice.Setup(rand.Reader)
if err != nil {
    panic(err)
}

// Alice encrypts some plaintext and sends the ciphertext to Bob.
ptAlice := []byte("text encrypted to Bob's public key")
aad := []byte("additional public data")
ct, err := sealer.Seal(ptAlice, aad)
if err != nil {
    panic(err)
}

// Bob decrypts the ciphertext.
opener, err := Bob.Setup(enc)
if err != nil {
    panic(err)
}
ptBob, err := opener.Open(ct, aad)
if err != nil {
    panic(err)
}

// Plaintext was sent successfully.
fmt.Println(bytes.Equal(ptAlice, ptBob))

Output:

true

Index ▾

Variables
type AEAD
    func (a AEAD) CipherLen(mLen uint) uint
    func (a AEAD) IsValid() bool
    func (a AEAD) KeySize() uint
    func (a AEAD) New(key []byte) (cipher.AEAD, error)
    func (a AEAD) NonceSize() uint
type Context
type KDF
    func (k KDF) Expand(pseudorandomKey, info []byte, outputLen uint) []byte
    func (k KDF) Extract(secret, salt []byte) (pseudorandomKey []byte)
    func (k KDF) ExtractSize() int
    func (k KDF) IsValid() bool
type KEM
    func (k KEM) IsValid() bool
    func (k KEM) Scheme() kem.AuthScheme
type Opener
    func UnmarshalOpener(raw []byte) (Opener, error)
type Receiver
    func (r *Receiver) Setup(enc []byte) (Opener, error)
    func (r *Receiver) SetupAuth(enc []byte, pkS kem.PublicKey) (Opener, error)
    func (r *Receiver) SetupAuthPSK(enc, psk, pskID []byte, pkS kem.PublicKey) (Opener, error)
    func (r *Receiver) SetupPSK(enc, psk, pskID []byte) (Opener, error)
type Sealer
    func UnmarshalSealer(raw []byte) (Sealer, error)
type Sender
    func (s *Sender) Setup(rnd io.Reader) (enc []byte, seal Sealer, err error)
    func (s *Sender) SetupAuth(rnd io.Reader, skS kem.PrivateKey) (enc []byte, seal Sealer, err error)
    func (s *Sender) SetupAuthPSK(rnd io.Reader, skS kem.PrivateKey, psk, pskID []byte) (enc []byte, seal Sealer, err error)
    func (s *Sender) SetupPSK(rnd io.Reader, psk, pskID []byte) (enc []byte, seal Sealer, err error)
type Suite
    func NewSuite(kemID KEM, kdfID KDF, aeadID AEAD) Suite
    func (suite Suite) NewReceiver(skR kem.PrivateKey, info []byte) (*Receiver, error)
    func (suite Suite) NewSender(pkR kem.PublicKey, info []byte) (*Sender, error)
    func (suite Suite) Params() (KEM, KDF, AEAD)
    func (suite Suite) String() string

Examples

Package

Package files

aead.go algs.go hpke.go hybridkem.go kembase.go marshal.go shortkem.go util.go xkem.go

Variables

var (
    ErrInvalidHPKESuite       = errors.New("hpke: invalid HPKE suite")
    ErrInvalidKDF             = errors.New("hpke: invalid KDF identifier")
    ErrInvalidKEM             = errors.New("hpke: invalid KEM identifier")
    ErrInvalidAEAD            = errors.New("hpke: invalid AEAD identifier")
    ErrInvalidKEMPublicKey    = errors.New("hpke: invalid KEM public key")
    ErrInvalidKEMPrivateKey   = errors.New("hpke: invalid KEM private key")
    ErrInvalidKEMSharedSecret = errors.New("hpke: invalid KEM shared secret")
    ErrAEADSeqOverflows       = errors.New("hpke: AEAD sequence number overflows")
)

type AEAD

type AEAD uint16
const (
    // AEAD_AES128GCM is AES-128 block cipher in Galois Counter Mode (GCM).
    AEAD_AES128GCM AEAD = 0x01
    // AEAD_AES256GCM is AES-256 block cipher in Galois Counter Mode (GCM).
    AEAD_AES256GCM AEAD = 0x02
    // AEAD_ChaCha20Poly1305 is ChaCha20 stream cipher and Poly1305 MAC.
    AEAD_ChaCha20Poly1305 AEAD = 0x03
)

func (AEAD) CipherLen

func (a AEAD) CipherLen(mLen uint) uint

CipherLen returns the length of a ciphertext corresponding to a message of length mLen.

func (AEAD) IsValid

func (a AEAD) IsValid() bool

func (AEAD) KeySize

func (a AEAD) KeySize() uint

KeySize returns the size in bytes of the keys used by the AEAD cipher.

func (AEAD) New

func (a AEAD) New(key []byte) (cipher.AEAD, error)

New instantiates an AEAD cipher from the identifier, returns an error if the identifier is not known.

func (AEAD) NonceSize

func (a AEAD) NonceSize() uint

NonceSize returns the size in bytes of the nonce used by the AEAD cipher.

type Context

Context defines the capabilities of an HPKE context.

type Context interface {
    encoding.BinaryMarshaler
    // Export takes a context string exporterContext and a desired length (in
    // bytes), and produces a secret derived from the internal exporter secret
    // using the corresponding KDF Expand function. It panics if length is
    // greater than 255*N bytes, where N is the size (in bytes) of the KDF's
    // output.
    Export(exporterContext []byte, length uint) []byte
    // Suite returns the cipher suite corresponding to this context.
    Suite() Suite
}

type KDF

type KDF uint16
const (
    // KDF_HKDF_SHA256 is a KDF using HKDF with SHA-256.
    KDF_HKDF_SHA256 KDF = 0x01
    // KDF_HKDF_SHA384 is a KDF using HKDF with SHA-384.
    KDF_HKDF_SHA384 KDF = 0x02
    // KDF_HKDF_SHA512 is a KDF using HKDF with SHA-512.
    KDF_HKDF_SHA512 KDF = 0x03
)

func (KDF) Expand

func (k KDF) Expand(pseudorandomKey, info []byte, outputLen uint) []byte

Expand derives a variable length pseudorandom string from a pseudorandom key and an information string. Panics if the pseudorandom key is less than N bytes, or if the output length is greater than 255*N bytes, where N is the size returned by KDF.Extract function.

func (KDF) Extract

func (k KDF) Extract(secret, salt []byte) (pseudorandomKey []byte)

Extract derives a pseudorandom key from a high-entropy, secret input and a salt. The size of the output is determined by KDF.ExtractSize.

func (KDF) ExtractSize

func (k KDF) ExtractSize() int

ExtractSize returns the size (in bytes) of the pseudorandom key produced by KDF.Extract.

func (KDF) IsValid

func (k KDF) IsValid() bool

type KEM

type KEM uint16
const (
    // KEM_P256_HKDF_SHA256 is a KEM using P256 curve and HKDF with SHA-256.
    KEM_P256_HKDF_SHA256 KEM = 0x10
    // KEM_P384_HKDF_SHA384 is a KEM using P384 curve and HKDF with SHA-384.
    KEM_P384_HKDF_SHA384 KEM = 0x11
    // KEM_P521_HKDF_SHA512 is a KEM using P521 curve and HKDF with SHA-512.
    KEM_P521_HKDF_SHA512 KEM = 0x12
    // KEM_X25519_HKDF_SHA256 is a KEM using X25519 Diffie-Hellman function
    // and HKDF with SHA-256.
    KEM_X25519_HKDF_SHA256 KEM = 0x20
    // KEM_X448_HKDF_SHA512 is a KEM using X448 Diffie-Hellman function and
    // HKDF with SHA-512.
    KEM_X448_HKDF_SHA512 KEM = 0x21
    // KEM_X25519_KYBER768_DRAFT00 is a hybrid KEM built on DHKEM(X25519, HKDF-SHA256)
    // and Kyber768Draft00
    KEM_X25519_KYBER768_DRAFT00 KEM = 0x30
)

func (KEM) IsValid

func (k KEM) IsValid() bool

IsValid returns true if the KEM identifier is supported by the HPKE package.

func (KEM) Scheme

func (k KEM) Scheme() kem.AuthScheme

Scheme returns an instance of a KEM that supports authentication. Panics if the KEM identifier is invalid.

type Opener

Opener decrypts a ciphertext using an AEAD encryption.

type Opener interface {
    Context
    // Open takes a ciphertext and associated data to recover, if successful,
    // the plaintext. The nonce is handled by the Opener and incremented after
    // each call.
    Open(ct, aad []byte) (pt []byte, err error)
}

func UnmarshalOpener

func UnmarshalOpener(raw []byte) (Opener, error)

UnmarshalOpener parses a serialized HPKE opener and returns the corresponding Opener.

type Receiver

Receiver performs hybrid public-key decryption.

type Receiver struct {
    // contains filtered or unexported fields
}

func (*Receiver) Setup

func (r *Receiver) Setup(enc []byte) (Opener, error)

Setup generates a new HPKE context used for Base Mode encryption. Setup takes an encapsulated key and returns an Opener.

func (*Receiver) SetupAuth

func (r *Receiver) SetupAuth(enc []byte, pkS kem.PublicKey) (Opener, error)

SetupAuth generates a new HPKE context used for Auth Mode encryption. SetupAuth takes an encapsulated key and a public key, and returns an Opener.

func (*Receiver) SetupAuthPSK

func (r *Receiver) SetupAuthPSK(
    enc, psk, pskID []byte, pkS kem.PublicKey,
) (Opener, error)

SetupAuthPSK generates a new HPKE context used for Auth-PSK Mode encryption. SetupAuthPSK takes an encapsulated key, a public key, and a pre-shared key; and returns an Opener.

func (*Receiver) SetupPSK

func (r *Receiver) SetupPSK(enc, psk, pskID []byte) (Opener, error)

SetupPSK generates a new HPKE context used for PSK Mode encryption. SetupPSK takes an encapsulated key, and a pre-shared key; and returns an Opener.

type Sealer

Sealer encrypts a plaintext using an AEAD encryption.

type Sealer interface {
    Context
    // Seal takes a plaintext and associated data to produce a ciphertext.
    // The nonce is handled by the Sealer and incremented after each call.
    Seal(pt, aad []byte) (ct []byte, err error)
}

func UnmarshalSealer

func UnmarshalSealer(raw []byte) (Sealer, error)

UnmarshalSealer parses an HPKE sealer.

type Sender

Sender performs hybrid public-key encryption.

type Sender struct {
    // contains filtered or unexported fields
}

func (*Sender) Setup

func (s *Sender) Setup(rnd io.Reader) (enc []byte, seal Sealer, err error)

Setup generates a new HPKE context used for Base Mode encryption. Returns the Sealer and corresponding encapsulated key.

func (*Sender) SetupAuth

func (s *Sender) SetupAuth(rnd io.Reader, skS kem.PrivateKey) (
    enc []byte, seal Sealer, err error,
)

SetupAuth generates a new HPKE context used for Auth Mode encryption. Returns the Sealer and corresponding encapsulated key.

func (*Sender) SetupAuthPSK

func (s *Sender) SetupAuthPSK(rnd io.Reader, skS kem.PrivateKey, psk, pskID []byte) (
    enc []byte, seal Sealer, err error,
)

SetupAuthPSK generates a new HPKE context used for Auth-PSK Mode encryption. Returns the Sealer and corresponding encapsulated key.

func (*Sender) SetupPSK

func (s *Sender) SetupPSK(rnd io.Reader, psk, pskID []byte) (
    enc []byte, seal Sealer, err error,
)

SetupPSK generates a new HPKE context used for PSK Mode encryption. Returns the Sealer and corresponding encapsulated key.

type Suite

Suite is an HPKE cipher suite consisting of a KEM, KDF, and AEAD algorithm.

type Suite struct {
    // contains filtered or unexported fields
}

func NewSuite

func NewSuite(kemID KEM, kdfID KDF, aeadID AEAD) Suite

NewSuite builds a Suite from a specified set of algorithms. Panics if an algorithm identifier is not valid.

func (Suite) NewReceiver

func (suite Suite) NewReceiver(skR kem.PrivateKey, info []byte) (
    *Receiver, error,
)

NewReceiver creates a Receiver with knowledge of a private key.

func (Suite) NewSender

func (suite Suite) NewSender(pkR kem.PublicKey, info []byte) (*Sender, error)

NewSender creates a Sender with knowledge of the receiver's public-key.

func (Suite) Params

func (suite Suite) Params() (KEM, KDF, AEAD)

Params returns the codepoints for the algorithms comprising the suite.

func (Suite) String

func (suite Suite) String() string