123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- package tls
- import (
- "crypto/ecdh"
- "crypto/rand"
- "encoding/pem"
- "golang.org/x/crypto/cryptobyte"
- )
- type ECHCapableConfig interface {
- Config
- ECHConfigList() []byte
- SetECHConfigList([]byte)
- }
- func ECHKeygenDefault(publicName string) (configPem string, keyPem string, err error) {
- echKey, err := ecdh.X25519().GenerateKey(rand.Reader)
- if err != nil {
- return
- }
- echConfig, err := marshalECHConfig(0, echKey.PublicKey().Bytes(), publicName, 0)
- if err != nil {
- return
- }
- configBuilder := cryptobyte.NewBuilder(nil)
- configBuilder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddBytes(echConfig)
- })
- configBytes, err := configBuilder.Bytes()
- if err != nil {
- return
- }
- keyBuilder := cryptobyte.NewBuilder(nil)
- keyBuilder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddBytes(echKey.Bytes())
- })
- keyBuilder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddBytes(echConfig)
- })
- keyBytes, err := keyBuilder.Bytes()
- if err != nil {
- return
- }
- configPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBytes}))
- keyPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBytes}))
- return
- }
- func marshalECHConfig(id uint8, pubKey []byte, publicName string, maxNameLen uint8) ([]byte, error) {
- const extensionEncryptedClientHello = 0xfe0d
- const DHKEM_X25519_HKDF_SHA256 = 0x0020
- const KDF_HKDF_SHA256 = 0x0001
- builder := cryptobyte.NewBuilder(nil)
- builder.AddUint16(extensionEncryptedClientHello)
- builder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddUint8(id)
- builder.AddUint16(DHKEM_X25519_HKDF_SHA256) // The only DHKEM we support
- builder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddBytes(pubKey)
- })
- builder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) {
- const (
- AEAD_AES_128_GCM = 0x0001
- AEAD_AES_256_GCM = 0x0002
- AEAD_ChaCha20Poly1305 = 0x0003
- )
- for _, aeadID := range []uint16{AEAD_AES_128_GCM, AEAD_AES_256_GCM, AEAD_ChaCha20Poly1305} {
- builder.AddUint16(KDF_HKDF_SHA256) // The only KDF we support
- builder.AddUint16(aeadID)
- }
- })
- builder.AddUint8(maxNameLen)
- builder.AddUint8LengthPrefixed(func(builder *cryptobyte.Builder) {
- builder.AddBytes([]byte(publicName))
- })
- builder.AddUint16(0) // extensions
- })
- return builder.Bytes()
- }
|