Add existing HPKE project files
This commit is contained in:
130
aead.go
Normal file
130
aead.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package hpke
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
)
|
||||
|
||||
// The AEAD is one of the three components of an HPKE ciphersuite, implementing
|
||||
// symmetric encryption.
|
||||
type AEAD interface {
|
||||
ID() uint16
|
||||
keySize() int
|
||||
nonceSize() int
|
||||
aead(key []byte) (cipher.AEAD, error)
|
||||
}
|
||||
|
||||
// NewAEAD returns the AEAD implementation for the given AEAD ID.
|
||||
//
|
||||
// Applications are encouraged to use specific implementations like [AES128GCM]
|
||||
// or [ChaCha20Poly1305] instead, unless runtime agility is required.
|
||||
func NewAEAD(id uint16) (AEAD, error) {
|
||||
switch id {
|
||||
case 0x0001: // AES-128-GCM
|
||||
return AES128GCM(), nil
|
||||
case 0x0002: // AES-256-GCM
|
||||
return AES256GCM(), nil
|
||||
case 0x0003: // ChaCha20Poly1305
|
||||
return ChaCha20Poly1305(), nil
|
||||
case 0xFFFF: // Export-only
|
||||
return ExportOnly(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported AEAD %04x", id)
|
||||
}
|
||||
}
|
||||
|
||||
// AES128GCM returns an AES-128-GCM AEAD implementation.
|
||||
func AES128GCM() AEAD { return aes128GCM }
|
||||
|
||||
// AES256GCM returns an AES-256-GCM AEAD implementation.
|
||||
func AES256GCM() AEAD { return aes256GCM }
|
||||
|
||||
// ChaCha20Poly1305 returns a ChaCha20Poly1305 AEAD implementation.
|
||||
func ChaCha20Poly1305() AEAD { return chacha20poly1305AEAD }
|
||||
|
||||
// ExportOnly returns a placeholder AEAD implementation that cannot encrypt or
|
||||
// decrypt, but only export secrets with [Sender.Export] or [Recipient.Export].
|
||||
//
|
||||
// When this is used, [Sender.Seal] and [Recipient.Open] return errors.
|
||||
func ExportOnly() AEAD { return exportOnlyAEAD{} }
|
||||
|
||||
type aead struct {
|
||||
nK int
|
||||
nN int
|
||||
new func([]byte) (cipher.AEAD, error)
|
||||
id uint16
|
||||
}
|
||||
|
||||
var aes128GCM = &aead{
|
||||
nK: 128 / 8,
|
||||
nN: 96 / 8,
|
||||
new: newAESGCM,
|
||||
id: 0x0001,
|
||||
}
|
||||
|
||||
var aes256GCM = &aead{
|
||||
nK: 256 / 8,
|
||||
nN: 96 / 8,
|
||||
new: newAESGCM,
|
||||
id: 0x0002,
|
||||
}
|
||||
|
||||
var chacha20poly1305AEAD = &aead{
|
||||
nK: chacha20poly1305.KeySize,
|
||||
nN: chacha20poly1305.NonceSize,
|
||||
new: chacha20poly1305.New,
|
||||
id: 0x0003,
|
||||
}
|
||||
|
||||
func newAESGCM(key []byte) (cipher.AEAD, error) {
|
||||
b, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cipher.NewGCM(b)
|
||||
}
|
||||
|
||||
func (a *aead) ID() uint16 {
|
||||
return a.id
|
||||
}
|
||||
|
||||
func (a *aead) aead(key []byte) (cipher.AEAD, error) {
|
||||
if len(key) != a.nK {
|
||||
return nil, errors.New("invalid key size")
|
||||
}
|
||||
return a.new(key)
|
||||
}
|
||||
|
||||
func (a *aead) keySize() int {
|
||||
return a.nK
|
||||
}
|
||||
|
||||
func (a *aead) nonceSize() int {
|
||||
return a.nN
|
||||
}
|
||||
|
||||
type exportOnlyAEAD struct{}
|
||||
|
||||
func (exportOnlyAEAD) ID() uint16 {
|
||||
return 0xFFFF
|
||||
}
|
||||
|
||||
func (exportOnlyAEAD) aead(key []byte) (cipher.AEAD, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (exportOnlyAEAD) keySize() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (exportOnlyAEAD) nonceSize() int {
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user