commit 534572b8834b17d1e6c50dddceb7af9530da1858 Author: patrick Date: Fri Mar 6 23:52:07 2026 +0000 Add existing HPKE project files diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..2a7cf70 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/aead.go b/aead.go new file mode 100644 index 0000000..1a606c6 --- /dev/null +++ b/aead.go @@ -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 +} diff --git a/crypto/ecdh/interfaces.go b/crypto/ecdh/interfaces.go new file mode 100644 index 0000000..606f9fc --- /dev/null +++ b/crypto/ecdh/interfaces.go @@ -0,0 +1,15 @@ +// Package ecdh defines an additional interface that will be added to the +// crypto/ecdh package in Go 1.26+. +package ecdh + +import "crypto/ecdh" + +// KeyExchanger is an interface for an opaque private key that can be used for +// key exchange operations. For example, an ECDH key kept in a hardware module. +// +// It is implemented by [ecdh.PrivateKey]. +type KeyExchanger interface { + PublicKey() *ecdh.PublicKey + Curve() ecdh.Curve + ECDH(*ecdh.PublicKey) ([]byte, error) +} diff --git a/crypto/ecdh/stubs.go b/crypto/ecdh/stubs.go new file mode 100644 index 0000000..7039e00 --- /dev/null +++ b/crypto/ecdh/stubs.go @@ -0,0 +1,15 @@ +package ecdh + +import "crypto/ecdh" + +// This file contains stubs to allow importing only this package instead of +// crypto/ecdh, to minimize the diff. + +type Curve = ecdh.Curve +type PrivateKey = ecdh.PrivateKey +type PublicKey = ecdh.PublicKey + +func X25519() Curve { return ecdh.X25519() } +func P256() Curve { return ecdh.P256() } +func P384() Curve { return ecdh.P384() } +func P521() Curve { return ecdh.P521() } diff --git a/crypto/interfaces.go b/crypto/interfaces.go new file mode 100644 index 0000000..ae312af --- /dev/null +++ b/crypto/interfaces.go @@ -0,0 +1,68 @@ +// Package crypto defines additional interfaces that will be added to the +// crypto package in Go 1.26+. +package crypto + +import ( + "crypto/ecdh" + "crypto/mlkem" +) + +// KeyExchanger is an interface for an opaque private key that can be used for +// key exchange operations. For example, an ECDH key kept in a hardware module. +// +// It is implemented by [ecdh.PrivateKey]. +type KeyExchanger interface { + PublicKey() *ecdh.PublicKey + Curve() ecdh.Curve + ECDH(*ecdh.PublicKey) ([]byte, error) +} + +// Encapsulator is an interface for a public KEM key that can be used for +// encapsulation operations. +// +// It is implemented, for example, by [crypto/mlkem.EncapsulationKey768]. +type Encapsulator interface { + Bytes() []byte + Encapsulate() (sharedKey, ciphertext []byte) +} + +// Decapsulator is an interface for an opaque private KEM key that can be used for +// decapsulation operations. For example, an ML-KEM key kept in a hardware module. +// +// It will be implemented by [crypto/mlkem.DecapsulationKey768] in Go 1.26+. +// In the meantime, use [DecapsulatorFromDecapsulationKey768] and +// [DecapsulatorFromDecapsulationKey1024]. +type Decapsulator interface { + Encapsulator() Encapsulator + Decapsulate(ciphertext []byte) (sharedKey []byte, err error) +} + +// DecapsulatorFromDecapsulationKey768 wraps an ML-KEM-768 decapsulation key +// into a [Decapsulator], until Go 1.26+ where [crypto/mlkem.DecapsulationKey768] +// implements it natively. +func DecapsulatorFromDecapsulationKey768(dk *mlkem.DecapsulationKey768) Decapsulator { + return &mlkem768Decapsulator{dk} +} + +type mlkem768Decapsulator struct { + *mlkem.DecapsulationKey768 +} + +func (d *mlkem768Decapsulator) Encapsulator() Encapsulator { + return d.EncapsulationKey() +} + +// DecapsulatorFromDecapsulationKey1024 wraps an ML-KEM-1024 decapsulation key +// into a [Decapsulator], until Go 1.26+ where [crypto/mlkem.DecapsulationKey1024] +// implements it natively. +func DecapsulatorFromDecapsulationKey1024(dk *mlkem.DecapsulationKey1024) Decapsulator { + return &mlkem1024Decapsulator{dk} +} + +type mlkem1024Decapsulator struct { + *mlkem.DecapsulationKey1024 +} + +func (d *mlkem1024Decapsulator) Encapsulator() Encapsulator { + return d.EncapsulationKey() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..41825a1 --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module sources.truenas.cloud/code/hpke + +go 1.24.0 + +require golang.org/x/crypto v0.41.0 + +require golang.org/x/sys v0.35.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9e67244 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= diff --git a/hpke-pq.md b/hpke-pq.md new file mode 100644 index 0000000..c06f701 --- /dev/null +++ b/hpke-pq.md @@ -0,0 +1,262 @@ +# HPKE Hybrid KEMs + +[sources.truenas.cloud/code/hpke-pq](https://sources.truenas.cloud/code/hpke-pq) + +This document is a simplified and self-contained implementation reference for +the MLKEM768-X25519, MLKEM768-P256, and MLKEM1024-P384 hybrid HPKE KEMs, +specified in [draft-ietf-hpke-pq-03][], [draft-irtf-cfrg-hybrid-kems-07][], +[draft-irtf-cfrg-concrete-hybrid-kems-02][], and [draft-ietf-hpke-hpke-02]. + +It compensates for the need to cross-reference four documents, with different +nomenclature (including functions and components with the same name but +different behavior), alternative irrelevant definitions (the UG, UK, and CK +frameworks), and multiple KEM abstraction layers. + +## Conventions used in this document + +`||` denotes concatenation. `[N:M]` denotes the byte slice from index N (inclusive) +to index M (exclusive). Strings quoted with `""` are encoded as ASCII. Values in +code blocks are hex encoded byte strings. `random(N)` denotes N bytes of CSPRNG +output. All lengths are in bytes. + +ML-KEM.KeyGen_internal, ML-KEM.Encaps, ML-KEM.Encaps_internal, and ML-KEM.Decaps +are defined in [FIPS 203][]. `SHAKE256(s, L)` is an invocation of `SHAKE256(s, 8*L)` +defined in [FIPS 202][]. SHA3-256 is defined in [FIPS 202][]. + +## KEM definitions + +| Parameter | MLKEM768-X25519 | MLKEM768-P256 | MLKEM1024-P384 | +| ----------------- | ------------------ | ------------------ | ------------------ | +| ML-KEM parameters | ML-KEM-768 | ML-KEM-768 | ML-KEM-1024 | +| Group | Curve25519 | P-256 | P-384 | +| KEM identifier | 0x647a | 0x0050 | 0x0051 | +| Nsecret | 32 | 32 | 32 | +| Nenc | 1120 | 1153 | 1665 | +| Npk | 1216 | 1249 | 1665 | +| Nsk | 32 | 32 | 32 | +| Nrandom | 64 | 160 | 80 | +| Label | `"\.//^\"` | `"MLKEM768-P256"` | `"MLKEM1024-P384"` | +| KEM.Nct | 1088 | 1088 | 1568 | +| KEM.Nek | 1184 | 1184 | 1568 | +| KEM.Nseed | 64 | 64 | 64 | +| KEM.Nrandom | 32 | 32 | 32 | +| Group.Nelem | 32 | 65 | 97 | +| Group.Nseed | 32 | 128 | 48 | +| Group.Nscalar | N/A | 32 | 48 | + +The MLKEM768-X25519 Label is alternatively encoded as + + 5c2e2f2f5e5c + +## KEM functions + +``` +def GenerateKeyPair(): + seed = random(Nsk) + + ek_PQ, ek_T, _, _ = expandKey(seed) + ek = ek_PQ || ek_T + + return (seed, ek) + +def DeriveKeyPair(ikm): + # SHAKE256.LabeledDerive is part of the single-stage KDF described in + # draft-ietf-hpke-hpke-02 and defined in draft-ietf-hpke-pq-03, but is + # reproduced below for convenience. + seed = SHAKE256.LabeledDerive(ikm, "DeriveKeyPair", "", Nsk) + + ek_PQ, ek_T, _, _ = expandKey(seed) + ek = ek_PQ || ek_T + + return (seed, ek) + +def Encaps(ek): + ek_PQ = ek[0 : KEM.Nek] + ek_T = ek[KEM.Nek : KEM.Nek + Group.Nelem] + + ss_PQ, ct_PQ = ML-KEM.Encaps(ek_PQ) + + sk_E = Group.RandomScalar(random(Group.Nseed)) + ct_T = Group.Exp(Group.G, sk_E) + ss_T = Group.ElementToSharedSecret(Group.Exp(ek_T, sk_E)) + + ss = SHA3-256(ss_PQ || ss_T || ct_T || ek_T || Label) + ct = ct_PQ || ct_T + + return (ss, ct) + +def Decaps(seed, ct): + ct_PQ = ct[0 : KEM.Nct] + ct_T = ct[KEM.Nct : KEM.Nct + Group.Nelem] + + ek_PQ, ek_T, dk_PQ, dk_T = expandKey(seed) + + ss_PQ = ML-KEM.Decaps(dk_PQ, ct_PQ) + ss_T = Group.ElementToSharedSecret(Group.Exp(ct_T, dk_T)) + + ss = SHA3-256(ss_PQ || ss_T || ct_T || ek_T || Label) + + return ss + +def expandKey(seed): + seed_full = SHAKE256(seed, KEM.Nseed + Group.Nseed) + seed_PQ = seed_full[0 : KEM.Nseed] + seed_T = seed_full[KEM.Nseed : KEM.Nseed + Group.Nseed] + + # Note that even if expandKey returns the semi-expanded ML-KEM decapsulation + # key dk_PQ to use FIPS 203 definitions, that format should be avoided and + # instead seed_PQ should be expanded directly into the implementation's + # internal ML-KEM private representation. + (ek_PQ, dk_PQ) = ML-KEM.KeyGen_internal(seed_PQ) + dk_T = Group.RandomScalar(seed_T) + ek_T = Group.Exp(Group.G, dk_T) + + return (ek_PQ, ek_T, dk_PQ, dk_T) +``` + +There is no distinction between a private/public key and its serialization: +there is no abstract key format, only byte strings. In practice, implementations +will probably want to load keys into pairs of internal representations, and +serialize them back to their byte string format when needed. + +The IETF/IRTF documents lack a specified way to turn a private key into public +key, although it can be inferred from the key generation process. We define such +a process here as `PrivateKeyToPublicKey`. + +``` +def PrivateKeyToPublicKey(seed): + ek_PQ, ek_T, _, _ = expandKey(seed) + ek = ek_PQ || ek_T + + return ek +``` + +### Deterministic Encapsulation + +For testing purposes, implementations can provide Nrandom bytes of encapsulation +randomness to the deterministic internal function `EncapsDerand`. + +``` +def EncapsDerand(ek, randomness): + ek_PQ = ek[0 : KEM.Nek] + ek_T = ek[KEM.Nek : KEM.Nek + Group.Nelem] + + randomness_PQ = randomness[0 : KEM.Nrandom] + randomness_T = randomness[KEM.Nrandom : KEM.Nrandom + Group.Nseed] + + ss_PQ, ct_PQ = ML-KEM.Encaps_internal(ek_PQ, randomness_PQ) + + sk_E = Group.RandomScalar(randomness_T) + ct_T = Group.Exp(Group.G, sk_E) + ss_T = Group.ElementToSharedSecret(Group.Exp(ek_T, sk_E)) + + ss = SHA3-256(ss_PQ || ss_T || ct_T || ek_T || Label) + ct = ct_PQ || ct_T + + return (ss, ct) +``` + +## Group definitions + +### Curve25519 + +Group.Exp is the X25519 function defined in [RFC 7748][]. + +Group.G is the canonical generator, which encodes to + + 0900000000000000000000000000000000000000000000000000000000000000 + +consistently with [RFC 7748, Section 4.1][] and [RFC 7748, Section 6.1][]. + +Group.RandomScalar and Group.ElementToSharedSecret are the identity. + +### P-256 and P-384 + +The NIST P-256 and P-384 elliptic curves are defined in [SP800-186][]. + +`Group.Exp(p, x)` computes scalar multiplication between the input element p and +the scalar x. The input element p and the output element have length Group.Nelem +and are encoded in uncompressed representation using the +Elliptic-Curve-Point-to-Octet-String and Octet-String-to-Elliptic-Curve-Point +functions defined in [SEC 1, Version 2.0][]. The input scalar x has length +Group.Nscalar and is encoded in big-endian representation using the I2OSP and +OS2IP functions defined in [RFC 8017][]. + +Group.G is the canonical generator, which encodes to + + 046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29 + 64fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 + +for P-256, and to + + 04aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab + 73617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f + +for P-384, consistently with [SP800-186][], Section 3.2.1. + +``` +def Group.RandomScalar(seed): + start = 0 + end = Nscalar + sk = seed[start : end] + while OS2IP(sk) == 0 || OS2IP(sk) >= OS2IP(Group.N): + start = end + end = end + Nscalar + if end > len(seed): + # This happens with cryptographically negligible probability. + # The chance of a single rejection is < 2^-32 for P-256 and + # < 2^-192 for P-384. The chance of reaching this is thus + # < 2^-128 for P-256 and < 2^-192 for P-384. + raise Exception("Rejection sampling failed") + sk = seed[start : end] + return sk +``` + +Group.N is the order of the curve's group, which encodes to + + ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + +for P-256, and to + + ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 + +for P-384, consistently with [SP800-186][], Section 3.2.1. + +Group.ElementToSharedSecret encodes the input element as an X coordinate using +the Field-Element-to-Octet-String function in [SEC 1, Version 2.0][]. + +> Note that since the scalar x is always derived uniformly at random, the chance +> of it being zero are cryptographically negligible. Moreover, +> Octet-String-to-Elliptic-Curve-Point never decodes the point at infinity from +> a string of Group.Nelem bytes. Since NIST P curves have prime order, this +> means that the output of Group.Exp and input to Group.ElementToSharedSecret is +> also never the point at infinity. + +## SHAKE256.LabeledDerive + +SHAKE256.LabeledDerive is used by DeriveKeyPair, and is part of the single-stage +KDF specified across [draft-ietf-hpke-hpke-02][] and [draft-ietf-hpke-pq-03][], +but is reproduced below for convenience. + +``` +def SHAKE256.LabeledDerive(ikm, label, context, L): + suite_id = concat("KEM", I2OSP(kem_id, 2)) + prefixed_label = I2OSP(len(label), 2) || label + labeled_ikm = ikm || "HPKE-v1" || suite_id || prefixed_label || I2OSP(L, 2) || context + return SHAKE256(labeled_ikm, L) +``` + +I2OSP is defined in [RFC 8017][], and `kem_id` is the KEM identifier. + +[draft-ietf-hpke-hpke-02]: https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-02 +[draft-ietf-hpke-pq-03]: https://datatracker.ietf.org/doc/html/draft-ietf-hpke-pq-03 +[draft-irtf-cfrg-hybrid-kems-07]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hybrid-kems-07 +[draft-irtf-cfrg-concrete-hybrid-kems-02]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-concrete-hybrid-kems-02 +[RFC 7748]: https://rfc-editor.org/rfc/rfc7748.html +[RFC 7748, Section 4.1]: https://rfc-editor.org/rfc/rfc7748.html#section-4.1 +[RFC 7748, Section 6.1]: https://rfc-editor.org/rfc/rfc7748.html#section-6.1 +[RFC 8017]: https://datatracker.ietf.org/doc/html/rfc8017 +[FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202 +[FIPS 203]: https://doi.org/10.6028/NIST.FIPS.203 +[SP800-186]: https://doi.org/10.6028/NIST.SP.800-186 +[SEC 1, Version 2.0]: https://www.secg.org/sec1-v2.pdf diff --git a/hpke.go b/hpke.go new file mode 100644 index 0000000..ceca287 --- /dev/null +++ b/hpke.go @@ -0,0 +1,270 @@ +// Copyright 2024 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 implements Hybrid Public Key Encryption (HPKE) as defined in +// [RFC 9180]. +// +// [RFC 9180]: https://www.rfc-editor.org/rfc/rfc9180.html +package hpke + +import ( + "crypto/cipher" + "errors" + + "sources.truenas.cloud/code/hpke/internal/byteorder" +) + +type context struct { + suiteID []byte + + export func(string, uint16) ([]byte, error) + + aead cipher.AEAD + baseNonce []byte + // seqNum starts at zero and is incremented for each Seal/Open call. + // 64 bits are enough not to overflow for 500 years at 1ns per operation. + seqNum uint64 +} + +// Sender is a sending HPKE context. It is instantiated with a specific KEM +// encapsulation key (i.e. the public key), and it is stateful, incrementing the +// nonce counter for each [Sender.Seal] call. +type Sender struct { + *context +} + +// Recipient is a receiving HPKE context. It is instantiated with a specific KEM +// decapsulation key (i.e. the secret key), and it is stateful, incrementing the +// nonce counter for each successful [Recipient.Open] call. +type Recipient struct { + *context +} + +func newContext(sharedSecret []byte, kemID uint16, kdf KDF, aead AEAD, info []byte) (*context, error) { + sid := suiteID(kemID, kdf.ID(), aead.ID()) + + if kdf.oneStage() { + secrets := make([]byte, 0, 2+2+len(sharedSecret)) + secrets = byteorder.BEAppendUint16(secrets, 0) // empty psk + secrets = byteorder.BEAppendUint16(secrets, uint16(len(sharedSecret))) + secrets = append(secrets, sharedSecret...) + + ksContext := make([]byte, 0, 1+2+2+len(info)) + ksContext = append(ksContext, 0) // mode 0 + ksContext = byteorder.BEAppendUint16(ksContext, 0) // empty psk_id + ksContext = byteorder.BEAppendUint16(ksContext, uint16(len(info))) + ksContext = append(ksContext, info...) + + secret, err := kdf.labeledDerive(sid, secrets, "secret", ksContext, + uint16(aead.keySize()+aead.nonceSize()+kdf.size())) + if err != nil { + return nil, err + } + key := secret[:aead.keySize()] + baseNonce := secret[aead.keySize() : aead.keySize()+aead.nonceSize()] + expSecret := secret[aead.keySize()+aead.nonceSize():] + + a, err := aead.aead(key) + if err != nil { + return nil, err + } + export := func(exporterContext string, length uint16) ([]byte, error) { + return kdf.labeledDerive(sid, expSecret, "sec", []byte(exporterContext), length) + } + + return &context{ + aead: a, + suiteID: sid, + export: export, + baseNonce: baseNonce, + }, nil + } + + pskIDHash, err := kdf.labeledExtract(sid, nil, "psk_id_hash", nil) + if err != nil { + return nil, err + } + infoHash, err := kdf.labeledExtract(sid, nil, "info_hash", info) + if err != nil { + return nil, err + } + ksContext := append([]byte{0}, pskIDHash...) + ksContext = append(ksContext, infoHash...) + + secret, err := kdf.labeledExtract(sid, sharedSecret, "secret", nil) + if err != nil { + return nil, err + } + key, err := kdf.labeledExpand(sid, secret, "key", ksContext, uint16(aead.keySize())) + if err != nil { + return nil, err + } + a, err := aead.aead(key) + if err != nil { + return nil, err + } + baseNonce, err := kdf.labeledExpand(sid, secret, "base_nonce", ksContext, uint16(aead.nonceSize())) + if err != nil { + return nil, err + } + expSecret, err := kdf.labeledExpand(sid, secret, "exp", ksContext, uint16(kdf.size())) + if err != nil { + return nil, err + } + export := func(exporterContext string, length uint16) ([]byte, error) { + return kdf.labeledExpand(sid, expSecret, "sec", []byte(exporterContext), length) + } + + return &context{ + aead: a, + suiteID: sid, + export: export, + baseNonce: baseNonce, + }, nil +} + +// NewSender returns a sending HPKE context for the provided KEM encapsulation +// key (i.e. the public key), and using the ciphersuite defined by the +// combination of KEM, KDF, and AEAD. +// +// The info parameter is additional public information that must match between +// sender and recipient. +// +// The returned enc ciphertext can be used to instantiate a matching receiving +// HPKE context with the corresponding KEM decapsulation key. +func NewSender(pk PublicKey, kdf KDF, aead AEAD, info []byte) (enc []byte, s *Sender, err error) { + return NewSenderWithTestingRandomness(pk, nil, kdf, aead, info) +} + +// NewSenderWithTestingRandomness is like NewSender, but uses the provided +// testingRandomness for deterministic KEM encapsulation. This is only intended +// for use in tests with known-answer test vectors. +func NewSenderWithTestingRandomness(pk PublicKey, testingRandomness []byte, kdf KDF, aead AEAD, info []byte) (enc []byte, s *Sender, err error) { + sharedSecret, encapsulatedKey, err := pk.encap(testingRandomness) + if err != nil { + return nil, nil, err + } + context, err := newContext(sharedSecret, pk.KEM().ID(), kdf, aead, info) + if err != nil { + return nil, nil, err + } + return encapsulatedKey, &Sender{context}, nil +} + +// NewRecipient returns a receiving HPKE context for the provided KEM +// decapsulation key (i.e. the secret key), and using the ciphersuite defined by +// the combination of KEM, KDF, and AEAD. +// +// The enc parameter must have been produced by a matching sending HPKE context +// with the corresponding KEM encapsulation key. The info parameter is +// additional public information that must match between sender and recipient. +func NewRecipient(enc []byte, k PrivateKey, kdf KDF, aead AEAD, info []byte) (*Recipient, error) { + sharedSecret, err := k.decap(enc) + if err != nil { + return nil, err + } + context, err := newContext(sharedSecret, k.KEM().ID(), kdf, aead, info) + if err != nil { + return nil, err + } + return &Recipient{context}, nil +} + +// Seal encrypts the provided plaintext, optionally binding to the additional +// public data aad. +// +// Seal uses incrementing counters for each call, and Open on the receiving side +// must be called in the same order as Seal. +func (s *Sender) Seal(aad, plaintext []byte) ([]byte, error) { + if s.aead == nil { + return nil, errors.New("export-only instantiation") + } + ciphertext := s.aead.Seal(nil, s.nextNonce(), plaintext, aad) + s.seqNum++ + return ciphertext, nil +} + +// Seal instantiates a single-use HPKE sending HPKE context like [NewSender], +// and then encrypts the provided plaintext like [Sender.Seal] (with no aad). +// Seal returns the concatenation of the encapsulated key and the ciphertext. +func Seal(pk PublicKey, kdf KDF, aead AEAD, info, plaintext []byte) ([]byte, error) { + enc, s, err := NewSender(pk, kdf, aead, info) + if err != nil { + return nil, err + } + ct, err := s.Seal(nil, plaintext) + if err != nil { + return nil, err + } + return append(enc, ct...), nil +} + +// Export produces a secret value derived from the shared key between sender and +// recipient. length must be at most 65,535. +func (s *Sender) Export(exporterContext string, length int) ([]byte, error) { + if length < 0 || length > 0xFFFF { + return nil, errors.New("invalid length") + } + return s.export(exporterContext, uint16(length)) +} + +// Open decrypts the provided ciphertext, optionally binding to the additional +// public data aad, or returns an error if decryption fails. +// +// Open uses incrementing counters for each successful call, and must be called +// in the same order as Seal on the sending side. +func (r *Recipient) Open(aad, ciphertext []byte) ([]byte, error) { + if r.aead == nil { + return nil, errors.New("export-only instantiation") + } + plaintext, err := r.aead.Open(nil, r.nextNonce(), ciphertext, aad) + if err != nil { + return nil, err + } + r.seqNum++ + return plaintext, nil +} + +// Open instantiates a single-use HPKE receiving HPKE context like [NewRecipient], +// and then decrypts the provided ciphertext like [Recipient.Open] (with no aad). +// ciphertext must be the concatenation of the encapsulated key and the actual ciphertext. +func Open(k PrivateKey, kdf KDF, aead AEAD, info, ciphertext []byte) ([]byte, error) { + encSize := k.KEM().encSize() + if len(ciphertext) < encSize { + return nil, errors.New("ciphertext too short") + } + enc, ciphertext := ciphertext[:encSize], ciphertext[encSize:] + r, err := NewRecipient(enc, k, kdf, aead, info) + if err != nil { + return nil, err + } + return r.Open(nil, ciphertext) +} + +// Export produces a secret value derived from the shared key between sender and +// recipient. length must be at most 65,535. +func (r *Recipient) Export(exporterContext string, length int) ([]byte, error) { + if length < 0 || length > 0xFFFF { + return nil, errors.New("invalid length") + } + return r.export(exporterContext, uint16(length)) +} + +func (ctx *context) nextNonce() []byte { + nonce := make([]byte, ctx.aead.NonceSize()) + byteorder.BEPutUint64(nonce[len(nonce)-8:], ctx.seqNum) + for i := range ctx.baseNonce { + nonce[i] ^= ctx.baseNonce[i] + } + return nonce +} + +func suiteID(kemID, kdfID, aeadID uint16) []byte { + suiteID := make([]byte, 0, 4+2+2+2) + suiteID = append(suiteID, []byte("HPKE")...) + suiteID = byteorder.BEAppendUint16(suiteID, kemID) + suiteID = byteorder.BEAppendUint16(suiteID, kdfID) + suiteID = byteorder.BEAppendUint16(suiteID, aeadID) + return suiteID +} diff --git a/hpke_test.go b/hpke_test.go new file mode 100644 index 0000000..e5e48ed --- /dev/null +++ b/hpke_test.go @@ -0,0 +1,416 @@ +// Copyright 2024 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 ( + "bytes" + "crypto/ecdh" + "crypto/sha3" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "os" + "testing" +) + +func Example() { + // In this example, we use MLKEM768-X25519 as the KEM, HKDF-SHA256 as the + // KDF, and AES-256-GCM as the AEAD to encrypt a single message from a + // sender to a recipient using the one-shot API. + + kem, kdf, aead := MLKEM768X25519(), HKDFSHA256(), AES256GCM() + + // Recipient side + var ( + recipientPrivateKey PrivateKey + publicKeyBytes []byte + ) + { + k, err := kem.GenerateKey() + if err != nil { + panic(err) + } + recipientPrivateKey = k + publicKeyBytes = k.PublicKey().Bytes() + } + + // Sender side + var ciphertext []byte + { + publicKey, err := kem.NewPublicKey(publicKeyBytes) + if err != nil { + panic(err) + } + + message := []byte("|-()-|") + ct, err := Seal(publicKey, kdf, aead, []byte("example"), message) + if err != nil { + panic(err) + } + + ciphertext = ct + } + + // Recipient side + { + plaintext, err := Open(recipientPrivateKey, kdf, aead, []byte("example"), ciphertext) + if err != nil { + panic(err) + } + fmt.Printf("Decrypted message: %s\n", plaintext) + } + + // Output: + // Decrypted message: |-()-| +} + +func mustDecodeHex(t *testing.T, in string) []byte { + t.Helper() + b, err := hex.DecodeString(in) + if err != nil { + t.Fatal(err) + } + return b +} + +func TestVectors(t *testing.T) { + t.Run("rfc9180", func(t *testing.T) { + testVectors(t, "rfc9180") + }) + t.Run("hpke-pq", func(t *testing.T) { + testVectors(t, "hpke-pq") + }) +} + +func testVectors(t *testing.T, name string) { + vectorsJSON, err := os.ReadFile("testdata/" + name + ".json") + if err != nil { + t.Fatal(err) + } + var vectors []struct { + Mode uint16 `json:"mode"` + KEM uint16 `json:"kem_id"` + KDF uint16 `json:"kdf_id"` + AEAD uint16 `json:"aead_id"` + Info string `json:"info"` + IkmE string `json:"ikmE"` + IkmR string `json:"ikmR"` + SkRm string `json:"skRm"` + PkRm string `json:"pkRm"` + Enc string `json:"enc"` + Encryptions []struct { + Aad string `json:"aad"` + Ct string `json:"ct"` + Nonce string `json:"nonce"` + Pt string `json:"pt"` + } `json:"encryptions"` + Exports []struct { + Context string `json:"exporter_context"` + L int `json:"L"` + Value string `json:"exported_value"` + } `json:"exports"` + + // Instead of checking in a very large rfc9180.json, we computed + // alternative accumulated values. + AccEncryptions string `json:"encryptions_accumulated"` + AccExports string `json:"exports_accumulated"` + } + if err := json.Unmarshal(vectorsJSON, &vectors); err != nil { + t.Fatal(err) + } + + for _, vector := range vectors { + name := fmt.Sprintf("mode %04x kem %04x kdf %04x aead %04x", + vector.Mode, vector.KEM, vector.KDF, vector.AEAD) + t.Run(name, func(t *testing.T) { + if vector.Mode != 0 { + t.Skip("only mode 0 (base) is supported") + } + if vector.KEM == 0x0021 { + t.Skip("KEM 0x0021 (DHKEM(X448)) not supported") + } + if vector.KEM == 0x0040 { + t.Skip("KEM 0x0040 (ML-KEM-512) not supported") + } + if vector.KDF == 0x0012 || vector.KDF == 0x0013 { + t.Skipf("TurboSHAKE KDF not supported") + } + + kdf, err := NewKDF(vector.KDF) + if err != nil { + t.Fatal(err) + } + if kdf.ID() != vector.KDF { + t.Errorf("unexpected KDF ID: got %04x, want %04x", kdf.ID(), vector.KDF) + } + + aead, err := NewAEAD(vector.AEAD) + if err != nil { + t.Fatal(err) + } + if aead.ID() != vector.AEAD { + t.Errorf("unexpected AEAD ID: got %04x, want %04x", aead.ID(), vector.AEAD) + } + + kem, err := NewKEM(vector.KEM) + if err != nil { + t.Fatal(err) + } + if kem.ID() != vector.KEM { + t.Errorf("unexpected KEM ID: got %04x, want %04x", kem.ID(), vector.KEM) + } + + pubKeyBytes := mustDecodeHex(t, vector.PkRm) + kemSender, err := kem.NewPublicKey(pubKeyBytes) + if err != nil { + t.Fatal(err) + } + if kemSender.KEM() != kem { + t.Errorf("unexpected KEM from sender: got %04x, want %04x", kemSender.KEM().ID(), kem.ID()) + } + if !bytes.Equal(kemSender.Bytes(), pubKeyBytes) { + t.Errorf("unexpected KEM bytes: got %x, want %x", kemSender.Bytes(), pubKeyBytes) + } + + ikmE := mustDecodeHex(t, vector.IkmE) + info := mustDecodeHex(t, vector.Info) + encap, sender, err := NewSenderWithTestingRandomness(kemSender, ikmE, kdf, aead, info) + if err != nil { + t.Fatal(err) + } + if len(encap) != kem.encSize() { + t.Errorf("unexpected encapsulated key size: got %d, want %d", len(encap), kem.encSize()) + } + + expectedEncap := mustDecodeHex(t, vector.Enc) + if !bytes.Equal(encap, expectedEncap) { + t.Errorf("unexpected encapsulated key, got: %x, want %x", encap, expectedEncap) + } + + privKeyBytes := mustDecodeHex(t, vector.SkRm) + kemRecipient, err := kem.NewPrivateKey(privKeyBytes) + if err != nil { + t.Fatal(err) + } + if kemRecipient.KEM() != kem { + t.Errorf("unexpected KEM from recipient: got %04x, want %04x", kemRecipient.KEM().ID(), kem.ID()) + } + kemRecipientBytes, err := kemRecipient.Bytes() + if err != nil { + t.Fatal(err) + } + // X25519 serialized keys must be clamped, so the bytes might not match. + if !bytes.Equal(kemRecipientBytes, privKeyBytes) && vector.KEM != DHKEM(ecdh.X25519()).ID() { + t.Errorf("unexpected KEM bytes: got %x, want %x", kemRecipientBytes, privKeyBytes) + } + if vector.KEM == DHKEM(ecdh.X25519()).ID() { + kem2, err := kem.NewPrivateKey(kemRecipientBytes) + if err != nil { + t.Fatal(err) + } + kemRecipientBytes2, err := kem2.Bytes() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(kemRecipientBytes2, kemRecipientBytes) { + t.Errorf("X25519 re-serialized key differs: got %x, want %x", kemRecipientBytes2, kemRecipientBytes) + } + if !bytes.Equal(kem2.PublicKey().Bytes(), pubKeyBytes) { + t.Errorf("X25519 re-derived public key differs: got %x, want %x", kem2.PublicKey().Bytes(), pubKeyBytes) + } + } + if !bytes.Equal(kemRecipient.PublicKey().Bytes(), pubKeyBytes) { + t.Errorf("unexpected KEM sender bytes: got %x, want %x", kemRecipient.PublicKey().Bytes(), pubKeyBytes) + } + + ikm := mustDecodeHex(t, vector.IkmR) + derivRecipient, err := kem.DeriveKeyPair(ikm) + if err != nil { + t.Fatal(err) + } + derivRecipientBytes, err := derivRecipient.Bytes() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(derivRecipientBytes, privKeyBytes) && vector.KEM != DHKEM(ecdh.X25519()).ID() { + t.Errorf("unexpected KEM bytes from seed: got %x, want %x", derivRecipientBytes, privKeyBytes) + } + if !bytes.Equal(derivRecipient.PublicKey().Bytes(), pubKeyBytes) { + t.Errorf("unexpected KEM sender bytes from seed: got %x, want %x", derivRecipient.PublicKey().Bytes(), pubKeyBytes) + } + + recipient, err := NewRecipient(encap, kemRecipient, kdf, aead, info) + if err != nil { + t.Fatal(err) + } + + if aead != ExportOnly() && len(vector.AccEncryptions) != 0 { + source, sink := sha3.NewSHAKE128(), sha3.NewSHAKE128() + for range 1000 { + aad, plaintext := drawRandomInput(t, source), drawRandomInput(t, source) + ciphertext, err := sender.Seal(aad, plaintext) + if err != nil { + t.Fatal(err) + } + sink.Write(ciphertext) + got, err := recipient.Open(aad, ciphertext) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, plaintext) { + t.Errorf("unexpected plaintext: got %x want %x", got, plaintext) + } + } + encryptions := make([]byte, 16) + sink.Read(encryptions) + expectedEncryptions := mustDecodeHex(t, vector.AccEncryptions) + if !bytes.Equal(encryptions, expectedEncryptions) { + t.Errorf("unexpected accumulated encryptions, got: %x, want %x", encryptions, expectedEncryptions) + } + } else if aead != ExportOnly() { + for _, enc := range vector.Encryptions { + aad := mustDecodeHex(t, enc.Aad) + plaintext := mustDecodeHex(t, enc.Pt) + expectedCiphertext := mustDecodeHex(t, enc.Ct) + + ciphertext, err := sender.Seal(aad, plaintext) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(ciphertext, expectedCiphertext) { + t.Errorf("unexpected ciphertext, got: %x, want %x", ciphertext, expectedCiphertext) + } + + got, err := recipient.Open(aad, ciphertext) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, plaintext) { + t.Errorf("unexpected plaintext: got %x want %x", got, plaintext) + } + } + } else { + if _, err := sender.Seal(nil, nil); err == nil { + t.Error("expected error from Seal with export-only AEAD") + } + if _, err := recipient.Open(nil, nil); err == nil { + t.Error("expected error from Open with export-only AEAD") + } + } + + if len(vector.AccExports) != 0 { + source, sink := sha3.NewSHAKE128(), sha3.NewSHAKE128() + for l := range 1000 { + context := string(drawRandomInput(t, source)) + value, err := sender.Export(context, l) + if err != nil { + t.Fatal(err) + } + sink.Write(value) + got, err := recipient.Export(context, l) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, value) { + t.Errorf("recipient: unexpected exported secret: got %x want %x", got, value) + } + } + exports := make([]byte, 16) + sink.Read(exports) + expectedExports := mustDecodeHex(t, vector.AccExports) + if !bytes.Equal(exports, expectedExports) { + t.Errorf("unexpected accumulated exports, got: %x, want %x", exports, expectedExports) + } + } else { + for _, exp := range vector.Exports { + context := string(mustDecodeHex(t, exp.Context)) + expectedValue := mustDecodeHex(t, exp.Value) + + value, err := sender.Export(context, exp.L) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(value, expectedValue) { + t.Errorf("unexpected exported value, got: %x, want %x", value, expectedValue) + } + + got, err := recipient.Export(context, exp.L) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, value) { + t.Errorf("recipient: unexpected exported secret: got %x want %x", got, value) + } + } + } + }) + } +} + +func drawRandomInput(t *testing.T, r io.Reader) []byte { + t.Helper() + l := make([]byte, 1) + if _, err := r.Read(l); err != nil { + t.Fatal(err) + } + n := int(l[0]) + b := make([]byte, n) + if _, err := r.Read(b); err != nil { + t.Fatal(err) + } + return b +} + +func TestSingletons(t *testing.T) { + if HKDFSHA256() != HKDFSHA256() { + t.Error("HKDFSHA256() != HKDFSHA256()") + } + if HKDFSHA384() != HKDFSHA384() { + t.Error("HKDFSHA384() != HKDFSHA384()") + } + if HKDFSHA512() != HKDFSHA512() { + t.Error("HKDFSHA512() != HKDFSHA512()") + } + if AES128GCM() != AES128GCM() { + t.Error("AES128GCM() != AES128GCM()") + } + if AES256GCM() != AES256GCM() { + t.Error("AES256GCM() != AES256GCM()") + } + if ChaCha20Poly1305() != ChaCha20Poly1305() { + t.Error("ChaCha20Poly1305() != ChaCha20Poly1305()") + } + if ExportOnly() != ExportOnly() { + t.Error("ExportOnly() != ExportOnly()") + } + if DHKEM(ecdh.P256()) != DHKEM(ecdh.P256()) { + t.Error("DHKEM(P-256) != DHKEM(P-256)") + } + if DHKEM(ecdh.P384()) != DHKEM(ecdh.P384()) { + t.Error("DHKEM(P-384) != DHKEM(P-384)") + } + if DHKEM(ecdh.P521()) != DHKEM(ecdh.P521()) { + t.Error("DHKEM(P-521) != DHKEM(P-521)") + } + if DHKEM(ecdh.X25519()) != DHKEM(ecdh.X25519()) { + t.Error("DHKEM(X25519) != DHKEM(X25519)") + } + if MLKEM768() != MLKEM768() { + t.Error("MLKEM768() != MLKEM768()") + } + if MLKEM1024() != MLKEM1024() { + t.Error("MLKEM1024() != MLKEM1024()") + } + if MLKEM768X25519() != MLKEM768X25519() { + t.Error("MLKEM768X25519() != MLKEM768X25519()") + } + if MLKEM768P256() != MLKEM768P256() { + t.Error("MLKEM768P256() != MLKEM768P256()") + } + if MLKEM1024P384() != MLKEM1024P384() { + t.Error("MLKEM1024P384() != MLKEM1024P384()") + } +} diff --git a/internal/byteorder/byteorder.go b/internal/byteorder/byteorder.go new file mode 100644 index 0000000..01500a8 --- /dev/null +++ b/internal/byteorder/byteorder.go @@ -0,0 +1,149 @@ +// Copyright 2024 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 byteorder provides functions for decoding and encoding +// little and big endian integer types from/to byte slices. +package byteorder + +func LEUint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[0]) | uint16(b[1])<<8 +} + +func LEPutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) +} + +func LEAppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v), + byte(v>>8), + ) +} + +func LEUint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func LEPutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) +} + +func LEAppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + ) +} + +func LEUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func LEPutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) + b[4] = byte(v >> 32) + b[5] = byte(v >> 40) + b[6] = byte(v >> 48) + b[7] = byte(v >> 56) +} + +func LEAppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56), + ) +} + +func BEUint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[1]) | uint16(b[0])<<8 +} + +func BEPutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 8) + b[1] = byte(v) +} + +func BEAppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v>>8), + byte(v), + ) +} + +func BEUint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 +} + +func BEPutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 24) + b[1] = byte(v >> 16) + b[2] = byte(v >> 8) + b[3] = byte(v) +} + +func BEAppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v>>24), + byte(v>>16), + byte(v>>8), + byte(v), + ) +} + +func BEUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +func BEPutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) + b[1] = byte(v >> 48) + b[2] = byte(v >> 40) + b[3] = byte(v >> 32) + b[4] = byte(v >> 24) + b[5] = byte(v >> 16) + b[6] = byte(v >> 8) + b[7] = byte(v) +} + +func BEAppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v>>56), + byte(v>>48), + byte(v>>40), + byte(v>>32), + byte(v>>24), + byte(v>>16), + byte(v>>8), + byte(v), + ) +} diff --git a/internal/mlkemtest/mlkemtest_fips140v1.0.go b/internal/mlkemtest/mlkemtest_fips140v1.0.go new file mode 100644 index 0000000..0a4a5f6 --- /dev/null +++ b/internal/mlkemtest/mlkemtest_fips140v1.0.go @@ -0,0 +1,44 @@ +//go:build !go1.26 && fips140v1.0 + +package mlkemtest + +import ( + "crypto/mlkem" + "errors" + "unsafe" +) + +// Reach ungracefully into the internals of crypto/internal/fips140/mlkem to +// perform derandomized encapsulation, which will be exposed in Go 1.26. + +func Encapsulate768(ek *mlkem.EncapsulationKey768, rand []byte) (sharedKey, ciphertext []byte, err error) { + if len(rand) != 32 { + return nil, nil, errors.New("invalid ML-KEM-768 randomness size") + } + key := (*mlkem768EncapsulationKey)(unsafe.Pointer(ek)) + sharedKey, ciphertext = mlkem768EncapsulateInternal(key.key, (*[32]byte)(rand)) + return sharedKey, ciphertext, nil +} + +type mlkem768EncapsulationKey struct { + key unsafe.Pointer // *crypto/internal/fips140/v1.0.0-c2097c7c/mlkem.EncapsulationKey768 +} + +//go:linkname mlkem768EncapsulateInternal crypto/internal/fips140/v1.0.0-c2097c7c/mlkem.(*EncapsulationKey768).EncapsulateInternal +func mlkem768EncapsulateInternal(ek unsafe.Pointer, m *[32]byte) (sharedKey, ciphertext []byte) + +func Encapsulate1024(ek *mlkem.EncapsulationKey1024, rand []byte) (sharedKey, ciphertext []byte, err error) { + if len(rand) != 32 { + return nil, nil, errors.New("invalid ML-KEM-1024 randomness size") + } + key := (*mlkem1024EncapsulationKey)(unsafe.Pointer(ek)) + sharedKey, ciphertext = mlkem1024EncapsulateInternal(key.key, (*[32]byte)(rand)) + return sharedKey, ciphertext, nil +} + +type mlkem1024EncapsulationKey struct { + key unsafe.Pointer // *crypto/internal/fips140/v1.0.0-c2097c7c/mlkem.EncapsulationKey1024 +} + +//go:linkname mlkem1024EncapsulateInternal crypto/internal/fips140/v1.0.0-c2097c7c/mlkem.(*EncapsulationKey1024).EncapsulateInternal +func mlkem1024EncapsulateInternal(ek unsafe.Pointer, m *[32]byte) (sharedKey, ciphertext []byte) diff --git a/internal/mlkemtest/mlkemtest_go1.26.go b/internal/mlkemtest/mlkemtest_go1.26.go new file mode 100644 index 0000000..18805c4 --- /dev/null +++ b/internal/mlkemtest/mlkemtest_go1.26.go @@ -0,0 +1,16 @@ +//go:build go1.26 + +package mlkemtest + +import ( + "crypto/mlkem" + "crypto/mlkem/mlkemtest" +) + +func Encapsulate768(ek *mlkem.EncapsulationKey768, rand []byte) (sharedKey, ciphertext []byte, err error) { + return mlkemtest.Encapsulate768(ek, rand) +} + +func Encapsulate1024(ek *mlkem.EncapsulationKey1024, rand []byte) (sharedKey, ciphertext []byte, err error) { + return mlkemtest.Encapsulate1024(ek, rand) +} diff --git a/kdf.go b/kdf.go new file mode 100644 index 0000000..04dc68b --- /dev/null +++ b/kdf.go @@ -0,0 +1,156 @@ +// 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/hkdf" + "crypto/sha256" + "crypto/sha3" + "crypto/sha512" + "errors" + "fmt" + "hash" + + "sources.truenas.cloud/code/hpke/internal/byteorder" +) + +// The KDF is one of the three components of an HPKE ciphersuite, implementing +// key derivation. +type KDF interface { + ID() uint16 + oneStage() bool + size() int // Nh + labeledDerive(suiteID, inputKey []byte, label string, context []byte, length uint16) ([]byte, error) + labeledExtract(suiteID, salt []byte, label string, inputKey []byte) ([]byte, error) + labeledExpand(suiteID, randomKey []byte, label string, info []byte, length uint16) ([]byte, error) +} + +// NewKDF returns the KDF implementation for the given KDF ID. +// +// Applications are encouraged to use specific implementations like [HKDFSHA256] +// instead, unless runtime agility is required. +func NewKDF(id uint16) (KDF, error) { + switch id { + case 0x0001: // HKDF-SHA256 + return HKDFSHA256(), nil + case 0x0002: // HKDF-SHA384 + return HKDFSHA384(), nil + case 0x0003: // HKDF-SHA512 + return HKDFSHA512(), nil + case 0x0010: // SHAKE128 + return SHAKE128(), nil + case 0x0011: // SHAKE256 + return SHAKE256(), nil + default: + return nil, fmt.Errorf("unsupported KDF %04x", id) + } +} + +// HKDFSHA256 returns an HKDF-SHA256 KDF implementation. +func HKDFSHA256() KDF { return hkdfSHA256 } + +// HKDFSHA384 returns an HKDF-SHA384 KDF implementation. +func HKDFSHA384() KDF { return hkdfSHA384 } + +// HKDFSHA512 returns an HKDF-SHA512 KDF implementation. +func HKDFSHA512() KDF { return hkdfSHA512 } + +type hkdfKDF struct { + hash func() hash.Hash + id uint16 + nH int +} + +var hkdfSHA256 = &hkdfKDF{hash: sha256.New, id: 0x0001, nH: sha256.Size} +var hkdfSHA384 = &hkdfKDF{hash: sha512.New384, id: 0x0002, nH: sha512.Size384} +var hkdfSHA512 = &hkdfKDF{hash: sha512.New, id: 0x0003, nH: sha512.Size} + +func (kdf *hkdfKDF) ID() uint16 { + return kdf.id +} + +func (kdf *hkdfKDF) size() int { + return kdf.nH +} + +func (kdf *hkdfKDF) oneStage() bool { + return false +} + +func (kdf *hkdfKDF) labeledDerive(_, _ []byte, _ string, _ []byte, _ uint16) ([]byte, error) { + return nil, errors.New("hpke: internal error: labeledDerive called on two-stage KDF") +} + +func (kdf *hkdfKDF) labeledExtract(suiteID []byte, salt []byte, label string, inputKey []byte) ([]byte, error) { + labeledIKM := make([]byte, 0, 7+len(suiteID)+len(label)+len(inputKey)) + labeledIKM = append(labeledIKM, []byte("HPKE-v1")...) + labeledIKM = append(labeledIKM, suiteID...) + labeledIKM = append(labeledIKM, label...) + labeledIKM = append(labeledIKM, inputKey...) + return hkdf.Extract(kdf.hash, labeledIKM, salt) +} + +func (kdf *hkdfKDF) labeledExpand(suiteID []byte, randomKey []byte, label string, info []byte, length uint16) ([]byte, error) { + labeledInfo := make([]byte, 0, 2+7+len(suiteID)+len(label)+len(info)) + labeledInfo = byteorder.BEAppendUint16(labeledInfo, length) + labeledInfo = append(labeledInfo, []byte("HPKE-v1")...) + labeledInfo = append(labeledInfo, suiteID...) + labeledInfo = append(labeledInfo, label...) + labeledInfo = append(labeledInfo, info...) + return hkdf.Expand(kdf.hash, randomKey, string(labeledInfo), int(length)) +} + +// SHAKE128 returns a SHAKE128 KDF implementation. +func SHAKE128() KDF { + return shake128KDF +} + +// SHAKE256 returns a SHAKE256 KDF implementation. +func SHAKE256() KDF { + return shake256KDF +} + +type shakeKDF struct { + hash func() *sha3.SHAKE + id uint16 + nH int +} + +var shake128KDF = &shakeKDF{hash: sha3.NewSHAKE128, id: 0x0010, nH: 32} +var shake256KDF = &shakeKDF{hash: sha3.NewSHAKE256, id: 0x0011, nH: 64} + +func (kdf *shakeKDF) ID() uint16 { + return kdf.id +} + +func (kdf *shakeKDF) size() int { + return kdf.nH +} + +func (kdf *shakeKDF) oneStage() bool { + return true +} + +func (kdf *shakeKDF) labeledDerive(suiteID, inputKey []byte, label string, context []byte, length uint16) ([]byte, error) { + H := kdf.hash() + H.Write(inputKey) + H.Write([]byte("HPKE-v1")) + H.Write(suiteID) + H.Write([]byte{byte(len(label) >> 8), byte(len(label))}) + H.Write([]byte(label)) + H.Write([]byte{byte(length >> 8), byte(length)}) + H.Write(context) + out := make([]byte, length) + H.Read(out) + return out, nil +} + +func (kdf *shakeKDF) labeledExtract(_, _ []byte, _ string, _ []byte) ([]byte, error) { + return nil, errors.New("hpke: internal error: labeledExtract called on one-stage KDF") +} + +func (kdf *shakeKDF) labeledExpand(_, _ []byte, _ string, _ []byte, _ uint16) ([]byte, error) { + return nil, errors.New("hpke: internal error: labeledExpand called on one-stage KDF") +} diff --git a/kem.go b/kem.go new file mode 100644 index 0000000..2985fdc --- /dev/null +++ b/kem.go @@ -0,0 +1,388 @@ +// 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/rand" + "errors" + + "sources.truenas.cloud/code/hpke/crypto/ecdh" + "sources.truenas.cloud/code/hpke/internal/byteorder" +) + +// A KEM is a Key Encapsulation Mechanism, one of the three components of an +// HPKE ciphersuite. +type KEM interface { + // ID returns the HPKE KEM identifier. + ID() uint16 + + // GenerateKey generates a new key pair. + GenerateKey() (PrivateKey, error) + + // NewPublicKey deserializes a public key from bytes. + // + // It implements DeserializePublicKey, as defined in RFC 9180. + NewPublicKey([]byte) (PublicKey, error) + + // NewPrivateKey deserializes a private key from bytes. + // + // It implements DeserializePrivateKey, as defined in RFC 9180. + NewPrivateKey([]byte) (PrivateKey, error) + + // DeriveKeyPair derives a key pair from the given input keying material. + // + // It implements DeriveKeyPair, as defined in RFC 9180. + DeriveKeyPair(ikm []byte) (PrivateKey, error) + + encSize() int +} + +// NewKEM returns the KEM implementation for the given KEM ID. +// +// Applications are encouraged to use specific implementations like [DHKEM] or +// [MLKEM768X25519] instead, unless runtime agility is required. +func NewKEM(id uint16) (KEM, error) { + switch id { + case 0x0010: // DHKEM(P-256, HKDF-SHA256) + return DHKEM(ecdh.P256()), nil + case 0x0011: // DHKEM(P-384, HKDF-SHA384) + return DHKEM(ecdh.P384()), nil + case 0x0012: // DHKEM(P-521, HKDF-SHA512) + return DHKEM(ecdh.P521()), nil + case 0x0020: // DHKEM(X25519, HKDF-SHA256) + return DHKEM(ecdh.X25519()), nil + case 0x0041: // ML-KEM-768 + return MLKEM768(), nil + case 0x0042: // ML-KEM-1024 + return MLKEM1024(), nil + case 0x647a: // MLKEM768-X25519 + return MLKEM768X25519(), nil + case 0x0050: // MLKEM768-P256 + return MLKEM768P256(), nil + case 0x0051: // MLKEM1024-P384 + return MLKEM1024P384(), nil + default: + return nil, errors.New("unsupported KEM") + } +} + +// A PublicKey is an instantiation of a KEM (one of the three components of an +// HPKE ciphersuite) with an encapsulation key (i.e. the public key). +// +// A PublicKey is usually obtained from a method of the corresponding [KEM] or +// [PrivateKey], such as [KEM.NewPublicKey] or [PrivateKey.PublicKey]. +type PublicKey interface { + // KEM returns the instantiated KEM. + KEM() KEM + + // Bytes returns the public key as the output of SerializePublicKey. + Bytes() []byte + + // encap performs KEM encapsulation, producing a shared secret and + // ciphertext (i.e. the encapsulated key). The testingRandomness parameter, + // if not nil, is used to perform deterministic encapsulation for testing. + encap(testingRandomness []byte) (sharedSecret, enc []byte, err error) +} + +// A PrivateKey is an instantiation of a KEM (one of the three components of +// an HPKE ciphersuite) with a decapsulation key (i.e. the secret key). +// +// A PrivateKey is usually obtained from a method of the corresponding [KEM], +// such as [KEM.GenerateKey] or [KEM.NewPrivateKey]. +type PrivateKey interface { + // KEM returns the instantiated KEM. + KEM() KEM + + // Bytes returns the private key as the output of SerializePrivateKey, as + // defined in RFC 9180. + // + // Note that for X25519 this might not match the input to NewPrivateKey. + // This is a requirement of RFC 9180, Section 7.1.2. + Bytes() ([]byte, error) + + // PublicKey returns the corresponding PublicKey. + PublicKey() PublicKey + + decap(enc []byte) (sharedSecret []byte, err error) +} + +type dhKEM struct { + kdf KDF + id uint16 + curve ecdh.Curve + Nsecret uint16 + Nsk uint16 + Nenc int +} + +func (kem *dhKEM) extractAndExpand(dhKey, kemContext []byte) ([]byte, error) { + suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id) + eaePRK, err := kem.kdf.labeledExtract(suiteID, nil, "eae_prk", dhKey) + if err != nil { + return nil, err + } + return kem.kdf.labeledExpand(suiteID, eaePRK, "shared_secret", kemContext, kem.Nsecret) +} + +func (kem *dhKEM) ID() uint16 { + return kem.id +} + +func (kem *dhKEM) encSize() int { + return kem.Nenc +} + +var dhKEMP256 = &dhKEM{HKDFSHA256(), 0x0010, ecdh.P256(), 32, 32, 65} +var dhKEMP384 = &dhKEM{HKDFSHA384(), 0x0011, ecdh.P384(), 48, 48, 97} +var dhKEMP521 = &dhKEM{HKDFSHA512(), 0x0012, ecdh.P521(), 64, 66, 133} +var dhKEMX25519 = &dhKEM{HKDFSHA256(), 0x0020, ecdh.X25519(), 32, 32, 32} + +// DHKEM returns a KEM implementing one of +// +// - DHKEM(P-256, HKDF-SHA256) +// - DHKEM(P-384, HKDF-SHA384) +// - DHKEM(P-521, HKDF-SHA512) +// - DHKEM(X25519, HKDF-SHA256) +// +// depending on curve. +func DHKEM(curve ecdh.Curve) KEM { + switch curve { + case ecdh.P256(): + return dhKEMP256 + case ecdh.P384(): + return dhKEMP384 + case ecdh.P521(): + return dhKEMP521 + case ecdh.X25519(): + return dhKEMX25519 + default: + // The set of ecdh.Curve implementations is closed, because the + // interface has unexported methods. Therefore, this default case is + // only hit if a new curve is added that DHKEM doesn't support. + return unsupportedCurveKEM{} + } +} + +type unsupportedCurveKEM struct{} + +func (unsupportedCurveKEM) ID() uint16 { + return 0 +} +func (unsupportedCurveKEM) GenerateKey() (PrivateKey, error) { + return nil, errors.New("unsupported curve") +} +func (unsupportedCurveKEM) NewPublicKey([]byte) (PublicKey, error) { + return nil, errors.New("unsupported curve") +} +func (unsupportedCurveKEM) NewPrivateKey([]byte) (PrivateKey, error) { + return nil, errors.New("unsupported curve") +} +func (unsupportedCurveKEM) DeriveKeyPair([]byte) (PrivateKey, error) { + return nil, errors.New("unsupported curve") +} +func (unsupportedCurveKEM) encSize() int { + return 0 +} + +type dhKEMPublicKey struct { + kem *dhKEM + pub *ecdh.PublicKey +} + +// NewDHKEMPublicKey returns a PublicKey implementing +// +// - DHKEM(P-256, HKDF-SHA256) +// - DHKEM(P-384, HKDF-SHA384) +// - DHKEM(P-521, HKDF-SHA512) +// - DHKEM(X25519, HKDF-SHA256) +// +// depending on the underlying curve of pub ([ecdh.X25519], [ecdh.P256], +// [ecdh.P384], or [ecdh.P521]). +// +// This function is meant for applications that already have an instantiated +// crypto/ecdh public key. Otherwise, applications should use the +// [KEM.NewPublicKey] method of [DHKEM]. +func NewDHKEMPublicKey(pub *ecdh.PublicKey) (PublicKey, error) { + kem, ok := DHKEM(pub.Curve()).(*dhKEM) + if !ok { + return nil, errors.New("unsupported curve") + } + return &dhKEMPublicKey{ + kem: kem, + pub: pub, + }, nil +} + +func (kem *dhKEM) NewPublicKey(data []byte) (PublicKey, error) { + pub, err := kem.curve.NewPublicKey(data) + if err != nil { + return nil, err + } + return NewDHKEMPublicKey(pub) +} + +func (pk *dhKEMPublicKey) KEM() KEM { + return pk.kem +} + +func (pk *dhKEMPublicKey) Bytes() []byte { + return pk.pub.Bytes() +} + +func (pk *dhKEMPublicKey) encap(testingRandomness []byte) (ss []byte, enc []byte, err error) { + var privEph ecdh.KeyExchanger + if testingRandomness == nil { + privEph, err = pk.pub.Curve().GenerateKey(rand.Reader) + if err != nil { + return nil, nil, err + } + } else { + r, err := pk.KEM().DeriveKeyPair(testingRandomness) + if err != nil { + return nil, nil, err + } + privEph = r.(*dhKEMPrivateKey).priv + } + dhVal, err := privEph.ECDH(pk.pub) + if err != nil { + return nil, nil, err + } + encPubEph := privEph.PublicKey().Bytes() + + encPubRecip := pk.pub.Bytes() + kemContext := append(encPubEph, encPubRecip...) + ss, err = pk.kem.extractAndExpand(dhVal, kemContext) + if err != nil { + return nil, nil, err + } + return ss, encPubEph, nil +} + +type dhKEMPrivateKey struct { + kem *dhKEM + priv ecdh.KeyExchanger +} + +// NewDHKEMPrivateKey returns a PrivateKey implementing +// +// - DHKEM(P-256, HKDF-SHA256) +// - DHKEM(P-384, HKDF-SHA384) +// - DHKEM(P-521, HKDF-SHA512) +// - DHKEM(X25519, HKDF-SHA256) +// +// depending on the underlying curve of priv ([ecdh.X25519], [ecdh.P256], +// [ecdh.P384], or [ecdh.P521]). +// +// This function is meant for applications that already have an instantiated +// crypto/ecdh private key, or another implementation of a [ecdh.KeyExchanger] +// (e.g. a hardware key). Otherwise, applications should use the +// [KEM.NewPrivateKey] method of [DHKEM]. +func NewDHKEMPrivateKey(priv ecdh.KeyExchanger) (PrivateKey, error) { + kem, ok := DHKEM(priv.Curve()).(*dhKEM) + if !ok { + return nil, errors.New("unsupported curve") + } + return &dhKEMPrivateKey{ + kem: kem, + priv: priv, + }, nil +} + +func (kem *dhKEM) GenerateKey() (PrivateKey, error) { + priv, err := kem.curve.GenerateKey(rand.Reader) + if err != nil { + return nil, err + } + return NewDHKEMPrivateKey(priv) +} + +func (kem *dhKEM) NewPrivateKey(ikm []byte) (PrivateKey, error) { + priv, err := kem.curve.NewPrivateKey(ikm) + if err != nil { + return nil, err + } + return NewDHKEMPrivateKey(priv) +} + +func (kem *dhKEM) DeriveKeyPair(ikm []byte) (PrivateKey, error) { + // DeriveKeyPair from RFC 9180 Section 7.1.3. + suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id) + prk, err := kem.kdf.labeledExtract(suiteID, nil, "dkp_prk", ikm) + if err != nil { + return nil, err + } + if kem == dhKEMX25519 { + s, err := kem.kdf.labeledExpand(suiteID, prk, "sk", nil, kem.Nsk) + if err != nil { + return nil, err + } + return kem.NewPrivateKey(s) + } + var counter uint8 + for counter < 4 { + s, err := kem.kdf.labeledExpand(suiteID, prk, "candidate", []byte{counter}, kem.Nsk) + if err != nil { + return nil, err + } + if kem == dhKEMP521 { + s[0] &= 0x01 + } + r, err := kem.NewPrivateKey(s) + if err != nil { + counter++ + continue + } + return r, nil + } + panic("chance of four rejections is < 2^-128") +} + +func (k *dhKEMPrivateKey) KEM() KEM { + return k.kem +} + +func (k *dhKEMPrivateKey) Bytes() ([]byte, error) { + // Bizarrely, RFC 9180, Section 7.1.2 says SerializePrivateKey MUST clamp + // the output, which I thought we all agreed to instead do as part of the DH + // function, letting private keys be random bytes. + // + // At the same time, it says DeserializePrivateKey MUST also clamp, implying + // that the input doesn't have to be clamped, so Bytes by spec doesn't + // necessarily match the NewPrivateKey input. + // + // I'm sure this will not lead to any unexpected behavior or interop issue. + priv, ok := k.priv.(*ecdh.PrivateKey) + if !ok { + return nil, errors.New("ecdh: private key does not support Bytes") + } + if k.kem == dhKEMX25519 { + b := priv.Bytes() + b[0] &= 248 + b[31] &= 127 + b[31] |= 64 + return b, nil + } + return priv.Bytes(), nil +} + +func (k *dhKEMPrivateKey) PublicKey() PublicKey { + return &dhKEMPublicKey{ + kem: k.kem, + pub: k.priv.PublicKey(), + } +} + +func (k *dhKEMPrivateKey) decap(encPubEph []byte) ([]byte, error) { + pubEph, err := k.priv.Curve().NewPublicKey(encPubEph) + if err != nil { + return nil, err + } + dhVal, err := k.priv.ECDH(pubEph) + if err != nil { + return nil, err + } + kemContext := append(encPubEph, k.priv.PublicKey().Bytes()...) + return k.kem.extractAndExpand(dhVal, kemContext) +} diff --git a/pq.go b/pq.go new file mode 100644 index 0000000..9ae814f --- /dev/null +++ b/pq.go @@ -0,0 +1,567 @@ +// 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 ( + "bytes" + "crypto/mlkem" + "crypto/rand" + "crypto/sha3" + "errors" + + "sources.truenas.cloud/code/hpke/crypto" + "sources.truenas.cloud/code/hpke/crypto/ecdh" + "sources.truenas.cloud/code/hpke/internal/byteorder" + "sources.truenas.cloud/code/hpke/internal/mlkemtest" +) + +var mlkem768X25519 = &hybridKEM{ + id: 0x647a, + label: /**/ `\./` + + /* */ `/^\`, + curve: ecdh.X25519(), + + curveSeedSize: 32, + curvePointSize: 32, + pqEncapsKeySize: mlkem.EncapsulationKeySize768, + pqCiphertextSize: mlkem.CiphertextSize768, + + pqNewPublicKey: func(data []byte) (crypto.Encapsulator, error) { + return mlkem.NewEncapsulationKey768(data) + }, + pqNewPrivateKey: func(data []byte) (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.NewDecapsulationKey768(data)) + }, +} + +// MLKEM768X25519 returns a KEM implementing MLKEM768-X25519 (a.k.a. X-Wing) +// from draft-ietf-hpke-pq. +func MLKEM768X25519() KEM { + return mlkem768X25519 +} + +var mlkem768P256 = &hybridKEM{ + id: 0x0050, + label: "MLKEM768-P256", + curve: ecdh.P256(), + + curveSeedSize: 32, + curvePointSize: 65, + pqEncapsKeySize: mlkem.EncapsulationKeySize768, + pqCiphertextSize: mlkem.CiphertextSize768, + + pqNewPublicKey: func(data []byte) (crypto.Encapsulator, error) { + return mlkem.NewEncapsulationKey768(data) + }, + pqNewPrivateKey: func(data []byte) (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.NewDecapsulationKey768(data)) + }, +} + +// MLKEM768P256 returns a KEM implementing MLKEM768-P256 from draft-ietf-hpke-pq. +func MLKEM768P256() KEM { + return mlkem768P256 +} + +var mlkem1024P384 = &hybridKEM{ + id: 0x0051, + label: "MLKEM1024-P384", + curve: ecdh.P384(), + + curveSeedSize: 48, + curvePointSize: 97, + pqEncapsKeySize: mlkem.EncapsulationKeySize1024, + pqCiphertextSize: mlkem.CiphertextSize1024, + + pqNewPublicKey: func(data []byte) (crypto.Encapsulator, error) { + return mlkem.NewEncapsulationKey1024(data) + }, + pqNewPrivateKey: func(data []byte) (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.NewDecapsulationKey1024(data)) + }, +} + +// MLKEM1024P384 returns a KEM implementing MLKEM1024-P384 from draft-ietf-hpke-pq. +func MLKEM1024P384() KEM { + return mlkem1024P384 +} + +type hybridKEM struct { + id uint16 + label string + curve ecdh.Curve + + curveSeedSize int + curvePointSize int + pqEncapsKeySize int + pqCiphertextSize int + + pqNewPublicKey func(data []byte) (crypto.Encapsulator, error) + pqNewPrivateKey func(data []byte) (crypto.Decapsulator, error) +} + +func (kem *hybridKEM) ID() uint16 { + return kem.id +} + +func (kem *hybridKEM) encSize() int { + return kem.pqCiphertextSize + kem.curvePointSize +} + +func (kem *hybridKEM) sharedSecret(ssPQ, ssT, ctT, ekT []byte) []byte { + h := sha3.New256() + h.Write(ssPQ) + h.Write(ssT) + h.Write(ctT) + h.Write(ekT) + h.Write([]byte(kem.label)) + return h.Sum(nil) +} + +type hybridPublicKey struct { + kem *hybridKEM + t *ecdh.PublicKey + pq crypto.Encapsulator +} + +// NewHybridPublicKey returns a PublicKey implementing one of +// +// - MLKEM768-X25519 (a.k.a. X-Wing) +// - MLKEM768-P256 +// - MLKEM1024-P384 +// +// from draft-ietf-hpke-pq, depending on the underlying curve of t +// ([ecdh.X25519], [ecdh.P256], or [ecdh.P384]) and the type of pq (either +// *[mlkem.EncapsulationKey768] or *[mlkem.EncapsulationKey1024]). +// +// This function is meant for applications that already have instantiated +// crypto/ecdh and crypto/mlkem public keys. Otherwise, applications should use +// the [KEM.NewPublicKey] method of e.g. [MLKEM768X25519]. +func NewHybridPublicKey(pq crypto.Encapsulator, t *ecdh.PublicKey) (PublicKey, error) { + switch t.Curve() { + case ecdh.X25519(): + if _, ok := pq.(*mlkem.EncapsulationKey768); !ok { + return nil, errors.New("invalid PQ KEM for X25519 hybrid") + } + return &hybridPublicKey{mlkem768X25519, t, pq}, nil + case ecdh.P256(): + if _, ok := pq.(*mlkem.EncapsulationKey768); !ok { + return nil, errors.New("invalid PQ KEM for P-256 hybrid") + } + return &hybridPublicKey{mlkem768P256, t, pq}, nil + case ecdh.P384(): + if _, ok := pq.(*mlkem.EncapsulationKey1024); !ok { + return nil, errors.New("invalid PQ KEM for P-384 hybrid") + } + return &hybridPublicKey{mlkem1024P384, t, pq}, nil + default: + return nil, errors.New("unsupported curve") + } +} + +func (kem *hybridKEM) NewPublicKey(data []byte) (PublicKey, error) { + if len(data) != kem.pqEncapsKeySize+kem.curvePointSize { + return nil, errors.New("invalid public key size") + } + pq, err := kem.pqNewPublicKey(data[:kem.pqEncapsKeySize]) + if err != nil { + return nil, err + } + k, err := kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:]) + if err != nil { + return nil, err + } + return NewHybridPublicKey(pq, k) +} + +func (pk *hybridPublicKey) KEM() KEM { + return pk.kem +} + +func (pk *hybridPublicKey) Bytes() []byte { + return append(pk.pq.Bytes(), pk.t.Bytes()...) +} + +func (pk *hybridPublicKey) encap(testingRandomness []byte) (ss []byte, enc []byte, err error) { + var ssPQ, ctPQ []byte + if testingRandomness == nil { + ssPQ, ctPQ = pk.pq.Encapsulate() + } else { + if len(testingRandomness) < 32 { + return nil, nil, errors.New("insufficient testing randomness") + } + switch ek := pk.pq.(type) { + case *mlkem.EncapsulationKey768: + ssPQ, ctPQ, err = mlkemtest.Encapsulate768(ek, testingRandomness[:32]) + case *mlkem.EncapsulationKey1024: + ssPQ, ctPQ, err = mlkemtest.Encapsulate1024(ek, testingRandomness[:32]) + default: + return nil, nil, errors.New("internal error: unsupported public key type") + } + if err != nil { + return nil, nil, err + } + testingRandomness = testingRandomness[32:] + } + + var skE ecdh.KeyExchanger + if testingRandomness == nil { + skE, err = pk.t.Curve().GenerateKey(rand.Reader) + if err != nil { + return nil, nil, err + } + } else { + for len(testingRandomness) >= pk.kem.curveSeedSize { + seedT := testingRandomness[:pk.kem.curveSeedSize] + testingRandomness = testingRandomness[pk.kem.curveSeedSize:] + skE, err = pk.t.Curve().NewPrivateKey(seedT) + if err != nil { + continue + } + break + } + } + ssT, err := skE.ECDH(pk.t) + if err != nil { + return nil, nil, err + } + ctT := skE.PublicKey().Bytes() + + ss = pk.kem.sharedSecret(ssPQ, ssT, ctT, pk.t.Bytes()) + enc = append(ctPQ, ctT...) + return ss, enc, nil +} + +type hybridPrivateKey struct { + kem *hybridKEM + seed []byte // can be nil + t ecdh.KeyExchanger + pq crypto.Decapsulator +} + +// NewHybridPrivateKey returns a PrivateKey implementing +// +// - MLKEM768-X25519 (a.k.a. X-Wing) +// - MLKEM768-P256 +// - MLKEM1024-P384 +// +// from draft-ietf-hpke-pq, depending on the underlying curve of t +// ([ecdh.X25519], [ecdh.P256], or [ecdh.P384]) and the type of pq.Encapsulator() +// (either *[mlkem.EncapsulationKey768] or *[mlkem.EncapsulationKey1024]). +// +// This function is meant for applications that already have instantiated +// crypto/ecdh and crypto/mlkem private keys, or another implementation of a +// [ecdh.KeyExchanger] and [crypto.Decapsulator] (e.g. a hardware key). +// Otherwise, applications should use the [KEM.NewPrivateKey] method of e.g. +// [MLKEM768X25519]. +func NewHybridPrivateKey(pq crypto.Decapsulator, t ecdh.KeyExchanger) (PrivateKey, error) { + return newHybridPrivateKey(pq, t, nil) +} + +func (kem *hybridKEM) GenerateKey() (PrivateKey, error) { + seed := make([]byte, 32) + rand.Read(seed) + return kem.NewPrivateKey(seed) +} + +func (kem *hybridKEM) NewPrivateKey(priv []byte) (PrivateKey, error) { + if len(priv) != 32 { + return nil, errors.New("hpke: invalid hybrid KEM secret length") + } + + s := sha3.NewSHAKE256() + s.Write(priv) + + seedPQ := make([]byte, mlkem.SeedSize) + s.Read(seedPQ) + pq, err := kem.pqNewPrivateKey(seedPQ) + if err != nil { + return nil, err + } + + seedT := make([]byte, kem.curveSeedSize) + for { + s.Read(seedT) + k, err := kem.curve.NewPrivateKey(seedT) + if err != nil { + continue + } + return newHybridPrivateKey(pq, k, priv) + } +} + +func newHybridPrivateKey(pq crypto.Decapsulator, t ecdh.KeyExchanger, seed []byte) (PrivateKey, error) { + switch t.Curve() { + case ecdh.X25519(): + if _, ok := pq.Encapsulator().(*mlkem.EncapsulationKey768); !ok { + return nil, errors.New("invalid PQ KEM for X25519 hybrid") + } + return &hybridPrivateKey{mlkem768X25519, bytes.Clone(seed), t, pq}, nil + case ecdh.P256(): + if _, ok := pq.Encapsulator().(*mlkem.EncapsulationKey768); !ok { + return nil, errors.New("invalid PQ KEM for P-256 hybrid") + } + return &hybridPrivateKey{mlkem768P256, bytes.Clone(seed), t, pq}, nil + case ecdh.P384(): + if _, ok := pq.Encapsulator().(*mlkem.EncapsulationKey1024); !ok { + return nil, errors.New("invalid PQ KEM for P-384 hybrid") + } + return &hybridPrivateKey{mlkem1024P384, bytes.Clone(seed), t, pq}, nil + default: + return nil, errors.New("unsupported curve") + } +} + +func (kem *hybridKEM) DeriveKeyPair(ikm []byte) (PrivateKey, error) { + suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id) + dk, err := SHAKE256().labeledDerive(suiteID, ikm, "DeriveKeyPair", nil, 32) + if err != nil { + return nil, err + } + return kem.NewPrivateKey(dk) +} + +func (k *hybridPrivateKey) KEM() KEM { + return k.kem +} + +func (k *hybridPrivateKey) Bytes() ([]byte, error) { + if k.seed == nil { + return nil, errors.New("private key seed not available") + } + return k.seed, nil +} + +func (k *hybridPrivateKey) PublicKey() PublicKey { + return &hybridPublicKey{ + kem: k.kem, + t: k.t.PublicKey(), + pq: k.pq.Encapsulator(), + } +} + +func (k *hybridPrivateKey) decap(enc []byte) ([]byte, error) { + if len(enc) != k.kem.pqCiphertextSize+k.kem.curvePointSize { + return nil, errors.New("invalid encapsulated key size") + } + ctPQ, ctT := enc[:k.kem.pqCiphertextSize], enc[k.kem.pqCiphertextSize:] + ssPQ, err := k.pq.Decapsulate(ctPQ) + if err != nil { + return nil, err + } + pub, err := k.t.Curve().NewPublicKey(ctT) + if err != nil { + return nil, err + } + ssT, err := k.t.ECDH(pub) + if err != nil { + return nil, err + } + ss := k.kem.sharedSecret(ssPQ, ssT, ctT, k.t.PublicKey().Bytes()) + return ss, nil +} + +var mlkem768 = &mlkemKEM{ + id: 0x0041, + ciphertextSize: mlkem.CiphertextSize768, + newPublicKey: func(data []byte) (crypto.Encapsulator, error) { + return mlkem.NewEncapsulationKey768(data) + }, + newPrivateKey: func(data []byte) (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.NewDecapsulationKey768(data)) + }, + generateKey: func() (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.GenerateKey768()) + }, +} + +// MLKEM768 returns a KEM implementing ML-KEM-768 from draft-ietf-hpke-pq. +func MLKEM768() KEM { + return mlkem768 +} + +var mlkem1024 = &mlkemKEM{ + id: 0x0042, + ciphertextSize: mlkem.CiphertextSize1024, + newPublicKey: func(data []byte) (crypto.Encapsulator, error) { + return mlkem.NewEncapsulationKey1024(data) + }, + newPrivateKey: func(data []byte) (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.NewDecapsulationKey1024(data)) + }, + generateKey: func() (crypto.Decapsulator, error) { + return wrapDecapsulator(mlkem.GenerateKey1024()) + }, +} + +// MLKEM1024 returns a KEM implementing ML-KEM-1024 from draft-ietf-hpke-pq. +func MLKEM1024() KEM { + return mlkem1024 +} + +type mlkemKEM struct { + id uint16 + ciphertextSize int + newPublicKey func(data []byte) (crypto.Encapsulator, error) + newPrivateKey func(data []byte) (crypto.Decapsulator, error) + generateKey func() (crypto.Decapsulator, error) +} + +func (kem *mlkemKEM) ID() uint16 { + return kem.id +} + +func (kem *mlkemKEM) encSize() int { + return kem.ciphertextSize +} + +type mlkemPublicKey struct { + kem *mlkemKEM + pq crypto.Encapsulator +} + +// NewMLKEMPublicKey returns a KEMPublicKey implementing +// +// - ML-KEM-768 +// - ML-KEM-1024 +// +// from draft-ietf-hpke-pq, depending on the type of pub +// (*[mlkem.EncapsulationKey768] or *[mlkem.EncapsulationKey1024]). +// +// This function is meant for applications that already have an instantiated +// crypto/mlkem public key. Otherwise, applications should use the +// [KEM.NewPublicKey] method of e.g. [MLKEM768]. +func NewMLKEMPublicKey(pub crypto.Encapsulator) (PublicKey, error) { + switch pub.(type) { + case *mlkem.EncapsulationKey768: + return &mlkemPublicKey{mlkem768, pub}, nil + case *mlkem.EncapsulationKey1024: + return &mlkemPublicKey{mlkem1024, pub}, nil + default: + return nil, errors.New("unsupported public key type") + } +} + +func (kem *mlkemKEM) NewPublicKey(data []byte) (PublicKey, error) { + pq, err := kem.newPublicKey(data) + if err != nil { + return nil, err + } + return NewMLKEMPublicKey(pq) +} + +func (pk *mlkemPublicKey) KEM() KEM { + return pk.kem +} + +func (pk *mlkemPublicKey) Bytes() []byte { + return pk.pq.Bytes() +} + +func (pk *mlkemPublicKey) encap(testingRandomness []byte) (ss []byte, enc []byte, err error) { + if testingRandomness != nil { + switch ek := pk.pq.(type) { + case *mlkem.EncapsulationKey768: + return mlkemtest.Encapsulate768(ek, testingRandomness) + case *mlkem.EncapsulationKey1024: + return mlkemtest.Encapsulate1024(ek, testingRandomness) + default: + return nil, nil, errors.New("internal error: unsupported public key type") + } + } + ss, enc = pk.pq.Encapsulate() + return ss, enc, nil +} + +type mlkemPrivateKey struct { + kem *mlkemKEM + pq crypto.Decapsulator +} + +// NewMLKEMPrivateKey returns a KEMPrivateKey implementing +// +// - ML-KEM-768 +// - ML-KEM-1024 +// +// from draft-ietf-hpke-pq, depending on the type of priv.Encapsulator() +// (either *[mlkem.EncapsulationKey768] or *[mlkem.EncapsulationKey1024]). +// +// This function is meant for applications that already have an instantiated +// crypto/mlkem private key. Otherwise, applications should use the +// [KEM.NewPrivateKey] method of e.g. [MLKEM768]. +func NewMLKEMPrivateKey(priv crypto.Decapsulator) (PrivateKey, error) { + switch priv.Encapsulator().(type) { + case *mlkem.EncapsulationKey768: + return &mlkemPrivateKey{mlkem768, priv}, nil + case *mlkem.EncapsulationKey1024: + return &mlkemPrivateKey{mlkem1024, priv}, nil + default: + return nil, errors.New("unsupported public key type") + } +} + +func (kem *mlkemKEM) GenerateKey() (PrivateKey, error) { + pq, err := kem.generateKey() + if err != nil { + return nil, err + } + return NewMLKEMPrivateKey(pq) +} + +func (kem *mlkemKEM) NewPrivateKey(priv []byte) (PrivateKey, error) { + pq, err := kem.newPrivateKey(priv) + if err != nil { + return nil, err + } + return NewMLKEMPrivateKey(pq) +} + +func (kem *mlkemKEM) DeriveKeyPair(ikm []byte) (PrivateKey, error) { + suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id) + dk, err := SHAKE256().labeledDerive(suiteID, ikm, "DeriveKeyPair", nil, 64) + if err != nil { + return nil, err + } + return kem.NewPrivateKey(dk) +} + +func (k *mlkemPrivateKey) KEM() KEM { + return k.kem +} + +func (k *mlkemPrivateKey) Bytes() ([]byte, error) { + pq, ok := k.pq.(interface { + Bytes() []byte + }) + if !ok { + return nil, errors.New("private key seed not available") + } + return pq.Bytes(), nil +} + +func (k *mlkemPrivateKey) PublicKey() PublicKey { + return &mlkemPublicKey{ + kem: k.kem, + pq: k.pq.Encapsulator(), + } +} + +func (k *mlkemPrivateKey) decap(enc []byte) ([]byte, error) { + return k.pq.Decapsulate(enc) +} + +func wrapDecapsulator(dk any, err error) (crypto.Decapsulator, error) { + if err != nil { + return nil, err + } + switch key := dk.(type) { + case *mlkem.DecapsulationKey768: + return crypto.DecapsulatorFromDecapsulationKey768(key), nil + case *mlkem.DecapsulationKey1024: + return crypto.DecapsulatorFromDecapsulationKey1024(key), nil + default: + return nil, errors.New("hpke: internal error: unknown decapsulation key type") + } +} diff --git a/testdata/hpke-pq.json b/testdata/hpke-pq.json new file mode 100644 index 0000000..d58e79b --- /dev/null +++ b/testdata/hpke-pq.json @@ -0,0 +1,1380 @@ +[ + { + "mode": 0, + "kem_id": 64, + "kdf_id": 1, + "aead_id": 1, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "b0451916702d592d6358f6306f9e3ac1f5dc3329014f00d416fc231e4cb0b21b", + "ikmR": "1e3b1d6d1ce340c7fa402d6c3dabf8db8842429714abb88235701cef640629b80a8f68e5fd56cc470ab718539c93bf35f361bdd35d9d65c2e277ef967fe467e8", + "skRm": "ba0f0c4af2328dc89ec354c6b59c3714626773daf08f2d7e249309d9c331cc0f055b007c6947d28bfc52cc1e6af7086cd5db100a8147a4857615a4cd1e83ca63", + "pkRm": "8eac7c8b5ca25cbbc076fc1413a6110db16959041ddfa05fb3723a238ab1ac2a83b87b2979278293133c46e645d7e580bb6b44c8a1ba0089b9c2c44e25ca0100533b3e273fb4617f63341fbc00aa455bc7cc31ad4e22abcdf22bab319d187b835d64858db7668f45babf348258407e56d8714eb6344947185d824d6e1ba4746aa371889d625338d9199a3bc105adeb7f61290fda304f872c8e4106a8e3c3864011202ae9664cc590b44c55aefc4400379215210d28080effe9a88cc46c5e6337ffac99eec23fa1ab7bf8c26092db95d3ec449d422bdf410f8e5773cf836745b074b71044056b3b25b341139b9beb90bf64a2b7990b6d5b06a493b056d1e481566ccd98082ce5d022bb7a4ebddc87f5f921736661771c4e0617a9f8d1be2738bea8f57b1f3ba8c552ce5657725d539dcf4bc4814008ed05c052a0b848c994b43a69c0da278fd951e9e817ab39908fd95972973d0d033cd8e694dd12513a045886e5b892b76ef6387ad8801cb8b5c9fc7c1fc66a2ab845c5eca21e85b06e749cab30161efcc20c5a64426fc966fbca757a088effd1ca7c4134cad87c4e03a528bc303d3c08697916a5174ea87bbcefe6c2790213fd9a354d0609d03118345c99ae3ccc8a3c395dd8198c5c51b37ba959822fac0250cc981f9b46118b09c8bf5c77eb5768c8d9bc05070fa16668beba956ca4af56d7caebd7140a20a11a7c22a5d27c58e656221bad27064c3112914bd55bcfd052788c7416f53de45308bfa37270b43223b7b2e67c1fdee7b11f2520b35c04533c127df47c0a90b3dd094e0728632fa109416cbd4fdcb9958b3b6cb3517e06698db47c5f037d0cd0b6d9847a56f05ba213b211b5101654458f76c91d2b916012cb15594759e9593794ad26c804f598675266984ddbb9fd44768c923916e26d8e696c10251a414c61e71613e2a9046c612cc593c62f716a9828cba5a7777ea6b961e86bc0093ee9683956e4a2c115a14cf6bb7d771f19594f45d578c808748b78bd0412c7b12ab80e923b368b6c978436c783a392f65f42967ac1f80753a6ad38b16db644879c4a6dc613818e739397903c409c2a38e303d6d87e098391f558e28c7f982b48b9700904cba6fd3855", + "enc": "602149195315a9350529c1cba669db47f58c20275cebc68f9968f3e5bcfd67038e1096f47aeb4029656b7c8288fd85d734ec73f827bcd5f9f14ffc403e84135ba8032a4f002c5e38028a6d7aca106d4b0697e4706eddfaa5beee9e0030136cbf7a487d74ea90d419bb65a329f83ac496e85a45080eafba06a536a259bbca49dc5d2698e86d8901ed97e8919c58bdaa3a34430acbc0acdefa97fbb5667c58c1f1958b30a411647bf42ffc056c1718acce047f67f036075e5181135f6a4341e03d3b503dde15e1678f8b167519763055f3339466b9a310410c7eb5356b7b76fe7a38364c0e8c17fe0ec2e431e41b143794a5b2999e70d42bde653b43360c939392b088758ec2a87c4b08ba85ad951dcdd4dbcfe2f7011695c877a7736ac31fc85e208c0974384936d7b64e455355897025f40c049781456e814cc2da189e6a2f6c99f5d3f20fa9039e4b1f62d4899c2d82b449bda4a2239b6e7a6e802f5ae9bc5c882078abfb5088a5b4b727f9d1b4b2045c1c6b4de122b68f3e27cba0d39c2dbb44b26f60c7b5afa52166585f0f5d656a299ee82ae42a9a31a1ab3d387c53c0c639586740e3753cbe723156b5a5a472da0337fa26eb4651791bf653dd33d7c62a69686cdac505b5703c2a8b41640a01893a1b1792e9c9351bbd5a6768505cd74dad62570a24b6d6de277657ea700905ac28c03f18961fcd0da4c57df37254868e58c92cb1ae7ef90db8b92c25734ae5a9941cccc50ebe5e608c6ec254bda7635e45fb2c65008bb68b59a066caee2b91f83b28ef0111f7998046e54c731b7c55837e98161ccaa25a2e8061da0fdded26ea68665f03da247991325ccd3cc1e7c92effc8d4228c1e7db2c0bd2086b336ac6773bf9de5e07052d39db319c84f08972f101d87c440431d910d142ec44ae5b6b7fe18f57d58cae9ab63f9dc0b7c1e42bd02d22fc87d0096908138e15c7414aae4ed049dda42a7c49b39d5b958c225941069e2bc9ef5ae35e3b918cf9a6702c76be5476a4ac07c38ffa55ab6ae4c927a063e5b7f71dafae3aad28ce31a92b2cfde8212f047da47e1175e81addde6a9a1ab", + "shared_secret": "2fc9533e0ba8e59f0753280bc099674320bae39a0d4f817b6271789b2f4aef33", + "suite_id": "48504b45004000010001", + "key": "1c70cc9e7fd0247c168ca60a571b94bd", + "base_nonce": "388be5ab975de38b6b63492e", + "exporter_secret": "51885fdc6e31c3628f35b26fcfbc232d904d7f4b6e22e6ede588c6e0aad60f90", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "7b2cbf3267568e7658d5f142438a320203d93dcc4da7c35cc6160cd3155d27476e84b45c97b8e99b4a4fdde2a4646f0fe22c126d95671b1eb02841aa6171843f901956d704ac203c16bb", + "nonce": "388be5ab975de38b6b63492e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "4fa580ef1a1e04b215025d5f2e484de4a46ccb4058f9c1f6bf510d28608cd9f75f5a01b033fb7800d4bad1fe9e08f75bdea91e1987dd645b51e4ad0c8e9ffc2a8563fbe09eb415a9e3f0", + "nonce": "388be5ab975de38b6b63492f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "391022ddca55bb7d752fea753c42137f150757a4e3ff63a7ab9a46b763c7767dd27819e80a6d22b9edf9df0074ce13a75cc6cafc386f11e31c53e51881e7aef511d17b3f67377bb69c6e", + "nonce": "388be5ab975de38b6b63492c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "5c5e1bab076151db3a9552b29f6be3a8108537f3874521cf3f141b2088bdfdf8d136b7b5ea868ce778169b0ddefd1bbb5d8d548fb359deac79835620f3446c08a4744d145026f977a23b", + "nonce": "388be5ab975de38b6b63492d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "f0463c8994eaadbb949bf601ca8e698f01a6030dc6b9f0e4e88c8707b1e89ed16d6d55b04908cb0dc4827946d449fe438b28d1e90ede4c072ff31698bfce8d54d0975e264d52e84f7346", + "nonce": "388be5ab975de38b6b63492a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "44fed22a38864e1fc9287ebf7ce113929b8da044c541c135a9f330027c5fababdea4e586635a6a005c51397e609f10a98799bd73726559a1f6d9b6ff77b05b6eaa2275942e965e46b7d5", + "nonce": "388be5ab975de38b6b63492b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "6e7cce46c77a79bbfdf63b9997a0e3980daf4e315358a40ced6019adb0d6e7d368430a4f7a9fd0ecac24bfebd6b46fdd8655961e62bd873d32d4a55b5ab46eee8d201e62754d933f5e5f", + "nonce": "388be5ab975de38b6b634928", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "82c186b67aaa9ae4de7e4212e94d3f2b2777215a797f933c0f5d30781145b02544d07eafa09242e84cc8ec0917ff034d96cb08d903eb4a34441753cc849bc949d773c7399af0cd9e75ae", + "nonce": "388be5ab975de38b6b634929", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "b353fa2e5f0c7f4a2d9dd93dc3f3c2803c435364f583702622693a5524697c70b1910153616fa9340a19f967c2da4bd68f4cf358e9e38d6a527ed82ff620146f6e9e3c3c6621b7c76951", + "nonce": "388be5ab975de38b6b634926", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "eea203f1dbffb1469fab12dc04aa58b2af27e7020497c2f37f932cc8407cda1186eabda9163f8301d36830a7165ff35fcbeb431cd2781aba131dd1f84f80b3eb77598a9bbe71012d9750", + "nonce": "388be5ab975de38b6b634927", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "9a6166b51568ad9c72f80a718dff2b6bb3894b7b5dcac4c2323d1fbe1c8e80f8" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "941652eaf3a06b4300f89840b3bb3f85364870313875b10c2a1a084672ba0940" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "a455a11c021def4aa9d6e287246f0aa2b4697e83ba6d89b530f156eb35db147f" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "29e17489149c6718945dea94f8b0b209384d1bbd81a4e9a3475c795858a1cbd9" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "43bc54430d1a9d9d9e0dd6075a5206ee633db6af96c0243a71f9c795f0170fe5" + } + ] + }, + { + "mode": 0, + "kem_id": 65, + "kdf_id": 1, + "aead_id": 1, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "54274849d6fa9d1c71d658b4bcdec56bba6a4a49e0178fe4639d321920c258c0", + "ikmR": "16835630bb0fbe89f7a5605bd673559f4a665773fd52aec4ea0cd4e7509e112ee5f9bbc75753ec5e86665343136139d2e8676ccd973ccf3114732dbae7445cf0", + "skRm": "3530176644619eb968895c1a251e8568e063278a7d9f4314b7d0ad973be2fd0b9560e77a2ca3f07958d782cab43cbae46e16bbc90277545d333e11ddcf18df61", + "pkRm": "a1b148974799dc3042a014273479423033ceb9716d732a5b1a661ff5297c0d3a75cc04410a1b75ce70c2b886939ae604320bb06767984f519ac0753fb3b24c1d41aebd7636b9c8343367788ab742c6428c036b11fb118a27f1022f5b5e7e14b1fb7634270b9d2d42c226c513af2701422b1d103237279025809a0244c90f3ac295eab9c35de3ca5d235754b0cd3ed59119e21805f48316877a735bb110f77730019d6682889cb649fb099be1269884f13ca7586aa9465c91621906549de239addb0bc740798b990763e8636027f94a3b6813ff511fed9c5717e15901d2a788faac1197c3f8d1b821da8c392497f5250de1b12f5800cfda207d438a6b85560d3c2c7dfdf2661a986569d67261e403bd937a89d36ae7bbc78089871d2422f3c25594016fc6dccfb47794a221074fa473c326cf2436b389d788c121042ac16ec3211dc3c289cb48a49ebb9848682f171b332f9b5ebff373e5033d9754b77903ad3013312900b98feb190162108214b3900c9ef41acab13a1505d021d622893b1baa93323e16008b3445af21087ea0765d8cd814405396d935265a974a39b91f93e31d0348865eb7979f1452e59751b1c97476f88d262187f3203531793d6d035091214467d022cd879a4c566e61d3b4c825828e03677d234e7980c8de4a0a5e948882e826c8d10cb2d49b2aacc05360798ef0abe47680a4d806c53acf0f2092e23467def40a7103611b887306774c442767cdc4be59e98509e2be4bc1bb2f175fefa186f2b39a66f1a96e11504d798d026947c9cac13bf3c330f52cf8837c3f340001e11849bc3024a99481f3477fdc6d1734095195189510100672b90b68868bd65b01a51c0df279e9bc94c414acbb2a8ca4745096ac5355fc6457f22935d52232d69559a3cfd6ca6349731e5f65594b44364854a6fc6705236c836391663d4328cbc47e7ff5a97b69707b842aac9091c613c744b53539ba5c514a40cddc7880748a7e1816ac8581e239244f3525ab63758d2030d44a7bb9a9ab4a403c9930c8d5e755816c20c1ec0e59741887086910a7030192243c9195bf9a9c9f5580bf404911c059f4c1b70644c892f420d1411920dc710920b9fbbc2204523b962c5d86129f91d7c464f989ffc2a8801ba19694755f494065f0669b2751f864643bac568ba848a12abfa15b295d177bd7b87332585c0aec3899f8442ef04e0a4b15b19c506ef8bb84b641e3b8c6199cc352f08316a9322a4a7969472dc1b130fed40e6141b019454c04cc00c2491e680017a892a38f33567880c586231a495063cad436ea8118474278bcc5adf6e0be18622193b58757f291f660ba459c98f3d19e2eb372cb43268a82ab855845bdf5b264a4b93a688beac81201e8484eb48ba6a908a90bb9e0c038d70775921a9c021caaf313cb31f2bbf4a71effc3ca8f378d80b4abd739bde0d4a8c6679184db9828f531ae63a399869ecba99e435c4d36837a0f29ce020426254157d00acfe6720165a4c6e44a434456ba606c323701a398b8384585c694cc9e8475a346529c94389b654778fd2392ee13b5610a925a520513345eda13955065a949d3ab4a35b65968c2a8e15389a533a8f6a88960780eeb074db08bec75dd725c35f95ad3ffacc0f93f6ed4593e6b99f27856d5f757300f81845476", + "enc": "f208b05a0a31e7bfa386471789e63ed19c037306acd4f46fa22638a9bdd8727e95da7fcbc96e48c3c6dc056cd8305a00a5bca8a1e93a0afe2e95a96f5e11ebd5aaa6403ceabb03f7e570fdc330551d573db8e20ef9da74c43f01e3e608086c4127b9a7a21e528167ad147839ea05858f96656551fe18add75ea8c539dacb30727826a8548c2fe7cc3cbd265f3b72bc1ecbd4c708a6b42b45e1cd8a9f9703751a1de534ecdc2206e842cc28d2199def060e66ad8cf8c1b4f1bc25529779b70ad2f778634fdb6c644c5d5229059d137a263777270e0926021bda68e0da63ee55b50610de504211501225baf5e4643ef6697bb58a4fa2133f8ceb11081c93a8bc99ba2962bfd4e7d37afb09e18ddb094ca6b417dfb663fdfff5fb0aa19acb178fbaa049edab4aebb4cd6e82e79c4d7d2a3ebc30f5feb21ac9b69016ae2d86a6b1d04f81833c646a101d7c493a76452519c7a573127e0eb6f2c33e845f0480f288ccaeb8c764bfe9616f44f2ab8e2608b758d66b045bc2dab5126edce6cff0ea5b46a8cc9a914f0885a8cf661de2031faab4d8fbaff1eb957bc006944cfcd9d2aac2a3f0fd1706e00306cf75c17b264342aa7e4d3322383b3e5be0bb0ae9944e8e6c0e35b99857b60647a2f508f8c5d5ca1cc99a2809a6e0f53ffdb9b0e38a4ccabd2193dc39fca692d52ca9931e69601f3e7e481fbd996818286a28c6234942e303e37f26d61e54f76169228f1e1019cd7b8c657cdc9f0e1bfa471a3ca6b7c575fbc95612d7feb7c6f9f861377b13293eff6f271556552f79a5dccbc0a9e23f7ac877fc8d17a636d7638bc5efb2b178bec0816936d479a59f09d2095a7926af0e957e8cfaf152796ef9b94fcfa103b8bc7257137fe6b5a37fd3e7b28db71f48714650bbf12f943ba1299dfb94ce797079d9cc2c010c1793da338a2718cea6dfeb774419deeb14271f8e323e5e80b9a21a853d3b41f945207cf22f76ed906224e6c213b88182f5c3ef12f38fa9756323322cadccc5f12c2ae9f25c9971e0250b3bce5307a6d8e28e215a7199f1d6d30eb0390f3c60ce14b32f9a4f64da363173013249d827aa104e42b6036e158773c19858485ef0f4e75936c846299dcefa7103ada6d42808247d66323ae82cb0493c8752fbf9e92dd6a7158fdfaf4f1d389cdb3a20c0b98e409282a43537a6eb6dfe29afd898f2e5976f8042c166ee0f89b96905245f06bee9ee1ee8110c818d4f01e6b6ccfdf0bccf7814c26c229ef570a9f1da1003fb1ef3aaf5157872c44ba77c607635faa93ab8e0bfcd07c881792e313e37c413a94e1179cc1b3ba703835ecc16c46aeac51befe03a0c197c380c55d821071ca3c5ff5b44f1768a1c888bc9f533c054f4dccc5ab839b7b366c75f1b232d2e3223336f875f121b5031591e378690eec5fae0c96be8402a2e214bbfb6364922dc66eba8bf128b13df4b2261bcddbdd49ff79f223e5a0c0c68503f30b97f242ca4cfe769a9449188595c3ddca23080f317c638d0508474959d60c06acb6a5e34", + "shared_secret": "02a5ae918c2061093153b64a9ab0e7fd0557b83c525ae40b5105445562acf451", + "suite_id": "48504b45004100010001", + "key": "10bb7d2e2caea3dfe5be5b67839a19f8", + "base_nonce": "4b26a28723c323f51bfe6e7c", + "exporter_secret": "e0fad26021e07668d9a455daa43aa39e21fe0fcb46cb479b1c71a44fc4f64cdd", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "f46dae7e4b18a6c14d9d8758d84997e74766bd1f79d59f28e53ee3fd610bbe4616ce1da84f186da448a6b9990c9cb7e299cc744d371116da846aa0346adc53474903e1ce604e7bbeea8a", + "nonce": "4b26a28723c323f51bfe6e7c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "f0051c99ec402db090087f7ea2de907113234774d2e6c36cff87d4e4ecc46a90e9916a5f3e6249b6de2e141b9f49b21f77d0259dc05f3d15045c33a84a9c176796fe1cc0cc7a265f9579", + "nonce": "4b26a28723c323f51bfe6e7d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "f5a3b69c1239f0defc082cab5a76f863ae774d58f5d4909780dd9e2be5a87496e148286a114b8ef736144174f91b0fcc4bb1a446a7dc664c0341286c5a560aa1a04b4a30f8f9a8859d58", + "nonce": "4b26a28723c323f51bfe6e7e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "ba959f80762a22aaef77d151c31e60c72f7c91668c3e3c7dbd8be6d12636cdcedd6e5f604eb1c16abf897a93dd2f4b1a5c8a73301b04da92f341ab0d32ef0af3476a352ed020ebbaab28", + "nonce": "4b26a28723c323f51bfe6e7f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "cd5c0cae7e2a0eb7c6272b38e6ca4a3ccbca5353959e52de7d8d09bab9cf8faf880141258f756e06d351af8952452027261e7b49e3b814ff9180df85f6c32ada58a7cfcfb1f74d85b373", + "nonce": "4b26a28723c323f51bfe6e78", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "70b1f80675614765d12e7568b0c4374a1638eecf9e572c5c47258f1f78ea707538740b75ae68a121e4f096e4e4be75f3aae8d93d4017188a08f27d1f43b5b9cdc121c2882fa33382e4fc", + "nonce": "4b26a28723c323f51bfe6e79", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "77977a6a7e4134b98c296665a34be0edcd513c2556fbf2c5e9631183201ec105901e85f52e2474c29d221aeca8eea9db4a22590f3c2504e96b4151e3dbcea71c14d8a155bcd97b22c855", + "nonce": "4b26a28723c323f51bfe6e7a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "eb96e1f80a79496fbbe9d5e961e9a725edd09202365240ee310df4e0a222aaf7a3b1a0213fdbff5b29baa684d674a2527a7acb8b1e59620146efa5f304e8b5277503dc1fb3be9a3f298c", + "nonce": "4b26a28723c323f51bfe6e7b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "2b25c36b321d475d031dbcb640345433ef0e0655c6064b06e65300a5be8de5352aeaee7bdfd90862132c206deb2bfb1a8f25ca8abf753367b61f7cf9296e50da0e9610898b07938a5879", + "nonce": "4b26a28723c323f51bfe6e74", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "972f3fb949449fbe0343b3d90e3c0c0ff6fca573b5659d7e809c97189984af3f0ddad6b96245a1d98e8d210fbdd3c9ad7eae27a0494a651b20d6ccf5ba9759617168c08a578db137e9b6", + "nonce": "4b26a28723c323f51bfe6e75", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "9f0882a3779fd74998b9c8ee1009e8bb00ef576b71cda1f0b3ce2a29df7872df" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "5f7f4918f923103a198fe8dceb584b364e3209c8cb6a57591e4e73d9f4981586" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "bac03295658e50b3af56f1625e5c75c2dc5cbbaf40e35d62335bced71033a1c7" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "e62eaf1f8a45248d7b9eafc1e289267f633aff1c97d53e93dfcddaaf2a6aab4f" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "e1b2cf7512f8cef31523f5dc20df0186fe51baaeb39e768802943c5050973537" + } + ] + }, + { + "mode": 0, + "kem_id": 66, + "kdf_id": 2, + "aead_id": 2, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "b79ccf36c6d61fb48511de939a6a23be436eb9c744bdbd3a6aab85bcad61377b", + "ikmR": "7544cdff18a3f8789f512337a27b6c68efd145a30ed3dc630f5dcc5ec6932929bce1c023147c48c954fdc213a7c9c0dd8895b8d28ec5c5e44d0b30abf9d8ca47", + "skRm": "f279454d08150d5bd81252001d02e1099f12fb7e9be6da2fe427bbaa2d79b0ab67306c0153c052610c4fdba3fad3435aeb1b65817d442c5c18ce07ea42440005", + "pkRm": "3f1cc56f89842dab230c6c09ca701c98db48e54a993a498b4b3336536051318309c58a8bbee9274b19a7f297510601197f42940c4207fa027965828e42f4a254f919343505cd922bf800a9551a63d784cdc61cc1c3566a87c8b817b6ced8013315711e3696c3b0051ce7497d9bc92796b3b629ab28b55842ad52660d3b268599c467c92311b4a792e827e67131582c9e3d1c8da43ab201319aa95070e10748fc65a1316a6b22f03fae85a08691395b660e759a33f9c80ec74516c0249ba6388aa105095750c7cd947a747497a879006dcbabdb98bccf025450810884c7ba8c452447e5cf0ee75665468fb16c5314c2af5b05a0eb0084087c98d985bd53b95dbbe589f31401c52143f678605e712f87b4076eeb076bb3a099f3832426416805640bf57fbe64484a79262887954f540762ac3a388258767caf06d3cacc1b9adf21a6d7116c30d44562b8507d34045a760ece1169adb264168c10c7844323f93c67710f65e2879ada7edc7728a6eb63c9c37b7169a360cc4d9f391060a42da0203ff28b5a702b82f1707e6e777e3a793f0fe5c40ddb4b1cd642c25659989bbc0270412d750d9d50866b532ad2e83f171bbab0d928b280c76c0a3a2da8555ae823413118e52b31a9f6a576837b3f9c0e455244c757b3b6b59d0f892bbe566408b82df224366b613e0c4915256647a01c495529c125956c21e69bc7a651cb3abcf9d11251a2318dfb57aea391fa8948b9024105f244fc1c64c4a23c37cb71b3fb7f31c102f736109c6acace09c24edb015a7c17ba67afe241684b4181a874049058c7f3d157363b8839e4027859911d245dd22538d9d953ee3699deb143b8708e689430fb95451bc0360632401c2a9ba537a73c855973f87032c993f0f26cc3a27a6c67b5f8a84df1571498c3790cc3933e80b1e88b7d4814ab2980b6821795f4765539e951d80798a1e93df6c882d6ea05fb21914a0b7c0ee9cec700cd8e8a46cd6c571fa97f88f5496c6c1bbf671cf92642ee7a8c431152bf8ba3ddd474829c463258901058bf860cb49239ceb1074014fb4d1ecbac121b17769057ff272d531c87eee2703ff854592385a7b8bf87cbcf95422709b9b11a05291e18c61f672a84d55874b952588b1f8f8510fcc13899e575d91b11b2164cc1086359721280895b0fdb63bbcc63e4e84346523ef1ab391be9591af524b6dca27de0a06733a754c764329c3b8044baae259f5aea803304192ff382f3e4879a9ba8b88c0dd3890a6e1b1dc6619ce9346b607c3ef1f24c29aabd0fb954c80777db8a7ff59173aef05efd13544a621f04919d63c87b37658dfdd1c58930bd9b58ae275ca32b912349c975e308864ec95e133917ad9539e7178a9fc74e3fdcbc4478b3eb410d4292c5f78cb32e217d6e381639ca363693423fc29be35a1ab7528ed9b84eee867f426c2aa96522a637b0d4b164e9a527d6c9108ce77ccc33389c05cabde51a4531ce64d59a09aa6aa7e493349510e8c69ba4206381b50f008a18eda076240113acfc9fb8d0c852dc40a75784eb555e0408a3e6e613672b76ce346b3b5c27d4f09a4c89caab1426a320c229f95b06765847b027c3d9896762b769abb6fb31066694c413576f2ec29b93c0837b3c46d6065d7d9a801b0755383493bbc93e919b0bb3d6979a277695a298a8346e23e9508e6a9af1d2bbdca30f9c5c275176842a92b8db727fe1f92d52e70a1976851643c09f42cdf6ca739ee93904103427d05f49cb54f540c627939ad4811214b9a6e8d2b5e8d665ffa518ac10902707241472750c8c4d90fb9288da17fe4110a0032c853444f2aba97ea389c1e3590b206c8b6b76181c9ad510c6860bbebeca69ac1aced3a0147d1803d570047d3259f329b14f352fcd96669a6044280333f7c3ace6048dde44492f70bf8dbc7150b661a02460ba61992ee8974dc225125a87dcb4598eb2792bbccf390b9dc966632e918d58c7a16ccb4c0886422c3b467976ce405acec161cf3c34742cc912ff313390b26de1f56a341917d479ceabf13a8b6077f81158e075a1d55790f7495c76e3c348fa122165cae430b48a753ff7dcbea6d59135b97127b844358a4620299a5dca16b634897a947121417f9837b3a8a7baf610a41759aa8be73fa5f22c2656c0149408128c5aa202bf5be9e1d12f54ca0db54056b2c35830aa4a33467dacd61538d7db881c7ed5ded2", + "enc": "e29704446b36f5c02d8ecb2be8455ca5b7d9001bd7903fc9c048429e0fe9d9d15aaaaeea991cc9621e1101acac18b28af34df64226c1a5c0b7f26d5ea2b49fddef0b7f7262364f2c125ef297d7a66ec9a83b0f36421daca3eb525b8ba046000e9b7efe28f84f542381b692655ca3e65c2dba93795d3e1f1690f25cbe6a259917e5a9f0a729556dbf168a52296f12ede001bd48ee24107abdcdace0c10cc30b32400598f0ca10f38d5ef31d633f041b7778661b68f2a5945996e43037c8b480eef09915cfbf0ac73ac977e033135e293e30fb351e708f1207a6a4557d3006efcf15c91a3c15735dc70f0139c7ffebfa5dc80e571b08bb884424a233b61d5be2b45888a09b0a61e91e11867324586e8651166dfbe8ab865179e9eb2ff5f9591a375b6da49b614e7dadde84f62bedc588b0f9af80abb9ff0885e2819e8cbfbb7743cebeb086a53fcb646d7bce56715e7c7d0627216866ffafb80fb2ba30eefd831c5aae04be2cea479716749be3e50d10ddae80dbef3ac31975f36df700b2ed055ed36b9c1a8e988e59d52b427e27e21fef1798422df54be26cf201d36c37562cd031a358886e2212cc9112bc249d6e7769fbe3495f84433ff8ef06b33cc9f0fab46b62625eaa66c82300f4fa29b176ad76e71d7c735a2896911644c97b7844623e73172792d2fd61db3b83508f4614a4cd1f09569f2ef4b0d638aa1dac7fea128d1e0b544a3cd57acefe681e62b57de7641d500ecff2eaa34a782ffd5b174b74b15b90ada89cf1eb4c55b5676a98ec8354eb38fff7a5762bbba0b9b6683fd45e32bd0199a873766f4736a1884cdda1cd30106cab2cab691d4bddd3b87b683a98a84de8e64707d025086c36dddfcc9d02a8bc76f10dc44e832dd73986634e90345b7d6b2a9c8dd3acd18a7e5db8df2e5c3574961499a07178b634e1ebb4e4953401c51c4a8383bd699add80aa3f9de82782a78b69c3cca8bf383afbd556a9814764d088f43e98bfaf4d8e9590b07c742e12274ea9b568e854bee8e6d0f7e902a28f5b2fc72d6fd10c40e77a914829591f391c19260ae5f4e2aaa113f8fae3de4f9ce85d91eca28bc300e6504f58915eddea0a7552a5c701a90ab8dae72d990459860f3df2f4305aa60185e20e17f4173dd0749552c1a4edf0b654cd41de6c3b07bff1bc4c873f4c06506f04b1eab0f8fa5883577bfa504b3b7b9be7a1555d71d0d7660679104d3e7f84cbc1b575314df50e0050e2fd5aa9c4f571c1b2d26a41558af619e15ffcdd8e27eb5a81c474abcf118524da82c96dbb691dac5679e5821bb382708476041d87a7175bba2af8b0bbab27658ef5dcf7f242e47129e67bf5d00e7318aebb409ce4d0607136fa38e9eb2ec8f29f3b2f4ca485d19f8d55a3221bf095ea4c155856d169b744a756502ce85d8415a2b6bf1b629282bbaa75c179e63888b57460fb4c2c010bed08e42655c6709ffbc032fe9ba2532c09c64e9eae3fe47113555cabb3cebdcbc790dd1e145fdaa10932fe245e33a486465abc9e4d017f52c03e5524c7d8e2e59727fba297e3e96179d09af8d56f178ba484ad194a00c701c521c82cfca2d1461dc507d50fa2f1be73087ee594753dee96196814cfea07a49f0a445219106e9e1dfef08aff1f136c244880b793c1484c10ae852f22bce3fdca96ae4cf1d4674d6584be28e502b9cca5705e9d03dcfe1abaf8a0369bef7bbb7bd0f577f6343be4dadc159c2328c861584c88d9624b26ed5c6461a7cf20ed84a0af3475710655e7e50427b12a6d6c7a0fedc1d59ed983f29568105bc3498f4c7b5df5006679e6e753a9e8986d105edbe43402a4a6289e88f26439f9a47dd887dfa9bdd2680840700cfec8d03952afba5011a23f55d0188443479ee93b40d9e9850272c3ad46e0675a329aa6dc1c4854becbc67939cad13ff3f3832d95ca5053d5e867935cf1fc19b737bbbffae220bfbb8b6890f0541d9a6824e33f09207516659579370f5279091b802a15343ec70924bfaad3663df95bbe667270ff842233c63d79f94ff65fccbca72282d8694e72cd7fe70e40bb1adcd9188a056c81f36cc3b8c74daed3738846fcd729d9c871dbc81a06624ab589bff471afca442d8434c452853d43ad9a0d0e39413216e65ed05b7c8121f0b09abdd9d1cd5bae2816c7e1498e49eefef0c0b0ace052a192922fc8e2ab482e2e67c64db0810c5e4c68", + "shared_secret": "82e39853d199735aa5bf8fb3fbee412de8b39ae39cbad0bd7326c3cf1f6c6232", + "suite_id": "48504b45004200020002", + "key": "ebd832651d7005d5a35804f59144f56e0314e41037eb8bccba607daea19dc555", + "base_nonce": "013887149dbdbc55d7839b50", + "exporter_secret": "8935fca4f779223c22ab972fe8a502fdf2a900679dfc2043daec923a367bb10b294386eaf52196dde82773c914c94f37", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "ba95e8b9f0e4379e073383af32ee83594859e83f2ccb767886fc9af7e7610181e6245a732465884ceecbfdb9301b6865e05cc45e3587d0655bddcaf72459649c92db3d0a40f343f9d344", + "nonce": "013887149dbdbc55d7839b50", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "ee00afc90fd18a09fb75cade86c1d0e6fac3f24dcfa6a01a185437570515f69b6fb893b0f42c5502366ec50b3d4181cf0f0fbcda62b1909870f77b0fb000d7be054fb3a59df4c1d727ab", + "nonce": "013887149dbdbc55d7839b51", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "3c1289e325df47042f142897d38e965e39e54140ba0d7efe4fe47f45bed3d54bc010b94e7fb3f790557f191812df1f21531558b3d4d1fa0c81863fc438bb6a293df247ca695a64aca140", + "nonce": "013887149dbdbc55d7839b52", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "5ea8a9aca17669792f0d1575a878477d5c4df693226698f62476efce2549a00a69b594f7776ab70b4ffa4ff4ffb3f6b78f6d8ffee59ab62f4301a87948667e4f6d8b7efad4215df3d0d1", + "nonce": "013887149dbdbc55d7839b53", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "55d64b7b3ffe781c69b05f74599aae39b38588f3d6e0d833cdfaf920ef1df4bd1fd658fe005f157ef9d368f45d0f3cd41068c9059c62ca535ad58781afc351f4b38611dcecc5d40c9d5d", + "nonce": "013887149dbdbc55d7839b54", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "03f577ef31fbbaf54252e9c9ac402360d7e87633d70c9ce384f89462e8bf7d52aa8b3ce760436ec89b5dea72770ba47bbe11a5d27fede61c6bb1730300334b4c6a447839dff17982720a", + "nonce": "013887149dbdbc55d7839b55", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "8416cc680f83defd1f362e4728db97e2bb8d05b395a45b4429aef680295fe887f15b6cf2f1c713271e9c768ede2195e229461f2634989d2c1b348d02337c518d06800aa5049680d68ba0", + "nonce": "013887149dbdbc55d7839b56", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "9c3c8a2e6940930a9b09aa88070dfa7678acb40f133c4aaf50d1cf82da0e04bd4451593a1f3ff1f862ee8776e2904df06bd566e6e1265d10f129f947daa5caf1735dda05aa4417f9fb09", + "nonce": "013887149dbdbc55d7839b57", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "fc64a28c49e056a846114179947087c57bb09fd3db49e4f149e22c01d817dca290def7771dc66a20bd26dbb28d366f7e44c3e5b02b8f7e37921d3fc4f3b0865410f5cd8bb919ad824744", + "nonce": "013887149dbdbc55d7839b58", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "6b011b9de556f1f06f811804b3a1b4040574b064b60b762027545ae317b1e6a8de53cdf253d81477a596433c91c1ca4cf3f06b573be0dee810ccd65d286e1c272cfbc3af0a439e1bf0b4", + "nonce": "013887149dbdbc55d7839b59", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "e35760f027e72a66915f5fa27d59383295a42242af91511563e6f0bd135fce81" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "30ec84fd5f4f49cd6ab82f09e903ee4192e92d116381510361b455b5d29df750" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "ed31f4bd4b7c5acf3245c5ae651b04bf4164ed3a700c0b040306108b1a315cea" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "db0e641c78de3f9adc2c441a770d848446f47315c8f8dc004a12551115341dc0" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "03471a43a65a317c6f35a3beafb2a73bce0b710d7b23155d2aa615a41c917731" + } + ] + }, + { + "mode": 0, + "kem_id": 80, + "kdf_id": 1, + "aead_id": 1, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "93f347b9b3d83b860c47c6abc515490bf0d50775db3ebb660ecaf9ae5d6c309441bc577accfd8e9d87791ae51b05b01ac8727672c01f71776d0698b02a8059f46a17533a410438058744866e0ff78b7220d4ce4d96e130d30b65eb35011ed134a5c606031a8e93afa8a760b491fbc084b0622a28d430f3211b14b340396616dd", + "ikmR": "eeae80edb6af9026dcbd638fcef2f4a19e03ef68ed699e507780f2c7d167ca53", + "skRm": "dfa3a04d54a0ec2f7edec57185e3df94063855fc7af64f25b815417a2c6eb0e4", + "pkRm": "ecab6a5f147046838ef641bf65f52fcce29e6130038573128e839a1ad7cb1a35a9c95c3a41d7464b365a3043b17a153c6a09382c580fcec41f38940d336309636c775bb20461f9814be668deea4d07623f545241445b72bc15125c8b90a7c41cda17292f93ab55659fdeab787340011e5c3de9e4a699660ff5256db96224b2586fecf6475fa76bc0978fd25b1099603053f48023baa119074011e01ca3f92a09ca088c2a9af0697416e661eebc46a2069c31042c570678cc229f6e502121112f4a148acc59990d6c378db26f97398bd2929a19d0c50b5713400b70f9d50c79388510c13bdf975f4b4c60f7fa643f059afaa580b61975fd59aa98b4c5f2cac3422b9f89f73d14a18a15942a5567c4baa09359a45d1ed35177959bbfe196c7314f95f0a40d24c6668b10de95a7e08cafb46873c99611bbdb8e1d5cb0c8c2beff0b41fae1000ec9cea1032a3a6838c3605397d59fb28c9975aa5f958725598a0c82b788f7fa22dd741a0e673497617043374e47f69903c891f47787ad069132a93eb6f9b15ff9923318a5c382c0fc7b432d8a00652197941684a9567a92515c71daa8daf80f2e425488f88bffea0ca2a6c682d8aa68264ef00241f0ba62e2d529add964129997f51a4a0d195b6d5b0c31634ae81cad7fa53442c76646a996b60c3e5f1818fdfa1895c0aa8cf393f91baeef237861e48bbb236c3460b949800ae4c3255454582a04abc3777c94f3ba0f3a4b4309024d117e5a3597e53a6655e17524805dbb4386af689609310f8c85c101bcbdca7c9fbec251a4f62e18b839bf46a1da5034a8887683a2b56133b7909665c5a097b7f40be725131156396bd60ff6021f17672795a375eefc66ce667e2d861a03242a2c67ab845301b2882cc62b54ba040a425611f8599744b741e55643bbeb0851b30ba7ca922d0078407396272355ee3c08a91670f2b8488b3c9c8791778a000aa263a75322831468679f795578863e67e149ccab053b39497be4ca149133a2e91cabc8390119900fda90d7b2413da2bcd9d244600178b7164446fb3a3dc433a415a8001085b45bbad32843835464999717ef180f51fc8660e63b400c957c609dc2bb6e43326fb33ab6c6c66dfe78a70bf5394c9262d65a395f857989854b95f99481d1862a5a3b5555ab9d44b1cb0bc9df89395b192bf4c43dde2bbb610850c6024c8591a7e6933746921421575d703a45e2bc08f86376c2a1cb2d133cf0346ccaeaadb81929c2d6126091c06ca81f95e413507b91e0f0cf548a5e79c344fd962c56c895238395abfa90bb27b7b646707120a894c3c947411ba11255f5a6a032cb3dbd06b80d1229e9dbcaa3fc84fe65561c3c4a8333cb7d1b4df823466041123fb604c14349ff8bc4b02ba1de71303cb99cfb3649f16703cea12780688cab0529a4a8cf1b09b5ed705231964a74622718248be25234add881a02a7572cb5ded432ef95a078f626c0006a0a0cc4e7992b08b52c552d80b1c71c3906b32ae52974b10447cf6ac6dc3a3dd53151611288dac5dddd98679b611d0c805d48aa5069451a03c3e9e880228e581901a5cc45c34cfc1cd258a7f7a10b90c281dd3da315a0b3a5c9669f3640c27d33028f922764585f8ae61cd138197f7f30615fcf00c2413dd168044c9a4e65e5f68e93f4b04edadc409f9fdbacde2f03203b08d8f35d316fc7e0a2fc57799c2ca8332a514c58c4260f57f980a241a6f98942c92c8c90f33541460657dde1040a84055924a69", + "enc": "ed5b96e04d48095bed5a54589775ee4979362198c7727fdcd62fbd6d0d4552aa5ae2a30283049bcbde84dd6e4c8a330bdf9ccf04190fbde2c63c0c9026740d5d00750e4c6244ac0e7b6a6edb8782f0ac040b4161d3a9f6500ffd1cfe6e93298ccaae1dc04a6519f52d96e43c4e7477cbdefdd17b65e002e2b04d1f3d5715dfa3a0014faba0eee73a2f30d9a71dfa4ef9a0a37ee45a7f67c9209efff17badd21d452bbae583b046a602614ffe168bdd8ec27048dc5d95f58f8b70134c161282816dffbf9f88db63f28b39ed958cae9b5ea26f0ee54927d1483b644f338be3cb6b20157fd4b91b4fa7266b32bacbd73e12afe877181d0123f02212902b1eb436c0970c395355ce6d92568014da811cd369ac68cb3d4be48318a2072965358bf0799f1320ee1a98268d8a5796c965bbc19d8b5ec7322e5390bd93aa85103e4dfbe35f16331afa21a128c62a0f9bdd04e321d266187413263fdc40522ca665df0272ac2a0418b692148fc3c2aa9273aaf424f9ddff17fb714e40be0595e6f3cc2d4e82732622ef545218ddbde8b902ff2df9150dd4a3d6af2300f57e9b72b6eccf95bfe26ced55081e01d4723a81abd0f00d44a40020d85d9c7c73ad4b129f7ebbba4d6c57e6251c58e824b47624e2e2a78c734cf21e76f0d7faaceba8b7b1ad1d663d8edc09b20d475fe79c6947f6a56fa371bb0c80625ba85fe475812137e216709fe99bb1a8d63ea38b34c89c1bde2b8685b146bf185537e53df86bae6dad3950fc946fd47893f48fdd1066a5fef1aeeb75144f0966717e12b092fd96a30503d7ffb84d1125bfb6422f296c1ef82701e5cca93a79a440a4b29a9de5961b582237fb7d71e5380df2bb8861c5dc2c6bead3ba60a35f6104bb50481e1436cac2828798011b9ba20a39017576be7a49559a3eb9b1212bfede28f72beffe5b40254df490ce0cbcc9110159d24cbe6b48227c5d0bc91c70d7f5204693122d06abee77b99fce86e12c51e6a460d5b47a0f19dfc5e0b6fbdb454abd151efbea1bc514074405497308a7278da302e9f64b033f78df23a31ecf071bf1f9cb30d9a7ea1cc87dd0066f3c1aaa0222caa580f8333ddffbdcb795da1869882ba55497b33ea610e38031de9923e1ef1f2cd48af494507a7765c7e67734e81a4d3683823dc7d15e8364280f255b8bdc7972c6d5f1385d11ea8bd5d7225fc5987a3a6d65bcd20b5334fb7036785950dda89bbcfd337ac286d87bf5447f3c7d16930a07995236970a65acb5c0cb56cb6294046296711b7bf3d7c1d40d26efb9550a50d653cea6844caf567dde9e78786b91a21eca728ef80f4b066962edd50144f2a0e7f7a36934a6ad42ccb51bfe75c66839af77456a126d71f09b40640fbc3eca319b16c525f422fefc83e4a2c9c2ae18f1c967a77660dc3acb57bc12e1f6692fdf1ee034fe8e0f5808143c4f342c5e6a37c520dc3a4c14e77ffe260e1027ec91bb4682417cfcd505b5c45e01e1532e8925eeeaa48ab5fd80e28dad7034aab8afdf96c6234842aca004f0aced6022c4e2f067b928d4908de20aa3f2d14307bacc6ec685b026858d06f5e98da3f120d5e8ab830248c49c3c4a4f0830298100999cbae5419d5ef0e557f0", + "shared_secret": "3688931682c215e9e06ad620eba7faa70dd0d38081b4ea3d5b636ee062578991", + "suite_id": "48504b45005000010001", + "key": "73d38ac7f53e00cf8f45a8a1c404db15", + "base_nonce": "3285a52336faa9bd2d1dc154", + "exporter_secret": "1109e3cdb4b327d00442091b96fdcf11d589d7b51485eaeef46a1969eb78d3ff", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "7be7af12b6976de87ef38a5454e94dbca114430bc8ebf32bd81a631b2c5c7fe67fe01acc69197d53dcb207c48073b9b3ea9fb5e1d20f817b48c7b3257291ae26742bba1be707d78202d6", + "nonce": "3285a52336faa9bd2d1dc154", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "b9e5d23242fd7cd8999282f58e324d5b9d278221311c2489187cc723ba58298c9c07b1c44bcf97ae312f5fdc67257fb8eaf4787d1250eb807bf5fef90f1740ce98cfa2d5a87f32868b06", + "nonce": "3285a52336faa9bd2d1dc155", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "f30fecec3515de28777547caada8dad061cc6d349cccdc4f1e33e3b7caf960276a41a46f5e5e3bff66ffe9f7207c4998d53b744a1e8693276a6e63aa292a725801431e8b491251ad4210", + "nonce": "3285a52336faa9bd2d1dc156", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "0843f8d4beeb2ba621dbab9be2fa9b5700cfc649d91cdd6239edd7b1936688dbde5df676eb27d70a3292786a92a6013fdc1217d0640140be0637334a6dcfd7295e736ed18e118c7ceded", + "nonce": "3285a52336faa9bd2d1dc157", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "25d0c73fda170f305f79728beb5dbc26fa9bc61dc0ac2a58dd2627c7a2f9491f769bf43a00934d73836269abfcd30807e0885bbfa9db5e59774ffe8d0c25b39e5aff446b8477d7abb969", + "nonce": "3285a52336faa9bd2d1dc150", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "cc09a83e476f47254e23aae994f1f987e599286498f7d49f097051fa456d2122e182f74a74c4c240af1dd44fa47d3c1d49b7f901caa90f772bf77818f55a5384922def70f2747447ecfc", + "nonce": "3285a52336faa9bd2d1dc151", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "06ef6f67a5b9cd3b7a800cf94a42c4418c8e56d41a1fd73eca8452fbdc16a65afcee161589565a9f8753a063b47694557e8bd26a40687bd27fae52930ca2dab851a0c2d52828ab58ed57", + "nonce": "3285a52336faa9bd2d1dc152", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "b286a4287d4f4b17d1112164e05fde12e687fbd867cd044a3415bb962bd27f75255d1d974257c457c1c617657c627c464b10196cecbcb8f8169d01886d0b3bdc53479a70ccdd0beaf534", + "nonce": "3285a52336faa9bd2d1dc153", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "a110b6995c33ef0fc7444f062d182e73615b8931ea415619fb57a6989fcb30bde2739a27eb54b6273729d676eff56fbd6d6a1f7067eff93885d124fe5203be649e901ab5cca8578fcdca", + "nonce": "3285a52336faa9bd2d1dc15c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "73c8e514dcc915f997348ced30795f3ed03d098cefe2fe8bd5439609405171aa5fddcc362e9a56799030addfda4e50f2951361b441f1b41b8a5222a69b2fc444d4fc39b85614695284ec", + "nonce": "3285a52336faa9bd2d1dc15d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "8ccc068f1e0364d9dfcd6f138f0f964e7d30275fa300548bd45b4022dc884851" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "95a615054a532f857ad1b59d2a1695fa676395060809f9c5b208e8d235db2764" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "0a678a6385518d2bc45541721df4545e6fcf8f843c10794f551a69ababa39e31" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "e9f5a0ab3ab64939777cef0bd3865eeba1589c1a1fcfa437e36f22107b08fef8" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "d3a915ba660a940af4233eed669fcebe50ea5b102004091917263cac57ee0386" + } + ] + }, + { + "mode": 0, + "kem_id": 25722, + "kdf_id": 1, + "aead_id": 3, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "a3a869097e0241158eca5dc6c9e695f9e0d2ee5db51c09c435aab69d56509a43d94ff76d7d47cf79ecf75394261236cec024bd849cc782e14f7f0738af83daed", + "ikmR": "0379761fa4f6869592b0d1f9a71eb92b122dc030a7a8858132109f6b1a4bbde4", + "skRm": "b3f98b03126a431ccecc62ae0f68e102c2d8e1cc7b21ba85d821d8e31761e0f8", + "pkRm": "3c282de306815eb40990929aeee0839bb37a71a052a9e5242cf15f4c4aa366e5142da0bb8da49e83840972355000288edfacce195826d1da5fff509dc5694d8ae6590fa763bd7213ece64e74c82134e3b8bb571c841967e44a500c2acfc7c1aba59273a5bb326ef52aa43471a9ecb54ad5c12d19bc05797d59980ae788039c265978586bbf92ce4c4b9013f3853f501a0a7b834f4843324b9bd3a07ff7f954d97aadb7d8621c58c75bc47995d02a2f70cc3d2bc519a8606fc0c9eca0b30a998bd237297dbc0298b106dc00c2a541bdfa9a26c95ba67167acb81ac705f1952fd173e6e23331c56db6913305384d52c51ef7facb92c08024a69e26437e1c289f77d455d08a1500c4a703acb376f424d57234fccaae84b3ae8d000ea8b128c4e259b6a976ffe650a5d9063c83996cbb00b30220ae43170eda370d623f481b24e4692e07a10777ab703d4b4a73c71e7a33a6f52b2aae7a4423aa5b69f58480b7acb04a6dac780a345317b40b171ae0264fb057810bce9c6b5a58027e3ef851e02cce85718c396824e3986a35e12873ba1ee6ec4c2cf0a767234baa61367af5a85f443272fc1e8c338769b8c2b9f1c58859cf920a9c26f71da71a60abf1c3e1824775b12e9608c711938475801036281e8d45a06942ba1164573ee1077b7a40ec213fe79575556bcab9f6823cab8c23297d67897bbec17b4ba6752c8913d0b781b9932a6df03505e3aa25fb6f75c20286b08b375bced9613cad18cbd42ac4063827afe5680e3cacaa96ba8f6c523236ca69da4475999abf18a25a433c94792988945ddfbb8413d367d3ac1315705797aa74632704b936cc96e689969118fac11b4f4c927a66aa670b4d8147a23a42aa6a309dc5f204902726c7ea6f1c6231a262308148c2d2ac81123050188b44a80aa8153bc5915aa8c207b22895a8339549d281c014162200d63cb2015a265ac48f0a3c93b9c71e05986e780c18f38c8fc5734fb7b22f34cc851413a3d17090021eef6b7019b5b93012753b150ffec031a038602ff62ffc6713c290a33ef86dbce641d579aa92c5aa1b4a6520b921efbc3c95156b34658dd14a7cead366a351c7a173907bd403c0cbc9b562281ed3712a4b6233d60f09d80e38e67a01c1660bc02a31303560632db6c63bdbb0bdda46b4faa77ba4cabfdf0789185c295c40220f65689675882fcc452b802a4baa895ebc50a931178d442c857ccfd503b678864a83565fec19c7ab782484877144745fc7227d582237498916a03a4ada6321b62abda04674f39338078ac087b1a52b77781d5574d41a2d320802b9d9bda34c8e356a5725fbae10599b83b97114c6cefca08f8d04809b8a79f9f0a26f2b9007f501a81679f0104c67f244cf514067e04f1aac0c823a6e2cb9517d5722eb3a8326a7b23ed62266f04acca740adb142bac5ba66c5a6b122a3180b97ccd6cf9bfc77a639515bb861a5cbbcc7f53d19b0cd66a0b64df56a15a98bff77182b7751ecc703bc947f516279a3b566485931415c4a9264bd7fcc36f1c4a1e15c3c8c17cab12805d9f585f4cba9bd496805f04c2d930a8e25248c02a362f8a56109cf263a0591ec4bb8bc6604d30dec4c715106266968653686289d7ff82e53d504f85fae5d4f64210866450ad272b3e4849b83de72a2e3b9fcf15ff88bc7348a401a95215ca1b16cbbfe5e082dd66029e768dadf2e52e283ce5d", + "enc": "b440cb006466e8ee9d161b371b6fa1ec419d6a7589492378dc678fedbcf9e7debfb47f7e0b5368b0e77ef5b5866686b65231dbd1c1a42e0af9b0abb06c795a1af0734b450dbb60fe0486b1497d7b09d0c46617a40c5f8c8ab51c2e8e1f48023f73b7c4716bba2e905d5fb42c3dedff166553ecf033305a57bf436317e6513deea2f65537065bb5d82dc4b8a965c3e939b910dc6b027e01673a6e1399b93976292ef9fd81120ef2f6c47d94a1c77d9fe16ba7107a8a6a4ce9ce0d302847d602167de077e17dbb7e0154202f76c381c4b6d8bca51680dab4dbf373da8f09aa23d2174fb36681ce42108f7baadcb35626baf30a416bd79b3e249585079c277b79b7b31108ef061f25b5d4e548f6f5cc3d4c24fa0f1716843bb63ad00a78f37d2e2b81517810abe9853829bed7b3ba309ad697d8a5f66af4dd237c25725e9c6263744bf8641d475d4792ab0535d2b4fdfcf0c5d95118f5779521023016d49751794a1ce66f2a652436843978937562a4a5e8628d2b720890d7f3b21c151399ba7db03cd15516c6a94b84f6d01a37ba92cc7ac6c480dc9f67c3a066378180bcd2922d3f5c65d69fd0b96aadc055d6b05ebb1105acc609f200e0c945a10e4e11371e23369de2069ccd7175a652c3cd09eb7f17c9b65b4aa79b26468f9b21f8c0aa8f7471d5cfbf3697d3eedea9351597ce981e7cf745c2950070c1f82f132b48584d03ba1262cb856ff6b5ae25992df8612d24f068b4325d3360673ed3ef6e2a57de297d5482c5cc355bc07f1d975fc6d60cd7109bf5a77a0ff7b2c5d9f4a276d30cb49da48b8b90b644b15a5b68fcc67c25f09a8e567cbe4fa2e2ba11c02993e9e9b4116a7c60da64a71932800aec2fb4d2eceef57c6fc2308f3adcd9b46a28748516284bdb4b3a36851512c5e0e6ed37ef5f00b07dc3c42667cf95cad764e47f48a994d17c103f8225755c76008013897c03c31043df0eb39a603e09caeaa41ae24488fe96e4d83b4ae5481045f4a7cfd7c80b31ce9eeb8fdecd34be1245f368ab5a3215cbcdfbe0529e1fbc4ba0041cfaba09836c25dd6219e75fbc6f143e74d686ecd9e1a416881bc21a9129fb865e82332985798f701f7952c4e69e7b4e6bd03bffdc0c65e2a2fde89f73b8659fd2cc7dfb070d3e95581d1bc587a2d9c4bf142fdc1f20856d3cfb64d35744ee279b829184723221e9fb19f012ab99c4bb1a904a116727b667c5a11a0e11f3e31682b0c114345ecc3ee153bccd884654bd5a8a023aa3db878148736f6a090f92785423a9ba2b037b3b90ee91657ba48a125360dae75a6fddfea406ca823a5e4fbb54aa8909fbd85d95d2ed256ed5d6a9194fad0d81a44d3172abf6b90cecd1ed2080762d670db4d3437ef8e9e7d39db4b4215c33f8d19240ed4bf2de8b1076b345707043a735bf9e96e16c8b670cf2df0ce8db638c7d84a13ee7b35266c7f0e60d2cb2e5734e9d646a871d0dfd8b4ee5f825bf799a1251ed21e54510e9c605bc83a0bd9673aee80e8d064a95c3c3151ffd27608173637fb9de30b3c02d96eecac05dbf7c2fbc98b4a1f6972ce928322a22e2b75c", + "shared_secret": "b90cf181d95351d1091569487caaf6c3434eeb181a2c4c04631980ce139afa67", + "suite_id": "48504b45647a00010003", + "key": "4a4c042267e8ec360c83b2baf0d5e3dcca73a86531cdf67ec41d95bccfe12387", + "base_nonce": "5ddfaaee10a4dfd0d8e1b49f", + "exporter_secret": "145e4b99cabeaa6f5a380367d140d308746ea25d96f937288f85403b5c4384ae", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "ac355d192158cd54250e1702be51e9d2eafe5f9292a9f153e02a2323e1ff071a30947836c38c63c986c28ccf05e00d4e5fe066a48ab8d5b39c69d32da80c93dc868daa0f853a6cbdd640", + "nonce": "5ddfaaee10a4dfd0d8e1b49f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "712e40f2971afcfbf899f766c47d815265c1a0f52dba3bd68dfe6d14918f114b1d85f5ed0409a9b6caa370f1ed94b9d564080dd7468f629881db3aee6db91b5479a634ff18b819694d43", + "nonce": "5ddfaaee10a4dfd0d8e1b49e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "f11c81d6a2d45fa589095aecaa499b7af97081376227f7a0970936ee5f034990f88ce1cee9696864419b9770d40c9ecf35a27eb16fa0c039b0039cc3b11ac1cf81ebaf6278467529ab06", + "nonce": "5ddfaaee10a4dfd0d8e1b49d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "fa4e91f12655a69406b6508ae7b9fbbf051cc12fee4cf8dc2d3de22f2b3e9f509f7218b8907d296e1af3e607be2d1d66f0e4fc778f84825ab4a5f0eede6332d65f3ca5b3022db90ccde7", + "nonce": "5ddfaaee10a4dfd0d8e1b49c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "25b2f4ffb6c23c860f88eb97bc0f25059da15910963a4d4d4ada731f75ddfbde4b4b08d6bf140c342cfd266921714db083927442a2bfed5c56c45f8d6e48317579a718b0ffc1590b3168", + "nonce": "5ddfaaee10a4dfd0d8e1b49b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "deb2e5362bf1b325f3165239138a943f3fbc39b6a36ccb0e9bfe98d2321d6308a6f6c921fdc2776374bc4e967b0bf6d7a249a1b937e0d213f8988af8bd6601e097df66cedc9f07f7d711", + "nonce": "5ddfaaee10a4dfd0d8e1b49a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "b15d463193eabcfe25dac6980fc95aae379aa480b971deed85cc11550daff84bc835580b71d8a37dc5ed3b40a6d392734206c8b31d5f15e70b4beaa046c90b545d64e7e66be53ad80285", + "nonce": "5ddfaaee10a4dfd0d8e1b499", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "5307b7d16e86656a69860247fe9979611ebb3bd378f7950765fefd26bebe57592fc7544b75f88086b6cfb8f53dcd100d05026871e661d9e8c9d10493d486ae81f400f4cf7a52462ef623", + "nonce": "5ddfaaee10a4dfd0d8e1b498", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "6f5839b9683dca37b52fdafd292385f80a70e6270724a11448702efca5ee48a474912e93896941074dd79b94e394ddeb04801ebf682c099ead1a210c485f654703a35e0a72f7e2ce9847", + "nonce": "5ddfaaee10a4dfd0d8e1b497", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "ef220699580defba59db627f5a79811c434b0a79826511fe8e1a8e06ec47959c7d8821ebd7a687bf2f77740b3629c545c7569d6fb6c97b934ad23aa85d5552511658815c791e4386f493", + "nonce": "5ddfaaee10a4dfd0d8e1b496", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "74e80a263b1c880d6d71a7525e6ba39ddf1024e53e32765d91db4924d44baff1" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "697c3732b9b884d51d3a20ce3049cf29b5c34e19b3a9943df9d93a59b505ef13" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "0b65e43e2e6f95a7a1c524afb99fc78fb3a8b1faa22bb0c3c955ef2c73018ac9" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "b3653c71602aaaefd5a664c2301e512268f2f20289e7f268c526dd41a226a03d" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "42426bda8927b8c98e63fddfa045a91db94d9df535f177037c7faf8114eb16ee" + } + ] + }, + { + "mode": 0, + "kem_id": 81, + "kdf_id": 2, + "aead_id": 2, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "6348148038b95c85a5cc10f9f2588090f269aa2aff80136df5d91cb863f0d29016d193591c0260600ce442e4db3255f95458f5580055b2d0e7b61a1ae226fd81689170775864984f69d203add08af3c9", + "ikmR": "0ac1e0b6b264f0de171b33b9fea8b6695c06f46bd5f838fa29cbcae1c6ce1119", + "skRm": "f1f10a30f20972ad29572652176e80ee17d2bd8a259e2b194eb05b8171a7f791", + "pkRm": "9e61cbb1024fb5421dcf61263ab45a1dd7987f214991d52ca43b6592da99ea746457b452d54c44adb90601b142393022d6865d5a04b42e7146d4a69bed3c83c8c341c4816f3408cb502568538aa52b6972e6cb1f227073f828481d187c98091c8b12279a382ba314831f98470a351eba6c7748821243a813f8bc3e0c126fe422c073a06f4f51acada064d0a8cff93655d69900b5924e32a17ebe97b61fca49f1a01c338c9f4be3a9150cba89259086b10184972fdd9218d7887ac706981a68b7d59ac333c4530b859cb9025b3da153688a2e97eb90dc4c73c7336c866525c64224ff5b8c7ee21dcb85af8007990b2694c184525ff0c019b4143dba13a6c78461696bb8c228444a9353b7776fe6a997f9bbbe30731ff7a9af746d78d88b39bb51aa4b8383103816338f1146707a3c07252553d50b54e3cca002369839d673050c0f69f6a3799b676f12b20454a0d3d1cf007d3ad9084145b18c4113986ab0ad2098c065b9266a8a015be7238abaaafbd564ea83ae4c238e147460b1268731d46c964c1af35a1d4ac56f1888334c73b7032c0e414a2ccbe43f89c1207d0cb25b348790814d70a9ca2b44658ebb50aee329e268abc620a5cf74610fb1a1b551a12e5ca3f1c220da4a9c0b4657f09abbb9d01c8c5766941577328633aa36a2aa788a819a6ac5f864034c1a9609125849c72e8c6387ec1820929a0189a8c7fcb20424cf78e7bfbf84b2b8485266d260a6e02e615a4a8fec3467163995e4a0e27c0e3ac5b7715b87c016851ab335d2b34c487c6c4a6baf5777c979e134ec464e7c7430ff7514c720bd4b340addc04b71b083b445bc5f10953ebc9be7941e6700690fe06e8d8a116b7096b08931771376ccd8ac6774c31d857ee5e309e30761e283ac09705864149c0ae4308c02864bd1b2190a1abce71f9a441dbaf3a87fb29b5d97349ed84297d0951743323a9ca97f9b6de720349fc63c7fa50d352431f6dc964ce09220939e0c8167db8ba6d97989ba204514476caac1459394aeed80154480741c813fdf60b5669c9db51a6840789a858c5df6d339dc86c2afca91815bb79488c3f21a9ddf432b33178956f374b2e4b01b6580f1810028618f7de42f4b52b266d9569e4c3ece4656b4f83dc25b7c7f05451736c8673a11a967500e9894fdba85359935a60a234c955ce9f93b20c64f229c66b6784bb6968351b74f5724c0ff6ba6c8e007e2eabfd3c5563ce4afbd120b600509ca661b7b1609718c7ba18c790f6a731b07b917c78f44dbc4a3f81bcd70292986cf33023cdc40014c33012d0c8ac0580fff60c7edb5b52a94582be5822e745054831a7a1c4daf11030145a50c69364a89c32215754fa77d0724ae92d00987252f19c5041304b5ffb835e9585787b9927ab496c3751bb4a80770f3b0eae62334f40db9830e8514483e847bdefb9999a08c08db3b8d9a82d7372ea54095d1d0a6d16415ec3a378e58cf88eb4198037a28353b0be221fe179adcd5527ff9bf3457121fec3b5fe642057b9facab0b03903474ba50ce3048ffa20f6fe30618901c0a241fe4370ba8303e7a526681932ec5e980a3eb162c028ec7c939fbe3235e74b938d31321d7906b85baecd94ae3f915d1303716a924ae611c97c5b856551785f31fc5a686c6d8ca495cb353bb6ad8281cfc9913b3a396550c7aeee90f851ba9223b00dffb4860b6951d202eb4068b50a64fa0275d6c9c514e1140cc6339e49a83fe895920803bd8438df470c568a23218b98a488623ea9a6809ba0610e7ccf00195e5f204df487631d609e3f24a763731bf753ba723173e7448c2025b4b60194d21cbc1eab61a346566e083db1a9b9bb259e36b5e7ce070e7414d6797a9b24c524436590db00198c136873a1799babfc4c87e30c78306f0bb9cfc440153734d33a8b6eb5731352cc4d75cb6f1b94c8654150a653f3c8f0eb160d8950b1a256e81859c6898a13f2472946927997a86bc858e41b5a84137caa9dc444a39314f993632ec7c21711e87a45c9a0739e0456c1ab74a4c00604faa601534978b260e631a10ebe2ae268ac31fd792eba11893f1ac28356808351293c717d0196234cc198de3c3f3086e08995adca62a24b69b9ca7bb53409e57c19c7bb9a062c80c56e67cdfc4c529355620e63a0d7567e14404b76a20494cda2bc2e53b66550dc99142a125b4f10ac9cb7fe990c6176bee2a4104d06403ae9d140541505c081727e95c2c794161df56c5aa10f40cf6b1aa471a9cddc4a8bc1b980955ec743415f38b4f72e2dc9ffcdf8240cad77957bd5965c49443235e6dd97d624d561a6c81e33b0ab35ba0ad9a5455f3136b3ac590d1cfe7c6", + "enc": "3c7ac781a006bca477854486be194790689fe87d95dc180ccbee287619d392f840faa8b3ef5ae177021049e2f7beb266ba6319b1019cf93b7693afde54ade2f9b6d5db36d98468322af21bdd0696a8f4ef0dfc0d234712c10626e251b2bd61c75682e83a79c0a16ccfe9405ee8423fa8feb6008dbe9b2c0ef8a990bc15f6e5f9be700f3fede382ca07302dba47d2a41f5495feca52fc0ec62d56e44f7b9765fb57e8c575c477da4be0743268d7c8cff1e5d10d3b5a6af2219d447cfcd7c1a818fda687873ca98811c6552d2d5ba3e0ceed24081516826aa35b0fd77b05563e318e1c2919f0f458850c6747d6f7ccb86cf7dee21ecf003bb7753ad345d98c2bfa1f2895208c2e2513fac654e5b012f2b62606fe1894feda99f55295a9f581ada452385e76fc78585e432284e4374d4472454dd68e14dad147592979b69c200c7eb7e4fda53d65d7c90463ed18782dfb592d897abdae12f0bae774aabbf89fdff8bdd9b6ae2767a97c6c8d6cc19612de4336b8012b50b7030b31cbfa5809404601aa98096f2b8b2512b0cab87bc8d261f83e0fd4a40dcd0258771d2484da0eda3e60cc834ce92a5bfd63eada6a9d0ea43df9f4740abcebc3999b3f900197e119640a86d8aa5b31e863b5b0c92fca9b7c9a537dc493a70a8f19983eafb25efa03560dc64ee7860b789a8bbb21c7e5f665be4b33405943fe0c573205062aa83aa8495d603c3316aab816dc7c1e6185e5a1999673f461322898b54159d8b0454767aba6bc020b914494b615a3a3c083d4d1ab568a635f7e3b67ecb7ed92a73c5026b218a1822487f30da0fa16885abf2af973a696cb7a46b0bbdb9c8e045e06fc81bb64464c50d1dca71f3dbebd191806194c690f2c16754248580373ba230da2e09d4a8bc5f886b0a53a1c653dce64d3c02a962c5a8e929bcbfce673ad2428718e2564655deae6cae4e65b235c29e9ed615e8d4cbfbc3412ebd5cfb8b90fea91d96b355a1037602a30161dd9c8374b2a986fa4482991c1f33d02d505be3d496e797c2cacc5e0587f3ee5c0241f430a9a0d2031373faa21533e34e03f230326f092604b62eb024e94fbb503df15ae9435f8134cc67c970204479a140040b461badf393e8d77c1a7562628df44f5f9f0e3b182307132764ae475b37cd3ee8e313b9630418c522bef06ea7643ccc5c00211073335fdbc084e3d5a142962f1bca66c0f638f6d13a580e66fb878782a8540b28fca9fb57300ea4ae561be3a2c95bebd51a7777545df8b93aed396e70135048e0a8bc962993064a8a3b8bda7d193dd7540c05841a8e3615d081e2dcdc26278baada99d3e128aa94d1a99ce3c4c8e483e250409dfd8a41044db77647921dc2ce00edb27f5291ca273b82caae2abe8bfe290e7fa087f7b7094faf32b3b6fcdbca61d8902104e1c19f2d92e912cad7129c1d42936afa10f54b39a7d0db3c67f7bf365b417cd2d8bf749d022bcec9a6592db43b06b28da0516e97b7ee7dd0cd9896a4030ecc77c4cccc8990d97514b43f132a5f8654f41599ac1004ce6e7a27831b1bc816ec4184bb6e023c12c88e181cd216670dd9aa779474d1b533d9908492922ca7ad778eb27c009304abb6e9ce85d3aabc5a523729201954f05c5316fc530ee69bd502d428d76ed838705660cecf87ae7d0aba0f348270c2d77f5c16a5dce9dd69adb27fb8a0c4dc988de3002b3e6df34ca9674dce43d3654dbb5bf8d727f500729a7ba8c1dd65e9e8251c8aca6de2b7027f751735f63bfc356054ac989d05f13f93a298fcbabe0ea42b2f35c53d724fb35163557e1da76d67acbd39821550f1d6289c6dec1a7040af912ce34b80e16bdcefc0f65ec6451b65c8a971c78ac6a9df6c2c6c2bf542ae72038b43aa481ba99c47cdfd35d03f1119ae4a3933221ec8303fa7450fa7b27a69b5f2f2636776757d9cf02a167e387ae0916ab2323bf4a9468db125a88e47938d8d864ec556a2752345cd17ba7f6bfd5ec2d47bc598d9b4771b0f5b6cad502e65954b498d3afe51e541c50f3bc3a0a728d97f3398af83ed707500f8441127d34a724317ed87ec6d47cbef9f6cde81b098181e2ef4bfe5ba7476d604bc05c98c3dc0ec6866ab5fc749552446028f630edcc49b1f24adf18f80f9b8f295c96c29004b856754d1f585162033216df34e926fe59e1350123f429f9d6d42e62b1279c409ddc7aca7f6774dd0464ccf6e1afab9943a483a6ea316f4b81a1ea11a3c1630c7cc22996bd975f0e870ef7a946da29c92e815ef004db3cf45eac7dcc4f3b52364e37ee2e09ec90a7022f709f18039f119140e02e919894a96a74f2a8c1c885c66c424ad6f81263791a", + "shared_secret": "295f5c336824d9726e2d92b0f6c4bbc689038071ac6a61bd9427d6779e5ef3f6", + "suite_id": "48504b45005100020002", + "key": "30875ecda9168f62085985807a0792185babd2da480ec2ecf2d54c4fdab7e54d", + "base_nonce": "9860c77b82a05e053d4a27bf", + "exporter_secret": "8c9e05ea5fabd826b79fffb7af5024973728298ae7246b9b387333f5a26996cc2e203748fff2108dfaa79e71a236e1df", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "58d7c48ed3f702c537ee4329993917013a02c4bb4c6d859cf2a8babfcab3c1837af507b25ac10909742c0b8aa5f664879b0cce8714ab264767cc258514e950058a8b9fdfbaf4d00c5d19", + "nonce": "9860c77b82a05e053d4a27bf", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "19d81fd364870a7e1d0749937209fc9e7ace7012f6497f68ccc380fbe0a39a8309d508db416b27335c0e1b3565b59d7bf00b68dfd1cfedcee3f3225a6edb52478ff5a6f0254cf61b4795", + "nonce": "9860c77b82a05e053d4a27be", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "764366be0d358ff54b43e609883fb83812692e295644606730978b0e1e9291f46dea22e6a2e6c0fea485330487a4edc3a166ff0e7f0c0869122ddf6f15612dd3fd17c203ded1b0cb366e", + "nonce": "9860c77b82a05e053d4a27bd", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "773980d14bad114e718a0f040d15ca433801778d1c6b16bc59029d759f1abdb9ce2a1249925dc4607a855015b3e5e812d03dfe5abb9724052985d5071cdb9b0193a2ef79b5644b80810d", + "nonce": "9860c77b82a05e053d4a27bc", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "af6dc202d8f066caa06db9982ce90172fe3217820472255c6fa2c5ba6b105b4535f4c7aac75ef9782d0397d834b51738beef8a126952066d42d931d72509da5939b42b205b5a67413f28", + "nonce": "9860c77b82a05e053d4a27bb", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "c531fd42c65150792a4ad66a21da4171301c15ffd3cb5db85f3b745f43868c8e99a03ca7a2e966cc7770c4d51f019bf7e93784f526af31f3432ade1277feec6fb63f7fc35b99e4810e79", + "nonce": "9860c77b82a05e053d4a27ba", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "3fe0aee6591dbba81516bcb614add1c2cfd9072a4df0b6cd58ca212606cdde8b1cb3d4501772f9f6a936ad39bb62e44d7dee15986995e2158e04467dee349dc21a600c12c9922f9f0431", + "nonce": "9860c77b82a05e053d4a27b9", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "8fcccfe513c0886c6177d59eed5000f6c1bd3ded70e2be70de011a9eb163186f0153bd7fed25f8b5f0dad1ef3cc72ed9f5866b4f90c96ce4a03262030363d3b851b030d88bb7c40a33f7", + "nonce": "9860c77b82a05e053d4a27b8", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "c34ae2512bbc83e78d9cdc96a68ac456f3d8b436ccbf0aec3a6d06a7f5d5eddc2b73d830743eea5d13eb1f6fb0afd3989e6360dfd0049ad9f1c27c914bdd5fe4a60b46e4bdf043bd9ac7", + "nonce": "9860c77b82a05e053d4a27b7", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "6931419b9282a4a181fc54209c9edefd1f4476ad8615d23370d9d1bf1ebe54a5cba33d0ab63458a28c262b6f6ac5b88f19c93d43ce9881d7589e0e3c694c4c07f85036e1925d9c97e1fc", + "nonce": "9860c77b82a05e053d4a27b6", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "80c72970a944788041845d9e25708627692c7d3f0ecd1f4d5062a0c279e18b7d" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "2d0f120a1cc74193455f47271da31b149eeda334a84679596734f2f9eef043bb" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "5922cfa1078c62a13067495acaaaac8196e3014712e09d24a105d8c851376a98" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "36e99dbbdce27ce4a71bc6ad691ed0936d241732ac6dc644979cff03f8eaa271" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "39c659546ea345a8e45cd962403c27403886f9d5ad79614ba4cbca74f9d31e25" + } + ] + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 16, + "aead_id": 1, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "96c7bf099d3c15329e8d2f2ec6415f0e2b0dc8ba891e7674d7a3b2d2c0ab5332", + "ikmR": "a7fd76a516c362036444bcfdb2690221ecec758eaadb3ff279478d29fef19fea", + "skRm": "aaf50bb090817310c6a9616d9f3ad0532114f7e3e649ff758c372afd41a5ac72", + "pkRm": "0466e73549bd3b77560153bf99aaff6657adcf4ac69c49d9e1645806ad13e7eb996ee704f53fa76ca2417f2a5f8846d260b399b0b2fb590638b74b20c6e42da032", + "enc": "047bf609c4e794449ba692975449c0a05f6bece9a113d1a9fc4b7024a03bda7d28d022cd9c91530b45de3659189aba21d5144aea491c7edea1de1635d06589e9e1", + "shared_secret": "04ea1f816264101eae8b7ab26fd5689e357b41fb69facb32303ec68442277326", + "suite_id": "48504b45001000100001", + "key": "8148293af4d9ccb6a3ea1116ae1bbe7e", + "base_nonce": "5055d867d32c17e6d5090d8f", + "exporter_secret": "d43cc0ab61579dfa14381223f62341df5309935dd0e031496c7674e780148ad7", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "7dd7a425170ed146015596fd4276f4f180f506f50f9fc6ac38b817b03bfd62fa95ec802c88bca05bfeda130f35f4f0a3e15c982f91e49747ec0d274fc2ca97244847e5e0c5d5d9ebbd84", + "nonce": "5055d867d32c17e6d5090d8f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "3558cfc695e0997fce70179f6cc8cdfc17c310bfe725582f0d6446acc2b8d4d567ab0543a5b450fdd1fff5c41b8fe883a4d2cf1655fde11007df070c6509ba4678aa8b940660aa631176", + "nonce": "5055d867d32c17e6d5090d8e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "f52759ff0f3cf819ac14ecd25f525fdb8e8183680c7e10dfff1fbff9004c745b1b518c5794547298713236bd122a1d5817cb0d9fd7489841d5ea84e60ce7dd0594c137ca7d888b1bbd30", + "nonce": "5055d867d32c17e6d5090d8d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "ecf73a896c94cfdc906e3e51a5ff5d4ab74afbd8a42c0d7237745c16bbf60d155170ad798cb79ec9bcced2ab110e03640cde0bf0fe7594e514a640d7ed34c9a0768c46a5daf00b370302", + "nonce": "5055d867d32c17e6d5090d8c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "c2d5c74b133d7cbc3fe4c8c84fa41ca41814a3ac89f9ff7101d3ba1f607651f4b24c3fe6fb4835438f7d0657f5aa5ca6282d0c24f3d9af93e456e82891adf1f959b0f80cc680695aba5c", + "nonce": "5055d867d32c17e6d5090d8b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "bda4490582e7051dc22577587aa9745aa88024ca6d0b390dcdaabe42992475c2264b512f67b0146c711cf2b01c402d7756dfeed03429ea661f38d6442363dfba5f621b36a43cd917f21c", + "nonce": "5055d867d32c17e6d5090d8a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "b24a18706bccfa169174a28f46915940d23a3840e08b572552c8156b76bb303f792ac375f03d8179cc1b99101fbe37a3b7349eab6702f803c23fd89f42208800a3b4c82d38062226c822", + "nonce": "5055d867d32c17e6d5090d89", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "32eb0506dd5254921bd2bd78eb3c45df39acc49622093fab57cbffbfca66a80825c64136af6694067d659615ba7a94ccb7139f05b6c09d068cc9b9643a3f9d492b8e2c579d6d24fb0641", + "nonce": "5055d867d32c17e6d5090d88", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "2206f910f3183a707018848108db1af71558e74a370fca7a444f7721d0d312e1810ce6ed9628222bda44d54c7561c1dc439cde4ab3631dab23528af2b212701261b57f02756ee4279c2c", + "nonce": "5055d867d32c17e6d5090d87", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "dafbabc8c9f3729bad9f55d51da0c93b97943641672252181ff0e7e8fc4362a6c781edf45b1c4457e9bbb8e76c789fa02993b39d7fafbd76a36fc16b2ad118b9d39362ac41960a9889b2", + "nonce": "5055d867d32c17e6d5090d86", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "6c8d18456476bdf3d7ad7e3e714f27a4cedf6918c0084541cfc554fd24df689f" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "6aaedb9b733dfed62e801dd0b98ac96d51aeb550fc7242835040a6194b2da678" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "af32bdf3ec4f880056897abd9b370bf33655216ce09534a991a9556c5041a74a" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "894d66236051daca86d63aef0418fa1819b956693780fe7f0b0b8978631a7a1f" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "af90e62c885209b6b096b7c6cac281f6300644baa8384e48cc5c31fa86687253" + } + ] + }, + { + "mode": 0, + "kem_id": 17, + "kdf_id": 17, + "aead_id": 2, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "a7447f62f4f6faf98140eed3531f3e3bf2c8f6d5e2fa2f2c56b97f3dcc79b695417a18b547b201dcd7d9b1583124b12a", + "ikmR": "8f51b7b6c1d043bc3fa3ed7a634cf506f8b4306874826ee1a43a50f605e6c25837d683d0db0f95491670dd4af71f37e7", + "skRm": "8970827e22fb4858ac58dc874bc7ec02a171536b89fc0f9ac268c2933c935babf27dea033a71ff11fed88f496a50d8e2", + "pkRm": "04e31383ea4abef5358ffbe602c13ea7d6c906c94c32af863a08dde6f6247bacaf32ae43108c34a05799dbb101a3311e0acce749a10eb5976629fb574bf9fa8f7129fd91fbafd1fe0e1a36cab2969d2d9f598abe586668ba4116ca597436de19a5", + "enc": "04839b259c8318f1f37971a0f6b2634581c4f981c1d93e5bcc2dce977389b23ea39aec3845f5f9265a7632d18914b63f4dc5d21a6b8674d52711a69368a42945ae9a3f101f03847d64333648c03999cb54ca438892496d808cfaf2194390b025f5", + "shared_secret": "3e788110069ce163aedf40839e5c0affbde08a0f739573ce2fa65b05e6a8867b4b9f746ab44dead83f7573a5c176e065", + "suite_id": "48504b45001100110002", + "key": "8e420c8e053254f46b521463478087c5fcc7aa73379854ca76cbe4d0b0133fe8", + "base_nonce": "f1f6dfbdd7553b6e11300419", + "exporter_secret": "88763b08dc5fb36bf081c412d9f157fc87974eae220e0398a84060338e26a7551f399a7656b12435994a9b039d47f6b4f6b7c378e86b118450e43eaa9a9f980f", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "8ae5aefdd44f9458890db14dd61019c262744b44a6bee6fb174535c98d683afa3ac391b7c81ee6e5c87f1c58cc4b50b53c4cf260223cff639c6c3e3215b794ebd6e0c689ab622d9e145b", + "nonce": "f1f6dfbdd7553b6e11300419", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "039d4d4aec84d7c3334cf5541eb18ca7f150a04d80f54322898ec30651be8e3ed19cc8c8df1fb0ce29af73d1f5162048caa9e026fb45d24b551817117c61ccb93f6026e9386ef7dd3f4c", + "nonce": "f1f6dfbdd7553b6e11300418", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "54ec7f08307809f01fdf02a1dfea4deeac375de5c75bca57e8c2d4802351064f9b79954546ca91413aa49844fcc74f9037884e946c8abf720c567e264b19cd246850fa5a085e01832e74", + "nonce": "f1f6dfbdd7553b6e1130041b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "c629eca609e2138ba7f6be17a98b00110dfe2cf61939587002793bcb2b431cbfcb4b3a00ceb6de9727d7d11f37a4ceb7514177e631911dd5010050f87d8658612570469155e06315e353", + "nonce": "f1f6dfbdd7553b6e1130041a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "3a8028856e82a11131be5bcd16b68e844957b87521c5b2bffc22f0bfbd9530dfc5c8a7c3329b4979ecb2655f68c73e514d4a3612382b752193ae77d7af0d034196d9b65bf4a5273be0bb", + "nonce": "f1f6dfbdd7553b6e1130041d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "e45f30fa2c40b4c7012310c3a922ad006925a84fcfa03e37980ba4b934fb3ffe67da7686035e9581c282762fa2e6b3bbccf69e52b5c07228a4a57fed01f46641c7d58f4688b45714dc15", + "nonce": "f1f6dfbdd7553b6e1130041c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "1d82effda9c252e242e0f28de57407bf24bc37c39096d1f7f258b297ab4af92af64ff8e161e5545c8f35c8bd864ff5b562743df6f06c782599123ee75b50ae5324b9f360ffa559554c49", + "nonce": "f1f6dfbdd7553b6e1130041f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "e51cdd4887f55c4e58541fcd68d783845d39612852bbba0fb68891f86812d0cf2a1c1bf4924ebbf879f07465f7d68ef0a706b1071a1fbb883611e9f72139bfea6362025517e2a5178df0", + "nonce": "f1f6dfbdd7553b6e1130041e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "e4444a038a275cf90e231d899444bf40be60e668c9a78bee4a2082e621446ebfc6fad989196ae383233db2ed95e5b43f94f8f2fcdaf488f4d81e6ef6c06cb312c8b1a0e31eec304d597b", + "nonce": "f1f6dfbdd7553b6e11300411", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "5dbd05ededf89d8eb21e87bd63841a4b6fa4d9dd39a58d0076a5d321b09ec76bb392ea18585a6556596ae95768c4028d0cdd52f12296eac1fd9cf2a40021f014639465c4c5d3f0f777fb", + "nonce": "f1f6dfbdd7553b6e11300410", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "2f37cd2b477ea838ac23f1ec147ad875febaa1dd6d40f2e6f8f8b7f1ffd83aaf" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "5739f7c71e13054582deb5f36c1b492a1716597ae85e9bcb3b57f8fbbd7cac20" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "5e42175487a19530d1526ec95a1495ddc3b84c65beb59e1af2956d6dc31c64e0" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "0ae95a4fa9fa5e65bc8c4ec3215ad92b628b10c8aabd39d478e0ede1214d6ea7" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "4dae3c1cb648e4ef417b5234a3451a7afe5db3b97759312cdaf700ebdb921c02" + } + ] + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 18, + "aead_id": 3, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "c06b6e86a54a949ee574b3a6c825942b1f25a53db4e766514f8992a11637f2df", + "ikmR": "dc20bda0ba90accb76c2cf8ef6af44c3f21bfd60884cd0f502459c48cebc9fec", + "skRm": "9c42767aaf46eb76c3432f8ec5d7a5e4730dbdcbd336e55980124b01c4ceb279", + "pkRm": "ef8f6e2fdaa8dfdce94c9e02aef1714c1cd80c0a1fde4977aa57f4d1b77d5d39", + "enc": "16881517e796589386b3af6a47d6273d7f31bce93ebe4ba5f715d288a9781729", + "shared_secret": "c2233acd6db9f7cfc6e65098b5b1f755fd3f42a94e7e8a26e66bf03320727d41", + "suite_id": "48504b45002000120003", + "key": "515da1c0a943594c2f9ffd5f09029c3254ba5ed8563108a8425fed0467f6be59", + "base_nonce": "add4df506db477afe9e0d01d", + "exporter_secret": "85ee7cc2542f4a44d1ed595ddb3203336b8da8caa9d7e913145956e8ad7ed0e4", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "db1eb8d49ddc1055bf036b8571e865347905b028bbf5fc4e805a6245ba2258ee6a44ec44898ebac911cfe9101730b7ce010f7ed44764163b28fa5f2e805297a467d1b3911d234556e0eb", + "nonce": "add4df506db477afe9e0d01d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "bc53f3a9dc0b0cd3b5d91da56730f393b34ef7287d7d4472f83aec64dbf18e8d49c46e097e2c001eda6595249a95392d2efb882c9e0fcf36c52315ed593ec90bec066397646176be4bbd", + "nonce": "add4df506db477afe9e0d01c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "330d90da5501c07c4748cd294d5efa6d39c3465b4725f69cfc68c4e5af1d1eaa5746042bbd609eaa11194b4ff5c006391ec6ece1e06a2f6f78740a5e77b5b81e07afc659dc77d5324e3a", + "nonce": "add4df506db477afe9e0d01f", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "ed353513e6992df17d459952e9f542301d8f49a9b01b0cd38ed349cecac22196a2bca5d309806cfa28c709a91309b4811e0969220276527d92a5de75a26a9d7ffa773ff504010bed60c0", + "nonce": "add4df506db477afe9e0d01e", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "023065b5ec334e23c6c868b7d6fb924d8d02c79f3428fefc902d634284cfc0a720186cbcd42ce2087125938817d76f6a993f91b0f03e219007bc804202eac2a48080c29f60f2cf7b52f0", + "nonce": "add4df506db477afe9e0d019", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "45a70360fa9b62de65ddfb834ec16523b031336dbcfad3f9a53217fea04673bc7cfb60c75913f0d8c7104a391ea4cc04e7656eb5512c0e8697043e59993764f59273b13f98f658d0bef0", + "nonce": "add4df506db477afe9e0d018", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "fb0b5a138185c14b2359e3ab40491db47de4febb548983cf3b1e0058c3e089f32e1712aa001418c69c15a1f8b511a278e51fd0285dde803782c48ed0e644e1541bc395a2906de8b60d8b", + "nonce": "add4df506db477afe9e0d01b", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "7a3da562afac770e456101d8747eeb97d83d8b38657ce789dbff00afd716cd6b0a7cca62981ab60473840cd5532f550b96f4ac9425785b570b290bdf9d8590c3fa6fbb806fdcb20ebf9b", + "nonce": "add4df506db477afe9e0d01a", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "4dbce315a3acb5599c55345b02e7563f9d729528e045bf2c78026cadb76b86e5f01b86b686a31e6008998fde761823fdbb152631b376206fbba038065e411204caa4ff6788c9b047eba2", + "nonce": "add4df506db477afe9e0d015", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "08f462e26cfb43ffffc9bac6e8345641b70dedbff333b030cdf068ff664eb680262f595911de584b896f04e9dc0c1a800b7328d38f04966ac0372cc34d60080568d74bd66288d2c3de06", + "nonce": "add4df506db477afe9e0d014", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "cb0b6502e374d2594ed5f8787625ce4541fd4908b3121341e20c124d6e2330eb" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "611c82773c6cd693e24b9039791661ba50be3ba679824b2c919a8596e64c589e" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "b8d5e13a02b55ff62601b000904ef10116f77e117fbbaa1870c4ba0340580b8e" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "3fa653d07a25986918a6f5c032464ba49ed7e7dc9e6e0c931164d09aee06b988" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "fc4787633bc77513c5ce119d716184d1369c94598b48aa0c420e2a6c61f1401c" + } + ] + }, + { + "mode": 0, + "kem_id": 33, + "kdf_id": 19, + "aead_id": 3, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "6d2603126151841be9fc82e04f7d2e8ec48a63e1e9014ecde3219b88c9a7800d9e578d6abfcd408ede13ae2ce446d0a0c0dae32ea4ac5a0c", + "ikmR": "68b98ac8cb448ab708201dbda774500d8a60a5a78445e628c3084ee43575db5370ea9d09a93f6c81683d2057399df83fb4d6aa6a848669e8", + "skRm": "74970bc93b6b47ca260c15ddf87f0ef7bd7856cf99cd4896dd30c8448ee0d6a497c78754c6bd2c2745f5da3d0bf395fe2e53793c262d44b1", + "pkRm": "ad40243d93eb1c8e9c4e0ac75344365d138c560fc9d55cc0af77f9ec354f83d251c650188b67031d4bad75e2aeb375ea8cb1bbc1df888c8c", + "enc": "1525ab8ee0687468ea1e4c5904ee1d4d274176d2e5c375dc5b8ef9ddc6999da2e8925c42bb30d064afe4343e12512f65a210ddff3efa1fbf", + "shared_secret": "19f9b9d4c9651b775dca8458b77e43388dbfa3bebf7e0264d843fcd7356e73e31962eb6e8589ab9a110d19e457c480a8f5f5da81e39a6eb1d563abf10a484f7c", + "suite_id": "48504b45002100130003", + "key": "acfe385ea5cc06e8baa39f688957ed69c076c3d8dc11a0f6d8cd38c07ff19356", + "base_nonce": "d66dbdc61ce293dde7e6fd55", + "exporter_secret": "e0a5bf27409e978f82885767ba5d08690c9ad3947357ed5b9c536fad0fff678924f223cbdb4c80d1b8bf31b8fb7b344d30540d3619e09f830ff03c144e89b478", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "66e7172da145177b7ab4d509c51ba797da0a55833ca7990cc61fd87ed123eb466cdf0708845b17f87aa37fd55fc04fe41f349232add1e69e81dac0bdd87d218a82f1f53c01f42e94aa70", + "nonce": "d66dbdc61ce293dde7e6fd55", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "338963b975052d9272e78efa775e461a7d83757c2a72f33dcc031bd1cc064b1fea4fc36badb18eebce87a2ab33fbdc962f8808a16fb9e507083a020f38099ae69912db44111d8b669068", + "nonce": "d66dbdc61ce293dde7e6fd54", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "27c4db43a0f33b789d68352e8a6c9c4321aa81a4162c274924f5adc917f3a66da2f1ee368af4ad23dfebeeb155c96d10ac007c7ff60a37bbf4219053138c5f337fb206c3088998a38f0a", + "nonce": "d66dbdc61ce293dde7e6fd57", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "4017721ef2415f4dacc2947f68c634df13b733afbf862eb8c637d5aa14feadd2a305a6a9434b4914190b552e5d94d7c4f50533d0448fdb9b035e1ceea51f9e01e807408b5ef4ea629d08", + "nonce": "d66dbdc61ce293dde7e6fd56", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "c865e2e84ae0d4f34b1652eb2e04bdb3add6f659b9a5bd251208c398e46ccf6037d302a683a8473da90dc61fe2562944cf9ab7cc955bcf971f8dc831d580f858dde854c84b2e2e91ca7f", + "nonce": "d66dbdc61ce293dde7e6fd51", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "bbd8691906d29fdf36f61a85397a73ea991d100b6b479be58512fb8fbeabbb2157df061705feba2c63e4e0867f0317db4fd920c900a3715beb0c1d49fcd6dbc2a331dd898dcd8bfcc7c9", + "nonce": "d66dbdc61ce293dde7e6fd50", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "3782bd8ad12af9b88b56068f5763edacd19fd86e76fd2c9907c4fe7e0cec15840ef5fbe5aeb7c238786c89a9b807259246e3b662c34844125bb6c926dec86a4a911449858d00695d35f5", + "nonce": "d66dbdc61ce293dde7e6fd53", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "09fdca1fb6811f62f92c846f42c08c9a24aefd61be882598f9fdb127f3e6ac71f8f33d8289a787e076912616b2592763b36075f7b50984efc0d30a1de4616ad2483c7fad2b51f4c239c7", + "nonce": "d66dbdc61ce293dde7e6fd52", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "92767e6bb671fdcca73dc06e13c04aa04bc3d9d8db6d58861dcc63eb12205a79cb361c328fb0b70251e7023d0d0b9bfbacd9ed9f5c8e2c3862f53faad0f2b49983c52763c120b49439de", + "nonce": "d66dbdc61ce293dde7e6fd5d", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "6a2f40cb89b98400183bfab1c18a72892066524ac1186fd19e24df505f421ad830d7f2339cb683c81b2133f765a17eb5c6eba734ad43d57da547313c3740a4a7fd2047d4a71626f3f38e", + "nonce": "d66dbdc61ce293dde7e6fd5c", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "294aaa547f92a75388115df08f5ed0e71ffdc775d179b59403802317a890422b" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "abf0e0554616c30e3db681486c7f9cd5cc9ee5ef53fc42b6a213e2e4b5b751cb" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "e2a65d82c10d6cfba493458fab961eb200c9d8ec46659f39fa9b23955c07d123" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "4efa1e5d10d96e7739701f475415425ab96dc7b31602b4d17e8c71f4a6be053b" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "ae05af65dbb4ad6ad4980de206f2697c9ea85cade602f232bc0a4a79e361ca1f" + } + ] + }, + { + "mode": 0, + "kem_id": 80, + "kdf_id": 16, + "aead_id": 2, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "921de292ad41875cdf0d18b80b5a70ffecc4ed2ab70a5ffe2c5dc6d852a4235c572dc13c0e09a93a80d470ff9cc7ef24d2bbb5f426384e021bb606a20c1d1054b81136238047e707c501e376a3471a6364e9c48a7fa4fe4a3400b7de42d35196f4d55db218a77f75034a051f056eeb978251381c25637786c478ae4e6f66c570", + "ikmR": "b5f7219caa1488cc677386064255e6638f60f66d0ca90c8510aa46e908b92fea", + "skRm": "97981e2761ed8ee8ce18b516d9b677fb13466f123268abccfc1cf2974fc9ed7e", + "pkRm": "86402706266c010967751a03f6fcaec78162a3160eeba56332c275ca139e1de9aa28820979566104a89d44e389b5ca0198b6216ae216c8092dea727af816a45b4367d746cbadac0ec2740bc94092cb694c50c18a63c33e000c4ea01724f3264620f3cb9564a56f1254e6a99b27212ca701281677c1030c15a11629ac8b82fca96104124a74164a17a9385dbb22ee758e7c58bdf9a0420bdbc18f8044b19c77e6e88bbec43fffa6600b14150cf83c62a98cc46c95cca4c2b0121ab95a9a5521110a0a18a554cc5027761a53641dd087550b0a34396d8e9a0dd81549df90babc7983b309460dec9b8252248c49a50c79c6d2015c8b288cce4759d864575633148a643cd014658a6b7303262d7904c190649a85e69f5c173f1839c208911bf0231451d3398fdbc55329b250261eaa70898f31a9b027abcd4c057c617827d247ba181f7cc9b435489eea803656765737b7c56015af4a7cba4fd5bc300c0a92a24d0ee74aed3495bf36a37cc0ce1a0762b0568748c2b7c51c8fa0f0aa7ca590c0ea0efdf00f1c7476bb7a0fcf7088b9cb7bb2d21151b96b8288030cca55d41abbce1a59906293f8110b5241431d71a371706d07592f9ac47e2ec33f18a4c41c8b4c7ca695c4665abab6c529565479313220e18797f80af5f64444d939b0f1161cb091ef466f3e04bae3c9b1d5e0af8d9c733b0059bc42cbaaba9774a7b74945968ae7b0652b5f6e9bab39e341fdc8641e3c65736b415138342bc593441539601aafefdab23332a16fd12e146b6e6bbc46eb1666a608786e764b7a2a4ea033ba0374cfa9919f383c9096d72619776f9a158f39c318d90462b58c9bfe6cb4d3b252bde61f9ba753c1b7b52825473a51a5719c57969b9c10cc4db3361de3f004562c356585839c634b4d06a41396951a66a43c98cb235636e24c9abd2bb5c217c1a67065cd062cd883434622afcf50a1bde7ae1b9a134002885230830c919d00507421dc7e21051a8228674fcc489bd3af29a870c5db5ca3819ebed5c0a432699b3b93381665b1e7bde9c579ff907cc622933db22e5dc826699308349112ec87046fb0517b503033e7a0a00643bdf60e786cb74a63683064667bb3734c4766e652c15673599a867c9dab4f3d827d926609055aa8fc870462691eda085f0c2ab171e23d7b982610797eb8ab5f00da80daf9ac813a38307a09e42640a6a75b6baa9c1b30793a513d8593103694216a6768063a9c55037c739193e9f70d911b0806c9c320442ddc357c16457b9f2459a8724875539945721ed87801e72308a8ebb383b324e7da0fc4105248dc2a4064131fe5120b3a9ac6f86ac428b7208887774a3f53212537191b6096b776c0ce175862b5fb545e66ce97664ef9f3071b476f3b70c27b74777e95953851b1d88a59f0774387588edfb7291a630f09f716084acd6713c5e8a579c4c6b74a93a9eb35ac491405af6a595707b178904340a80273c454023690c85b2f508b5a988b9eecd8143bc3056626212accbd756057f5d998bfd172e022b0df085852f30ac57584ba9190ff3901c0c77e5e7c3f94f4006d700d9082bd79b0a280b60d6efcc142eb65be80050c0a753779b99b0183937b418bf8010149bd84ad2ce420d5c33624fcbef2d0036ea77aa6eedaba3c3e2352462361dbb6048404cf06ca698f8bb23dc71f601251990cb32b4a3e1d54b153462669752d12e4a905f82252fd9cc4a92ae90374e911b29aa544488ec5089d033e72c94292f198f791", + "enc": "a6c234b8590d0eb310f48bdb90dfed980ba6efd4134ac8e0bf09eb9a6b9ab08e603882e58b5c4edc9a474a8f65dd7b5c90fcc9883e055b4ea466f085f75e528c7ea0006ba6c2b68678b233aa7dc73b3c4542ba82f05852ae7c92e0749f2f99a79a06318e9bc71bfa15fe38252e5f309de0b7ddc7f408046ebef97c7310503505910d92bf5b6c3709bdce5f4f9434c32599798af171db99435e94316ec027e2e29ff3985007e0b81941cfc37cd4623e3c2a06f3761699420dcd4d99b43063bfa91e24364c8b81ae2a6c3e7eb693ac52d5e29c3db05fa076f14645280453a72508e068a80ce5e2dd8fc6f187dffe96d3822b5269116d3c86e40135518b4890dae0a862e782642f3f5f3340324a4319451aa1fbd4c438c0b742151a6ac553b0be542f594e6f649895b87ebae9151ddd99f9eeb4352b04343bf83f7dccc5e87917f3d9f1691f85381bb923da7a1e32af7743960398fff21b924b3cdf165517b794c399368c48cdae947bfadf5359f54a41ae7c94ebf11bc4754973471edeb8b8f4304736f40ba1b443bb7ede23b6f8a1dd7b39e6061bf24325af854783984126565121e0100249c123c5ebbd38e6c77dac2f34912493e800619d49c1d5a661b57bdf2eab69e6bfb4348555e984d6c273c41892add8f84ddee96a61ee0f01d17edad5634b9394b2d77688e4e483c0c3181892abea43e101ef8144bf43f9e188c7343ae2de211ed628666d7a9e61db7c17db02a6a640f74ec56c5923c43b95f72bb313586a8454e810201e9d6ff0ce16c598d6fd2c1c6a2c73eccb0bcf81382c5737a6efdddf55a6f1d3edbbd4d4dbefb0885299c30dfe2cb93fe926759a922e6367d9c3b9f14484513ee45471af433150357cf91ebbf3e09a1373c1392be2a117cade16e493201e4e359193de9cf49334b3d14cf0f54c0f7c3e6619e23a406ca9127bdf60c6efb2df47cb6d7e9bef5c19b39cfcbef7ea5683ed8974bb6eee2d4e676c3a37427990b0e70a89f127365e1c940353f210561bd0c2cc957378316bc38e4ff7d82b731c72a7655e4fc67746bb43241a481ee1f1d37f03dc092cd6d223225488b10d89a39a8578caacc581267f2bd827a51a4aba741a2fa485273a302bc953f73ebcebc31a1f8403946eb4c72659d00f56256f8868ba18e01b435e0e5bcfe573e9a951093076e7d38c9559616c2fe85ff3e5480c81121acc1dba52c0f6a84a8f04fb20a4cb318320468798a52740fc6677a2515a85e6824750584f76fe60e874fcd56f94228572d75d9776d06b8af10875958fa1c9fb338cf15480008228ce4ffc65f9989c474e11d5ce8e7f2d0e08b36a5ca7483641305cf13b44d25848acfff9aec140348955843b270155bc5a06c294e3b8851ed766a8c82782c003b8190a761b725eefc880874fa9ece5f431d459c0c9965041ed6ffe45884724d81dd9371df2cab61402762017669e0bb8e7fc2a88cb5926c7ef3710989bf0a9f1fe57432545b36f131195c2c7550de7c763661a29887ef32163cb7be0db850e4c238f044cddfcf2b63c511502150c1271ef24936686161e2b1581f9ba9317d9031f9f6212ea33567ce6c24251cd8de20494be772dedceb91436a749119727d373c220e7", + "shared_secret": "d429a36ef033a91f0d903b5bcb0b1a9c7e35ab0f071cce04e8e46ba60f5a1d44", + "suite_id": "48504b45005000100002", + "key": "d1f04c59d173d7f0c6b0453ebaf8310b75ce26028dbb6714283a8654309a9905", + "base_nonce": "0e06b572ff5668e108569efd", + "exporter_secret": "60ae531b37a85f374827b7c1a5553548d6bdff998ff949d2b7a2df58dcb42ad1", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "04fce9b3e43bb7cede542dacf54e08ecc47097a30cefe707c9d8fbdec5f67ba33121a0ffed0a68abda27a8b536d7cc5dca6fa8e493c3e1c5106541ced45e52c8f69d333b0fe82121950f", + "nonce": "0e06b572ff5668e108569efd", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "1a4e0ffc70cc4d32d31a782c4d053c50470bc9f3a260e687ab9ba87122879e7fe90d39382d80431a46c9ebfa7243e8a734eb58896da596a93f0e769b5ae9188525744ab070f4b55c8dc3", + "nonce": "0e06b572ff5668e108569efc", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "8b1e7cd26e9e2ee87c2bc080a8406a71991ee71245317e2a0a723f55539b3fae0cf0eae18541773f165a4ff9e645fe1e15ed93603676e9991e499d355285cf7b8d646ad082129d70b8f4", + "nonce": "0e06b572ff5668e108569eff", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "73198cab9cc0f3ecfa00b0ff0fe669ee8f1facc18f81d4d10d486510a72f49ed8d9452314e56022c5d3a1f17f86fdc718de1f1da0fa1c263f324892c87c12005592fce57e903c71a99af", + "nonce": "0e06b572ff5668e108569efe", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "b9eb8d6ad364db67cc978a92440f1dab5f7076363ead4ad4f8f4fb7036689625f94fde6b574daab8186d5d352115f664ffe947f31d55361351cd228241d3bc48e8d3d1a7689e67b6477d", + "nonce": "0e06b572ff5668e108569ef9", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "f9407ba95c6183c23ba2a046049297f7fcfd9b7f291274f8bf693ff9221d90f8dfa0ff6c4b1d3f98432819da62094003e7396cfbb396ffa76e2131d8c8d181629dde3b165891518f91dc", + "nonce": "0e06b572ff5668e108569ef8", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "3fc68c9b7b31938f47d730febf38394c595afb19e5a42a776570fc1c66e0c42042ba546d45ca7da97ab3dbf86a0626cb159472f212af91a82e2c2d250e61b5d0f39c16c728953bbc1ab3", + "nonce": "0e06b572ff5668e108569efb", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "3c23e0b92c2bee04d35649990e1a99754eb937ef50e71e097f020764e4410dd8e9aa44e484b5e6c62e8514cd4d0aebf48c45b08819f88425f7d1ec070a923683da453c7b2d425d213c63", + "nonce": "0e06b572ff5668e108569efa", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "fdf95a33f922fca1f1c2aecf70c1318eb4732e89dc54f8567cdd69b0a7661b2189b31a64b06a5c423b4cc78e4106a7d3bd30da7a05a9694ad6ed13ff543e119fdbef246c50cfb19b5c8d", + "nonce": "0e06b572ff5668e108569ef5", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "360a32e536bf5178afc6c676f0db58ffa411a2182251b277a8f4010d713b065e2342771fc9de8b3d2e7d4a5e95a757d5e3cb3c33ffca96c7eed77feab46c7ba09a6349e72c5f42fe8d84", + "nonce": "0e06b572ff5668e108569ef4", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "8461aca597f1e1eb0ea51f9ea5b08002cf6fed3a9c380ad232688e2c7a7d3bb1" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "596fefe88796efd2fffe3926bf285ad0a4b6c126c5b86cee90b1b68dd4902bac" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "b332ccf3be8e7ede848e17c457ffb78afc59257164cd2ae26b5b964c74a569f1" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "b5f87bb01e1918b56a8efb2946c16d7bb228059529390ea2b3bb3c032e5c8318" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "835558ac9e5804543573361d287094e6237c27c868c24eedc1937a115d43eac8" + } + ] + }, + { + "mode": 0, + "kem_id": 25722, + "kdf_id": 17, + "aead_id": 3, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "2c8f82e0c5ce6aa2ae57c5b99b57076c32ef7b3e18a24b82836bc98d9745c9d5113b4ca12df3c92f78b06c473dedd42822408ebcc3cf82838eb793c6272659ce", + "ikmR": "9ed657ed25ee70055f12f2f1cf6f93165e5a6760a7bf6d4c2d9d6028c482781c", + "skRm": "977e67dd1cb3cbe7d2ba07816bd3d3d00f9b57a1c69426a628f4a1ca5ecb49fc", + "pkRm": "9911845091bd0729a5ff90815ca83add7c72e099c0c863164b31bfd9b626043a4b0a3c7b12c4346cacaf27e87a0cda5213cbbb5b900906629367090ac18b9d7771360998579c4236ba94530fd66610a98565f5ab16c09dd03b773e08960f86774b25ce60453880aa36f968965b8249e027317b0b8c034cc6c0fc4fed09123da353d6e12fa56186f5e84965274141a387f0c34b9f61913f1ab157a84818cacdce5c301d4b90068180ec7571be800cea28344e7686c90903737cbfab5c3271d4cf895319dabc6b8f6960206c9fcbd047d21292a49a8668f57d7d3c970e5c33f6c7a031aa97835872d18b400c2198a25105b64a1160a2b4a41b8e129182b91649daeaafde5b00c535006eda51fdf18da2b1bf9118597d9b0339f6240f847225da6859d654b2093ced52524d6205b46ba381e186aafa980f10c2b48034e925ba66134c0f22c9c449834ca3c64aeb30a2ba7e45753e754008f1738846fba70a53047c204ee7ca4bc941360e5b5b7c436d63cb8805f0afe89b611091a3cc4a8097dc3dc1c16582fb77cd877ce0f082ee191a51fa52b9f963c4db588e5b50f5403c253627c0c1b51535a24bcb5050577df039640f184c3a0515fa8a3dda7420164abffb2a7638e18ec08884c270a37b2920a9dabe11062f0434503499987b823ab6496d11f6cda0d10922646e2f32b191435c3ada4b2daac669173498212c1b836113da02e8951f8b3a649d6c3e78440064fb0c51f85d21abc5ab850198273042e48005a730da18635c2aa088d095334126903291f380967df663027bca4bc9ab39175ccfa62a068a9756aab81306bce4938092b7496b4a4eb2704022b36b3c9b1059e0611f086c3ba6c41c740fc49b1aad086b6cbb3e3bb257aaec638ce016ca8669e7402ab36b7f4d82a5a9759517f59a6be70abba022b114cb47566385c22b7ee10fa7d9c58453a87283cbc0c84798c1b5bd7086f06936fda6cf2c009a48699c7d701c6e0945bf21263c939facb1787b05704fd42e66c30211c3b7bf9b65b4bb0f8e487a4b32aebb5740a79c60967c978bb474158802c78148cf12188cb8041ccb0d1a322420150a19878033292cfddbcfd2da7111734f7ed2c377a4b0b1a49bdc411f8a05686da0b5ce08ad7ae25d7543008740c56a385579b16a8701ce83ebb848d286d187b8859bcdfa49b894fa9830581eca7a37fab258642b6ddc3c485866b69976016bea5af9d8395c2cc09b9c0f731b22e6769b32227ca607c1c6c167bff02608590f47e451f69a47bf745b2f86cee45c2347cb2994a78f70e9966cb10a65705dced887bc1c6125d523a2e0ce9de8885c25b54fc4cea0582a81c8bf958acdb283200b649953f9a243d4aeca6024f195cc5f62c4b2e913d2f423dc1a1a2f08c307b28b4f65bba5d32b49d77e68d471302cc2531507ff04bdf508c83d585756dc93bd08cd82d6984ef15c82aa978d00513aea8d7d2b76db37c007352f39aba1c643172c99ca2b334ea51298c4d9bf9c3886cb83353189173f8a225c09601c5958d8a335c57838a6ec5bce7021c081a0ad0a7a7211b93f584b83858ce387ca04758a84a774b4a709c90616c4100d68085323215f66d602f0e843c2871a8fe2c634412c6790376c50733bf524b6c8d7bac81e8469a091c29e66f3ea4ac94fb4283dbc8b2723e154e82ee50b21d3400e90272b58104aebfeeb97768e234968d50a", + "enc": "fa6f9ba3cd3c61e4612e030a17eac4ec810232396e5eb9897c9b7763beaaa4a3b722dc90e2d878ef19a467d2174b619e44ad48501f8894e417c7da658113606ce8c9281ae60ee4041efd415be95896ee6e7b81b4b4606319dc99229967519fff17acc3f09b2743c4d3793d94d12aee939e4375b5c1a93171c7bbc74142311ee6483150b55f785b4d73ff6022ae53e5176da2a5350523fdc004512b315d0021d59986dafd6f1dd6c56b4bd17a743f43a3ff9dd44c917eb1edee00d27c3010fe6adc2d65e243b12c87f8a061b9dd61ef5a9dd6560b15e59745e1b38e35f980a1cfbd604eecf700e52e558950cd6bf1956c7d9af0d88bcb26aa5a88982ca226fa29c4221dd55b465dfe6c3c0c092e53d5cb778676136ab2e0e42c346b84120bef9b7d47e91317c16c2ce9cdc3a342be4a4d1e43dfb3ef59873bad243ac73ce5460d114e2de013b41bf302729d17d101468223adc86b738f06823fe386ccca745c5178c310ae09f9d8c06387baec3268d2ad9cd2bb7ef20e49c0bb1a0d7e4458f29a1c3d4bcf0645a8559087fb81fa2251f44a5653b5af9028190ce7ad24ebff6415dc8869d7d8a1033ae7335f20fdec661d05b126135a666e6420cd247ce081a228dfa588e5366eb569c9546440902545868d9748c920a53afdd2ef7883b00be19e976b8e3785666c2516d2ad1a1423a5aa157487d27dcba1b935e0250a7c770b769446c459d79724fd655a3436131401e04209da7c062122ec1068a066d98b5eea3082fd91ad77c7918e91305bb6e280e03de2dd0f7a7b8fe8ebaa805620caf025e018cc70f0e4d2a021a2b60b92165c8e49a12367ba96feb33773d62fcd6d98f8d2c10397d08f0028e4920c0d685bfe2cabf429132aef2103fa7b3b392c5b1e82f7b08bace4b60f65a64a2a84401179f234fc82bb671302c24df8f2c333e5dcb86c98066e2e0f3ca5fa3690e32ba6eb91f4b9ef20c013b73f50c30aa6f26f675f432c528a53b23ed910af850edc6dd045a2c21336e6cac0cdc828a6b6520396b087d33e07a134f31a0cf421eba121e7132bd6f2e05962b8876fcfb470ce90f7f2519ef7a2c14b84323743518312378904b601c880531894a4a27a3889f72ea5757d0df133997c4e47238a845cc81dd0285f31a85821fa2f743a5b2cce98f759c5c3e00d962e1d059c4bdd35299e70af9aec743f0ff94ea25d3593951d90f0eb2428481934e12b7c3049d1669d257ed758276c41d61db2fc9510281e780937bc04e5affdf3abbf1e8210a11c43b65977eae043b83181a5fa2e2ab0650d224e2f1833f711c6f9eea63ebe416a3eec59eb464aa969e696e3e2e13bc27989b6ece98c049a05b5748c1ced459d74a6202d9d952fb902bca93a882d68b19d9f4090bca812c5081a26c1ad2f2824ffcb024d400e177a7ed266855b8b810c2c0e42cbb46e7b9f0c72c6899519b19f2222008ade44c731d678002533c12bff5a9a769f62075f40318d8fb0f3f73004d41c2b05730cd83480b9881f3e159274814b7e8e1bb859b5283b6df723cd5224140c5f9980a4624172406e5e6f613189f7dc4fa24372", + "shared_secret": "123e5d533b9b848e8a99543aa042a9a28cbae017a3d7730c5b6adcb23dfbc27f", + "suite_id": "48504b45647a00110003", + "key": "71663e55023184f6a4674fcb36a7789398d3c33efe1210ad1bbf4a1ad8aaaa6a", + "base_nonce": "57bd1f0b8f5dd860e69d1f70", + "exporter_secret": "84512f28ef61a222be1cac276c4751c89bc3c6318ee548e713dd940f8e1d8066589b922674736919f42053b03451b97ac8a0ebabdcfe3df67260be07cd57b0a7", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "47178a0360cb65c161cc69702a7c8875827cfe17345d5d6048c4b964010b9291108b022107ebba751f76b571a46fd9357097fbb9a43ee985b5b9d889b364ea02e91cc37d847c0a890456", + "nonce": "57bd1f0b8f5dd860e69d1f70", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "0d03c2ae21f8c7fd487c4f2fe223a480785f3ef89c4593c010ac01bf2206ea68825177168c286e19deff59c7b3fb267b76924e4a18bcd4b92d121f2408750a5b83c506512c80fdbfe933", + "nonce": "57bd1f0b8f5dd860e69d1f71", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "9cdf8ac7423474b4c9e7b46d5e3d9060a87ea85e979065b02dd6d17066a0266ac5769def51f6bff9df1e30c6936afb02557f4121c598e2e95e9f8e4f9b9d7be796776d2b8e634fe0d807", + "nonce": "57bd1f0b8f5dd860e69d1f72", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "95e471af9a80656008556a2504348b77481b0b7fe8b7f8592601de1218e4a1f9d632b662864fcdc933702a64353150761e03c2b3cefe1706909536bb7bf8644135a1a5dd0d01dc07fd90", + "nonce": "57bd1f0b8f5dd860e69d1f73", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "e563176585c627b43bd71ecaaa48d3a3d19893e3c61fe87e8862b91c57210abf584ea420c887784f303051f8b79144d54f469e394d7daaa426747d47d1d62b22552efe80ffee07dd3358", + "nonce": "57bd1f0b8f5dd860e69d1f74", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "a265fbf951b3293f8ce676515a8c64490a8a726f5c04813e9b4db2f6a0e04eda00d8777701b7eab15f8b62ef70b21e5ebe302d4e8fcf748e3878d3f78772637dc0ac07ca9e69c4d6401b", + "nonce": "57bd1f0b8f5dd860e69d1f75", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "195b86b6173bdb1402c8e743dd57b2a48569b121af1d8a6388d62be6f8ce3debfac9977013aa3988b9756ac2bebacd0d20372f3b248a83b6dd81878a109a2ff6dbb08d2175fa5634247d", + "nonce": "57bd1f0b8f5dd860e69d1f76", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "ec5e13eb3e1ba33bd99a634a1b7085ee3402ee4c58055111cec0c3acee12ae083bb0682a48c67d779c9579143987b6d32a927007d71e6741a5cf6d8a1b287a7c23e3d04c1f847c5486dd", + "nonce": "57bd1f0b8f5dd860e69d1f77", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "d2a8554c51640fdcf96d174bcaefa7ed865724d5e830de2a168497090cb2ca2233949f63469749cfcbc2cf72b7ead25ed8ba38e18e77e77b59ce3bbea6382759da95117beb3a6f735916", + "nonce": "57bd1f0b8f5dd860e69d1f78", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "827fc6de9c0cb23a06317e33330bbafdd6d4b4dbbf3227a6cd35e7fa27aa4ab7a5c416c135cc6aad29a9dd4ddd5d808e87f898ca02549dad081d5e675eb530e031df568d6ac3c1a679e5", + "nonce": "57bd1f0b8f5dd860e69d1f79", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "fb85fd013ee7b6cbf28ab09a2e20af5621349fafa549baa292a90d8e51e83cb2" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "937065d5393f93efc519c1614361d8e66131bbdbfbff6ce8d44b3d50a91a1272" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "9c7336c0f212d0f17c6453c21d709907d87c87101f8c18590ee286dc9be47492" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "9b4f7bdef7179bce71e47177baab9a6e4b016fe731c98509710d6dba783f7ef9" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "240f677428ffbb160262e71c96e50dc921b7819d19e803177730fdb0cf543486" + } + ] + }, + { + "mode": 0, + "kem_id": 66, + "kdf_id": 19, + "aead_id": 1, + "info": "34663634363532303666366532303631323034373732363536333639363136653230353537323665", + "ikmE": "a20456fa8c2a558686a231eea685c004974b90f53a716e9cc1716ddab8619efe", + "ikmR": "0278ee11918f9507508c01c00eecf2d031ea1fdfcad5eb80a4f4d5354be66152b0e2ed983c5d27069244dc174b7c1a53b4a4f89c535f56a0d0d80689bffb61bc", + "skRm": "d919b835b98c968e6a1e85a6e7c54be8774df0a4d00775626dea7c0fd0750d92fa2c8655a59401910e2da51f5bf78b2014840fed74753f760ac85586c0891570", + "pkRm": "94986ff91865dceb5545dc66ab563a66b69f44e5a1fc3b070b65b8bca63297abcf3711afe3f90e020b8440c0aee97927e2b8bdc1c3009503bf6ef459e8f14edc8bac14e08b9c9ab57448b49ae185a8572a5d60b1c899c268fc3b6ab357a025ac0d6b00092b72cbc10b6e5194b66bc21602acaf0c718c0cc68e4aaf385a00f91b5cd4b103fb932149a7b9d85a1b87564714b27ad8e7910794618c16a3378692c3dbb3c414ad46189ba6f6b70c27c54fc7153d50a17d9a3f8d9c23d6a96677c01b1c883dd359014409a3c1799cad15b3cf231d4f7580a8e0b369f674a404c2255850aea820f6db2d85d72238a421cddc7502cc6d6b954ace72893a1b2d2067a7fc55351f264fdc70afcda13d22d765a817803dc875157a8065da2545c14a32f6b1621395c375720d0c44f9901af5667c7f83cd0a57783965c9b849701f3a97d5c49de0145b99602e821566e0a72fc517c75e47af7f390633d42f42942c174a7472222c79b610a1a58118fb20dde85a6e7c152dc88aa9c136f9114309605db2a71d0e6c9e31d64846c710c8e83c2dd931f05455950886a0150143a06dbfb2271f37793ceb995efc753d299114dba8778156ae553d555139de082f0fab58e1b2801f852ce69a9d1f7658c447a817c3605c92743e14a11e04b67fa19faee6658bf1c0cc880bd7fb631d6cc0c850157fd011818175715cacbf4c27fbe694dfac8783e4a2b04b13d512a33a836aab7476cc1663a7247a7b0b970f5874d6a87e8682261cb76f2124a89b8b8623fc646039bc2de0914bfa40d6d5137be3926f533bc30477d3320a93744a2c08118b48a441e42c8d6b0da6d810d23bc476e3256e864f1c97132a2b98fe2465630132d3bcb323bc6f9b713cee867b3eb65e3723a8a5c82f90f203a570c4d27b0ca7e82b6400aa6be29ca4736688e826680577a9dba091b1ac6a618ed933b71d6954c3baa10e87834ae645d3a088b324b701c720662949e6139a59636b27b76d4478023a59cd9524c449c5863b28c5d0a129c45367a9a2b922fbb82f7a6f14f0596ab35676d285fbdb01e0da254504205bb65150808cca0968f5096727a00e20e1613764793ba348216b866cca6874198cc058a7a10975b82954a7a2ab5969cbd4eb360483677b779294aa3fed103b2615471ec979003087c201b4b9aa85717c22a1b2cbede1266fb8011677a085ac8e140b9f1f73caeedb22da4225d8676a9e245ed5a652b8d4a8d854b62df62d267c578047941ab8c694d864cc8327435879a7e1831ce0404e8543f8b12c3b6c113fb11a7ae5c84d3768dc88202a12c47e9299198c54a5221585130f2a7a268b38b29c34626a60492796cabdf692f1767cb68c8042868c1f896d0450778e7620f2161d44307c84b85d7c22997fd4414f0b4d5873457b67ab186cc0a990937f3376bb348e84b33b22c039308c6d451a0c9efa57eb681afb2274fb65b605d66344a3b6e8da6428632ad9343dccb54f01b2ad2c992fa03b21a0f8a1920cd00fc0398527a808864ae7a0329272c5b2d6355f174db475576130123108be6e3a4c57c4a35f4c936c7204af07a22f2865add016ce16938c084878d5c0fea2379fa8c62a1a03d464c364448065a01795f62eab904929e39548692255cbc4b0d061be105d995589cd458628d7b6d33219bd1b5d3a671acecb08f7e8c3b989cbd4cb9daec9bc370c02ceb969f8bb9de8fcbbce7167a3ab62e45a46f795624e06a6938b8b9fba309a447ee8e548b3b349141a8f6e9a3aa98453f32952a3b8af2cd91661949ac7536aa5e286ddb9b8237467a550c31931887ebb681e949e886269267acedc9c209c8b44e29ba93eabae80e24022633793b52c836cc1bb7222e1d15d51892cd76b2ec8e0b7c504a074577847b51098eccbef252a103a45200b66f0479afd4462e6b262ab392d0c14117a4a02c422b309a9c97ab87fed847afd1c498a746be5e9193ea82903826632609f979984c63374910721e0334bd6d0b12201a3c8f31456a767f3077a1a0ab9165701a2456cadc7b8b4686b8d7b0fc7722e6e176faf3c8ba9fc76414b50d8441ceeba4666c7679d544f6766c85e696f542283b6b5160fa1220c949cd4a76d84429d3ef5aadf1586171b1076b59f6f50734920427811810d712479eb9bdac568c6c2a93773b6d171315f48064dbadf351e25a5223aae6f94d75714c01cb15b33fd24eb", + "enc": "0ad5cf05cd1f610cd9ea6480bb51d65173a58470aa1904a9ca851695e1ebafefccc7c9e9bd8fa8fdab6b41914b35a0e0abfa287e13e38e863d04849b36cddc4ea337b95f60bae825d7f7881baec5a46e136ec4becfc5d022272cdc0700a639d5fa5e3a52a191e4da1a42a13c81ccfea6cb5b0b7c8613f82cd642fefe39c8844030561337dce23ca41f8233638a952581b1546ed24a4bc59ddfad87079fdbb7f69b71f36bc50eccb11970db724ae3ca42e3420635263a4859f254d83def930037ecc8f3aa8237e31aab421d6c29bbe2ab53ae012cb9ed4ac5dbdc40f2ffecce6eda07b0b491389932756828df6e30c982e98ffc26a3dfb507467bce4932fcf9459cd13c4ae48532f3a1d51177d4c586732608c8a2e89fb4bcb68cee4884c9ed7750ad5c925dbe5b6356279e85377db7dfe39395ab04a69700373ec05c54a758bf9aba9a8ac40114fe006892e1bde91c4eb9326917b96b0c0f7d94a8abe5500943c2d78f3a54271e2ef9163fa3613356a750d6803bda6b0ac7d8227b3a5865e30d373c7d14a9b6bb5ead190f5b04516dd17cec64ee934d648d05231679c18cc493c964a8ac1e95b239c1887d68888f2ad37aad8714237efb55572077921b856a326fd8d58c062d1be6d694495bc7634c5dad6559fde36f3bf25f574acc3227c4a04b0b0d7402548d1ffcdae97f706372dab7de7ea9f4572adb15c5020e2be1a0b2f91dccf0c922ecb8724c67ceacdeaca785a24252326b03db8dc2858a91d1441dd00be776e3246e2d3d4c7e7b348f3199d7a95d978c7c1b037ba1ae66c9082dc8ee0e4dc1d740537aba93fad1d91728c110bde37479456aa29599d3fee6923fb345c7322afdc43f08d5e5afb28a4a415af33d6b7aa17c5f1d3b18371ba5f81f618a324c9133c72acf73a7a14f896fe24c1f0ef9452c5eb81e3c8b20437366700d36f784c193866af646501a6fe4863ab6c26b608eed321a603ffccb13ec72dc0d5334299516fd6bb7ff4743c11fb9a6f6803a3c2f4b787a57491db12ff571772e84432b189dcc508f6e487f627700d367037d8ed883e59e8f63944aba263cdaa8e7f60bd35984a95e67fdf4387cef322622932f97ffcf57e0568fd3d0b177eac13372ae2f36f8bfed6edf21fe5f3b4a7e7519391b5566f6420849263977fc13407d7da86c496d1c96f90405ace6ccfd0dd529c2a37b96fe40982164f805c578c2ec3bd0c1b932c09148f4efcf38fe7954234573315954b86c96c7b1b281d3a719366a66e4d73efdedeb3dee2e060b4c5542b097b80d1c39f58de5f88685ccc4cd7ab4da0123af67ecbdcbc145dcbda52354147a11c103ff8bc7783774aeb9dfa96c23cd9a016233046a93a71ed1b47b8e2887f22e9b4dbd145527c613aaa8e5333b9e7467ca61841d37f805664f9ecedfc8f62fcaf392a2362a419eabf35aba64b332ac001b6df6039db869cfad027ade89c926448ba86b8a547e0f0d27606bbffdac20cd40a494a6bfcfea1b487ec6c7ad416b298f4ae272823b4502cc1db8735424302797dea67a46dc84b3e537f64e8f4c006efd4b2cb134b7f7d886fcbfcaccf0091703e425f58e35ebe927a51396fceff741a3ca3b6542acc966a58306dca3dd81955035bd827c6b882660c132fc6130f8c40cdea47bf0414a4a08740ced69013ab823a4d2ab25bc060e36ae7c8209644a9e76105eff422c0591d0d4dc6a3cbba78069bdd3998123daa49d638f0f1b7f1974336ad335bce3fdee61b87443e6f3198ae55a48f3dd6475b2d6042fae8dc6cdabbcab267696aa60e140b2bfef0cbb770915e95f16c094bf39250847a772dac0da8e9c2441ef1c488c34936d98f231aa21f28f33f41769e145e07983fac02aab9e82a36c9af934e89b5695650169796d674fd0eee16276c9f4ffd1a0a13c888a46e396db1c3b44be870884e14ad077b0db4325ad2016c722a3c814aa1920cf7bd6f42622d060967a5629915619c1f23a9b92707ec4c458d4495ffee88df7488fd990ce1633f61a0ace2c9983ae9197d6b9ded3fa0ae0fd660f8d4392cc5731b1013ab4e0adde644e75974384c44e3b80b2023f0c7bdab2e0cd4d39490a4e7462c9142a88045279b01df1865bbcdc32393959eb0a3e01e07e2665477f31973361a9890d4d6fb58563cb365e6682a55f70a6fb7d6664fc81081cf356f056a5c4e05e85040853a33b99356c4a3f75", + "shared_secret": "c2575ffa4d3ac41eb1b7e31cff87172128a33a0f3065313351cb8e556e13a9b1", + "suite_id": "48504b45004200130001", + "key": "441ee6f135d3300ede9f1852f1f42bcb", + "base_nonce": "310a20009a7d1a664530eafd", + "exporter_secret": "f8da246a278b45236e0f139a7d565a7a86981f0251996a2a8320aeb94ef09cf3917b54007e23bc3f6cd902716ddcdf5ca39f69884263020b06995939bd528d2c", + "encryptions": [ + { + "aad": "436f756e742d30", + "ct": "356251f31223c1de2adeb0e15789fdda984b39a140d7cc979afc67cc1b336768678e48edb73a31aa4aa7fa38fd2f351aae8f772373a8c7027993b1d7bf8ec762afa26ac12e6cbad02304", + "nonce": "310a20009a7d1a664530eafd", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d31", + "ct": "d67254890363dc9151b526b158e65e96955340969a0b1e805bf34e52923f0f361d45e19def328ed3181c2ed5189214c12087c588ca096ae248828cebb2bd4d790ff6bcbca82b5b0b8cb3", + "nonce": "310a20009a7d1a664530eafc", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d32", + "ct": "e80864680ab8a4e6f05cccd557694898e0744f20c0b3521e9a2376bee6da3def3e6215af2987729662b5b138e51b255d02ac44b643b9e59f77306b5aec7d4ef06d954da9dbd329dcc39a", + "nonce": "310a20009a7d1a664530eaff", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d33", + "ct": "414edbbc9ed90cd0c9a5c52114cfa0b38b200d44f66b73d33ab0b56fdbba4dc3ae30f83ecf333bcc1969a21b120368181dd7d0c40d09c827e31c039a1ade051e824688faf1770e183b09", + "nonce": "310a20009a7d1a664530eafe", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d34", + "ct": "ab5cfb41054b0a4aee98bd8f791c2d1cac6be826d3e1ef34a3d11ad683d31bad5c40ad590edcc5c76b0d4b49fd3ca8fd369a6dcc2e6764bd117615340a05021b82ac9275d9d9b3e896d1", + "nonce": "310a20009a7d1a664530eaf9", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d35", + "ct": "35b85c8573ceb3d4e5f6d11eb7968a5dee839e3acb00cb9e4dc594de4c156014783d7feaf006e07598d622f04b2df905fafbddaa715b707f4de674a5e4fbcc9cf7bce879a002689c453c", + "nonce": "310a20009a7d1a664530eaf8", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d36", + "ct": "fea0f4fd72a86ff845cd391af465cdd32d38a5099fb99c797e7d6933eb25527f020c9667cb2044e0a9a48b1991f76d08873f013002c176aee8453b38af7291a322d65859edccbd20a270", + "nonce": "310a20009a7d1a664530eafb", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d37", + "ct": "d2602b28e89965a304d09b0e93339f6c2dcb41eef81937d8980a228f85428b6e11cf3990875ff3b9b47f62beaab6ff4e59b41a11b5182165e4a6d7ca63e4bf016bc8b2148ca1cc683a30", + "nonce": "310a20009a7d1a664530eafa", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d38", + "ct": "c5069a5f1df75ded2932b3b99bd2a7f998a773ba83772674e01e72c313f73cdb4ba73e30968813f4aeb31cc3b69ce2537292c3e48a831d275e01c4d5a8cf9b0255654240574c2548cd91", + "nonce": "310a20009a7d1a664530eaf5", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + }, + { + "aad": "436f756e742d39", + "ct": "ce12c2444cf3a5a1b06de09d857118211be0553dfcd986371b5af0fd7054e604f1525b7d8fc00253a28317a3ddddf61897551750184d197886106ec687796e4270a9ea6bef86c7cd608d", + "nonce": "310a20009a7d1a664530eaf4", + "pt": "34323635363137353734373932303639373332303734373237353734363832633230373437323735373436383230363236353631373537343739" + } + ], + "exports": [ + { + "exporter_context": "70736575646f72616e646f6d30", + "L": 32, + "exported_value": "191181ed02b2f817fa25ded3752b71d8d61c34c051c362cc283f58002974c225" + }, + { + "exporter_context": "70736575646f72616e646f6d31", + "L": 32, + "exported_value": "a623dba86c60ac34914c65563c3989592085110280b11b49b6722588fcea2d96" + }, + { + "exporter_context": "70736575646f72616e646f6d32", + "L": 32, + "exported_value": "814f7a487b3d96fcd10ee069d86a61f7acdba088617e9bec9ab5d596f8ac6655" + }, + { + "exporter_context": "70736575646f72616e646f6d33", + "L": 32, + "exported_value": "26e6a79f6556555df3c8392dbfcb8ffddb4bb0d2e7de6a2fc010f445be447056" + }, + { + "exporter_context": "70736575646f72616e646f6d34", + "L": 32, + "exported_value": "8f0aa253ccdab7f34efa5264fcce34e702f5e9509b54507a6446a1cb5541bda2" + } + ] + } +] diff --git a/testdata/rfc9180.json b/testdata/rfc9180.json new file mode 100644 index 0000000..855459f --- /dev/null +++ b/testdata/rfc9180.json @@ -0,0 +1,332 @@ +[ + { + "mode": 0, + "kem_id": 32, + "kdf_id": 1, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "7268600d403fce431561aef583ee1613527cff655c1343f29812e66706df3234", + "ikmR": "6db9df30aa07dd42ee5e8181afdb977e538f5e1fec8a06223f33f7013e525037", + "skRm": "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8", + "pkRm": "3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d", + "enc": "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431", + "encryptions_accumulated": "dcabb32ad8e8acea785275323395abd0", + "exports_accumulated": "45db490fc51c86ba46cca1217f66a75e" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 1, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "2cd7c601cefb3d42a62b04b7a9041494c06c7843818e0ce28a8f704ae7ab20f9", + "ikmR": "dac33b0e9db1b59dbbea58d59a14e7b5896e9bdf98fad6891e99d1686492b9ee", + "skRm": "497b4502664cfea5d5af0b39934dac72242a74f8480451e1aee7d6a53320333d", + "pkRm": "430f4b9859665145a6b1ba274024487bd66f03a2dd577d7753c68d7d7d00c00c", + "enc": "6c93e09869df3402d7bf231bf540fadd35cd56be14f97178f0954db94b7fc256", + "encryptions_accumulated": "1702e73e1e71705faa8241022af1deea", + "exports_accumulated": "5cb678bf1c52afbd9afb58b8f7c1ced3" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 1, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "909a9b35d3dc4713a5e72a4da274b55d3d3821a37e5d099e74a647db583a904b", + "ikmR": "1ac01f181fdf9f352797655161c58b75c656a6cc2716dcb66372da835542e1df", + "skRm": "8057991eef8f1f1af18f4a9491d16a1ce333f695d4db8e38da75975c4478e0fb", + "pkRm": "4310ee97d88cc1f088a5576c77ab0cf5c3ac797f3d95139c6c84b5429c59662a", + "enc": "1afa08d3dec047a643885163f1180476fa7ddb54c6a8029ea33f95796bf2ac4a", + "encryptions_accumulated": "225fb3d35da3bb25e4371bcee4273502", + "exports_accumulated": "54e2189c04100b583c84452f94eb9a4a" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 1, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "55bc245ee4efda25d38f2d54d5bb6665291b99f8108a8c4b686c2b14893ea5d9", + "ikmR": "683ae0da1d22181e74ed2e503ebf82840deb1d5e872cade20f4b458d99783e31", + "skRm": "33d196c830a12f9ac65d6e565a590d80f04ee9b19c83c87f2c170d972a812848", + "pkRm": "194141ca6c3c3beb4792cd97ba0ea1faff09d98435012345766ee33aae2d7664", + "enc": "e5e8f9bfff6c2f29791fc351d2c25ce1299aa5eaca78a757c0b4fb4bcd830918", + "exports_accumulated": "3fe376e3f9c349bc5eae67bbce867a16" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 3, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "895221ae20f39cbf46871d6ea162d44b84dd7ba9cc7a3c80f16d6ea4242cd6d4", + "ikmR": "59a9b44375a297d452fc18e5bba1a64dec709f23109486fce2d3a5428ed2000a", + "skRm": "ddfbb71d7ea8ebd98fa9cc211aa7b535d258fe9ab4a08bc9896af270e35aad35", + "pkRm": "adf16c696b87995879b27d470d37212f38a58bfe7f84e6d50db638b8f2c22340", + "enc": "8998da4c3d6ade83c53e861a022c046db909f1c31107196ab4c2f4dd37e1a949", + "encryptions_accumulated": "19a0d0fb001f83e7606948507842f913", + "exports_accumulated": "e5d853af841b92602804e7a40c1f2487" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 3, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "e72b39232ee9ef9f6537a72afe28f551dbe632006aa1b300a00518883a3f2dc1", + "ikmR": "a0484936abc95d587acf7034156229f9970e9dfa76773754e40fb30e53c9de16", + "skRm": "bdd8943c1e60191f3ea4e69fc4f322aa1086db9650f1f952fdce88395a4bd1af", + "pkRm": "aa7bddcf5ca0b2c0cf760b5dffc62740a8e761ec572032a809bebc87aaf7575e", + "enc": "c12ba9fb91d7ebb03057d8bea4398688dcc1d1d1ff3b97f09b96b9bf89bd1e4a", + "encryptions_accumulated": "20402e520fdbfee76b2b0af73d810deb", + "exports_accumulated": "80b7f603f0966ca059dd5e8a7cede735" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 3, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "636d1237a5ae674c24caa0c32a980d3218d84f916ba31e16699892d27103a2a9", + "ikmR": "969bb169aa9c24a501ee9d962e96c310226d427fb6eb3fc579d9882dbc708315", + "skRm": "fad15f488c09c167bd18d8f48f282e30d944d624c5676742ad820119de44ea91", + "pkRm": "06aa193a5612d89a1935c33f1fda3109fcdf4b867da4c4507879f184340b0e0e", + "enc": "1d38fc578d4209ea0ef3ee5f1128ac4876a9549d74dc2d2f46e75942a6188244", + "encryptions_accumulated": "c03e64ef58b22065f04be776d77e160c", + "exports_accumulated": "fa84b4458d580b5069a1be60b4785eac" + }, + { + "mode": 0, + "kem_id": 32, + "kdf_id": 3, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "3cfbc97dece2c497126df8909efbdd3d56b3bbe97ddf6555c99a04ff4402474c", + "ikmR": "dff9a966e02b161472f167c0d4252d400069449e62384beb78111cb596220921", + "skRm": "7596739457c72bbd6758c7021cfcb4d2fcd677d1232896b8f00da223c5519c36", + "pkRm": "9a83674c1bc12909fd59635ba1445592b82a7c01d4dad3ffc8f3975e76c43732", + "enc": "444fbbf83d64fef654dfb2a17997d82ca37cd8aeb8094371da33afb95e0c5b0e", + "exports_accumulated": "7557bdf93eadf06e3682fce3d765277f" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 1, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "4270e54ffd08d79d5928020af4686d8f6b7d35dbe470265f1f5aa22816ce860e", + "ikmR": "668b37171f1072f3cf12ea8a236a45df23fc13b82af3609ad1e354f6ef817550", + "skRm": "f3ce7fdae57e1a310d87f1ebbde6f328be0a99cdbcadf4d6589cf29de4b8ffd2", + "pkRm": "04fe8c19ce0905191ebc298a9245792531f26f0cece2460639e8bc39cb7f706a826a779b4cf969b8a0e539c7f62fb3d30ad6aa8f80e30f1d128aafd68a2ce72ea0", + "enc": "04a92719c6195d5085104f469a8b9814d5838ff72b60501e2c4466e5e67b325ac98536d7b61a1af4b78e5b7f951c0900be863c403ce65c9bfcb9382657222d18c4", + "encryptions_accumulated": "fcb852ae6a1e19e874fbd18a199df3e4", + "exports_accumulated": "655be1f8b189a6b103528ac6d28d3109" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 1, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "a90d3417c3da9cb6c6ae19b4b5dd6cc9529a4cc24efb7ae0ace1f31887a8cd6c", + "ikmR": "a0ce15d49e28bd47a18a97e147582d814b08cbe00109fed5ec27d1b4e9f6f5e3", + "skRm": "317f915db7bc629c48fe765587897e01e282d3e8445f79f27f65d031a88082b2", + "pkRm": "04abc7e49a4c6b3566d77d0304addc6ed0e98512ffccf505e6a8e3eb25c685136f853148544876de76c0f2ef99cdc3a05ccf5ded7860c7c021238f9e2073d2356c", + "enc": "04c06b4f6bebc7bb495cb797ab753f911aff80aefb86fd8b6fcc35525f3ab5f03e0b21bd31a86c6048af3cb2d98e0d3bf01da5cc4c39ff5370d331a4f1f7d5a4e0", + "encryptions_accumulated": "8d3263541fc1695b6e88ff3a1208577c", + "exports_accumulated": "038af0baa5ce3c4c5f371c3823b15217" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 1, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "f1f1a3bc95416871539ecb51c3a8f0cf608afb40fbbe305c0a72819d35c33f1f", + "ikmR": "61092f3f56994dd424405899154a9918353e3e008171517ad576b900ddb275e7", + "skRm": "a4d1c55836aa30f9b3fbb6ac98d338c877c2867dd3a77396d13f68d3ab150d3b", + "pkRm": "04a697bffde9405c992883c5c439d6cc358170b51af72812333b015621dc0f40bad9bb726f68a5c013806a790ec716ab8669f84f6b694596c2987cf35baba2a006", + "enc": "04c07836a0206e04e31d8ae99bfd549380b072a1b1b82e563c935c095827824fc1559eac6fb9e3c70cd3193968994e7fe9781aa103f5b50e934b5b2f387e381291", + "encryptions_accumulated": "702cdecae9ba5c571c8b00ad1f313dbf", + "exports_accumulated": "2e0951156f1e7718a81be3004d606800" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 1, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "3800bb050bb4882791fc6b2361d7adc2543e4e0abbac367cf00a0c4251844350", + "ikmR": "c6638d8079a235ea4054885355a7caefee67151c6ff2a04f4ba26d099c3a8b02", + "skRm": "62c3868357a464f8461d03aa0182c7cebcde841036aea7230ddc7339f1088346", + "pkRm": "046c6bb9e1976402c692fef72552f4aaeedd83a5e5079de3d7ae732da0f397b15921fb9c52c9866affc8e29c0271a35937023a9245982ec18bab1eb157cf16fc33", + "enc": "04d804370b7e24b94749eb1dc8df6d4d4a5d75f9effad01739ebcad5c54a40d57aaa8b4190fc124dbde2e4f1e1d1b012a3bc4038157dc29b55533a932306d8d38d", + "exports_accumulated": "a6d39296bc2704db6194b7d6180ede8a" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 3, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "4ab11a9dd78c39668f7038f921ffc0993b368171d3ddde8031501ee1e08c4c9a", + "ikmR": "ea9ff7cc5b2705b188841c7ace169290ff312a9cb31467784ca92d7a2e6e1be8", + "skRm": "3ac8530ad1b01885960fab38cf3cdc4f7aef121eaa239f222623614b4079fb38", + "pkRm": "04085aa5b665dc3826f9650ccbcc471be268c8ada866422f739e2d531d4a8818a9466bc6b449357096232919ec4fe9070ccbac4aac30f4a1a53efcf7af90610edd", + "enc": "0493ed86735bdfb978cc055c98b45695ad7ce61ce748f4dd63c525a3b8d53a15565c6897888070070c1579db1f86aaa56deb8297e64db7e8924e72866f9a472580", + "encryptions_accumulated": "3d670fc7760ce5b208454bb678fbc1dd", + "exports_accumulated": "0a3e30b572dafc58b998cd51959924be" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 3, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "0c4b7c8090d9995e298d6fd61c7a0a66bb765a12219af1aacfaac99b4deaf8ad", + "ikmR": "a2f6e7c4d9e108e03be268a64fe73e11a320963c85375a30bfc9ec4a214c6a55", + "skRm": "9648e8711e9b6cb12dc19abf9da350cf61c3669c017b1db17bb36913b54a051d", + "pkRm": "0400f209b1bf3b35b405d750ef577d0b2dc81784005d1c67ff4f6d2860d7640ca379e22ac7fa105d94bc195758f4dfc0b82252098a8350c1bfeda8275ce4dd4262", + "enc": "0404dc39344526dbfa728afba96986d575811b5af199c11f821a0e603a4d191b25544a402f25364964b2c129cb417b3c1dab4dfc0854f3084e843f731654392726", + "encryptions_accumulated": "9da1683aade69d882aa094aa57201481", + "exports_accumulated": "80ab8f941a71d59f566e5032c6e2c675" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 3, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "02bd2bdbb430c0300cea89b37ada706206a9a74e488162671d1ff68b24deeb5f", + "ikmR": "8d283ea65b27585a331687855ab0836a01191d92ab689374f3f8d655e702d82f", + "skRm": "ebedc3ca088ad03dfbbfcd43f438c4bb5486376b8ccaea0dc25fc64b2f7fc0da", + "pkRm": "048fed808e948d46d95f778bd45236ce0c464567a1dc6f148ba71dc5aeff2ad52a43c71851b99a2cdbf1dad68d00baad45007e0af443ff80ad1b55322c658b7372", + "enc": "044415d6537c2e9dd4c8b73f2868b5b9e7e8e3d836990dc2fd5b466d1324c88f2df8436bac7aa2e6ebbfd13bd09eaaa7c57c7495643bacba2121dca2f2040e1c5f", + "encryptions_accumulated": "f025dca38d668cee68e7c434e1b98f9f", + "exports_accumulated": "2efbb7ade3f87133810f507fdd73f874" + }, + { + "mode": 0, + "kem_id": 16, + "kdf_id": 3, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "497efeca99592461588394f7e9496129ed89e62b58204e076d1b7141e999abda", + "ikmR": "49b7cbfc1756e8ae010dc80330108f5be91268b3636f3e547dbc714d6bcd3d16", + "skRm": "9d34abe85f6da91b286fbbcfbd12c64402de3d7f63819e6c613037746b4eae6b", + "pkRm": "0453a4d1a4333b291e32d50a77ac9157bbc946059941cf9ed5784c15adbc7ad8fe6bf34a504ed81fd9bc1b6bb066a037da30fccd6c0b42d72bf37b9fef43c8e498", + "enc": "04f910248e120076be2a4c93428ac0c8a6b89621cfef19f0f9e113d835cf39d5feabbf6d26444ebbb49c991ec22338ade3a5edff35a929be67c4e5f33dcff96706", + "exports_accumulated": "6df17307eeb20a9180cff75ea183dd60" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 1, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "5040af7a10269b11f78bb884812ad20041866db8bbd749a6a69e3f33e54da7164598f005bce09a9fe190e29c2f42df9e9e3aad040fccc625ddbd7aa99063fc594f40", + "ikmR": "39a28dc317c3e48b908948f99d608059f882d3d09c0541824bc25f94e6dee7aa0df1c644296b06fbb76e84aef5008f8a908e08fbabadf70658538d74753a85f8856a", + "skRm": "009227b4b91cf1eb6eecb6c0c0bae93a272d24e11c63bd4c34a581c49f9c3ca01c16bbd32a0a1fac22784f2ae985c85f183baad103b2d02aee787179dfc1a94fea11", + "pkRm": "0400b81073b1612cf7fdb6db07b35cf4bc17bda5854f3d270ecd9ea99f6c07b46795b8014b66c523ceed6f4829c18bc3886c891b63fa902500ce3ddeb1fbec7e608ac70050b76a0a7fc081dbf1cb30b005981113e635eb501a973aba662d7f16fcc12897dd752d657d37774bb16197c0d9724eecc1ed65349fb6ac1f280749e7669766f8cd", + "enc": "0400bec215e31718cd2eff5ba61d55d062d723527ec2029d7679a9c867d5c68219c9b217a9d7f78562dc0af3242fef35d1d6f4a28ee75f0d4b31bc918937b559b70762004c4fd6ad7373db7e31da8735fbd6171bbdcfa770211420682c760a40a482cc24f4125edbea9cb31fe71d5d796cfe788dc408857697a52fef711fb921fa7c385218", + "encryptions_accumulated": "94209973d36203eef2e56d155ef241d5", + "exports_accumulated": "31f25ea5e192561bce5f2c2822a9432c" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 1, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "9953fbd633be69d984fc4fffc4d7749f007dbf97102d36a647a8108b0bb7c609e826b026aec1cd47b93fc5acb7518fa455ed38d0c29e900c56990635612fd3d220d2", + "ikmR": "17320bc93d9bc1d422ba0c705bf693e9a51a855d6e09c11bddea5687adc1a1122ec81384dc7e47959cae01c420a69e8e39337d9ebf9a9b2f3905cb76a35b0693ac34", + "skRm": "01a27e65890d64a121cfe59b41484b63fd1213c989c00e05a049ac4ede1f5caeec52bf43a59bdc36731cb6f8a0b7d7724b047ff52803c421ee99d61d4ea2e569c825", + "pkRm": "0400eb4010ca82412c044b52bdc218625c4ea797e061236206843e318882b3c1642e7e14e7cc1b4b171a433075ac0c8563043829eee51059a8b68197c8a7f6922465650075f40b6f440fdf525e2512b0c2023709294d912d8c68f94140390bff228097ce2d5f89b2b21f50d4c0892cfb955c380293962d5fe72060913870b61adc8b111953", + "enc": "0401c1cf49cafa9e26e24a9e20d7fa44a50a4e88d27236ef17358e79f3615a97f825899a985b3edb5195cad24a4fb64828701e81fbfd9a7ef673efde508e789509bd7c00fd5bfe053377bbee22e40ae5d64aa6fb47b314b5ab7d71b652db9259962dce742317d54084f0cf62a4b7e3f3caa9e6afb8efd6bf1eb8a2e13a7e73ec9213070d68", + "encryptions_accumulated": "69d16fa7c814cd8be9aa2122fda8768f", + "exports_accumulated": "d295fad3aef8be1f89d785800f83a30b" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 1, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "566568b6cbfd1c6c06d1b0a2dc22d4e4965858bf3d54bf6cba5c018be0fad7a5cd9237937800f3cb57f10fa5691faeecab1685aa6da9b667469224a0989ff82b822b", + "ikmR": "f9f594556282cfe3eb30958ca2ef90ecd2a6ffd2661d41eb39ba184f3dae9f914aad297dd80cc763cb6525437a61ceae448aeeb304de137dc0f28dd007f0d592e137", + "skRm": "0168c8bf969b30bd949e154bf2db1964535e3f230f6604545bc9a33e9cd80fb17f4002170a9c91d55d7dd21db48e687cea83083498768cc008c6adf1e0ca08a309bd", + "pkRm": "040086b1a785a52af34a9a830332999896e99c5df0007a2ec3243ee3676ba040e60fde21bacf8e5f8db26b5acd42a2c81160286d54a2f124ca8816ac697993727431e50002aa5f5ebe70d88ff56445ade400fb979b466c9046123bbf5be72db9d90d1cde0bb7c217cff8ea0484445150eaf60170b039f54a5f6baeb7288bc62b1dedb59a1b", + "enc": "0401f828650ec526a647386324a31dadf75b54550b06707ae3e1fb83874b2633c935bb862bc4f07791ccfafbb08a1f00e18c531a34fec76f2cf3d581e7915fa40bbc3b010ab7c3d9162ea69928e71640ecff08b97f4fa9e8c66dfe563a13bf561cee7635563f91d387e2a38ee674ea28b24c633a988d1a08968b455e96307c64bda3f094b7", + "encryptions_accumulated": "586d5a92612828afbd7fdcea96006892", + "exports_accumulated": "a70389af65de4452a3f3147b66bd5c73" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 1, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "5dfb76f8b4708970acb4a6efa35ec4f2cebd61a3276a711c2fa42ef0bc9c191ea9dac7c0ac907336d830cea4a8394ab69e9171f344c4817309f93170cb34914987a5", + "ikmR": "9fd2aad24a653787f53df4a0d514c6d19610ca803298d7812bc0460b76c21da99315ebfec2343b4848d34ce526f0d39ce5a8dfddd9544e1c4d4b9a62f4191d096b42", + "skRm": "01ca47cf2f6f36fef46a01a46b393c30672224dd566aa3dd07a229519c49632c83d800e66149c3a7a07b840060549accd0d480ec5c71d2a975f88f6aa2fc0810b393", + "pkRm": "040143b7db23907d3ae1c43ef4882a6cdb142ca05a21c2475985c199807dd143e898136c65faf1ca1b6c6c2e8a92d67a0ab9c24f8c5cff7610cb942a73eb2ec4217c26018d67621cc78a60ec4bd1e23f90eb772adba2cf5a566020ee651f017b280a155c016679bd7e7ebad49e28e7ab679f66765f4ef34eae6b38a99f31bc73ea0f0d694d", + "enc": "040073dda7343ce32926c028c3be28508cccb751e2d4c6187bcc4e9b1de82d3d70c5702c6c866a920d9d9a574f5a4d4a0102db76207d5b3b77da16bb57486c5cc2a95f006b5d2e15efb24e297bdf8f2b6d7b25bf226d1b6efca47627b484d2942c14df6fe018d82ab9fb7306370c248864ea48fe5ca94934993517aacaa3b6bca8f92efc84", + "exports_accumulated": "d8fa94ac5e6829caf5ab4cdd1e05f5e1" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 3, + "aead_id": 1, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "018b6bb1b8bbcefbd91e66db4e1300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "ikmR": "7bf9fd92611f2ff4e6c2ab4dd636a320e0397d6a93d014277b025a7533684c3255a02aa1f2a142be5391eebfc60a6a9c729b79c2428b8d78fa36497b1e89e446d402", + "skRm": "019db24a3e8b1f383436cd06997dd864eb091418ff561e3876cee2e4762a0cc0b69688af9a7a4963c90d394b2be579144af97d4933c0e6c2c2d13e7505ea51a06b0d", + "pkRm": "0401e06b350786c48a60dfc50eed324b58ecafc4efba26242c46c14274bd97f0989487a6fae0626188fea971ae1cb53f5d0e87188c1c62af92254f17138bbcebf5acd0018e574ee1d695813ce9dc45b404d2cf9c04f27627c4c55da1f936d813fd39435d0713d4a3cdc5409954a1180eb2672bdfc4e0e79c04eda89f857f625e058742a1c8", + "enc": "0400ac8d1611948105f23cf5e6842b07bd39b352d9d1e7bff2c93ac063731d6372e2661eff2afce604d4a679b49195f15e4fa228432aed971f2d46c1beb51fb3e5812501fe199c3d94c1b199393642500443dd82ce1c01701a1279cc3d74e29773030e26a70d3512f761e1eb0d7882209599eb9acd295f5939311c55e737f11c19988878d6", + "encryptions_accumulated": "207972885962115e69daaa3bc5015151", + "exports_accumulated": "8e9c577501320d86ee84407840188f5f" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 3, + "aead_id": 2, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "7f06ab8215105fc46aceeb2e3dc5028b44364f960426eb0d8e4026c2f8b5d7e7a986688f1591abf5ab753c357a5d6f0440414b4ed4ede71317772ac98d9239f70904", + "ikmR": "2ad954bbe39b7122529f7dde780bff626cd97f850d0784a432784e69d86eccaade43b6c10a8ffdb94bf943c6da479db137914ec835a7e715e36e45e29b587bab3bf1", + "skRm": "01462680369ae375e4b3791070a7458ed527842f6a98a79ff5e0d4cbde83c27196a3916956655523a6a2556a7af62c5cadabe2ef9da3760bb21e005202f7b2462847", + "pkRm": "0401b45498c1714e2dce167d3caf162e45e0642afc7ed435df7902ccae0e84ba0f7d373f646b7738bbbdca11ed91bdeae3cdcba3301f2457be452f271fa6837580e661012af49583a62e48d44bed350c7118c0d8dc861c238c72a2bda17f64704f464b57338e7f40b60959480c0e58e6559b190d81663ed816e523b6b6a418f66d2451ec64", + "enc": "040138b385ca16bb0d5fa0c0665fbbd7e69e3ee29f63991d3e9b5fa740aab8900aaeed46ed73a49055758425a0ce36507c54b29cc5b85a5cee6bae0cf1c21f2731ece2013dc3fb7c8d21654bb161b463962ca19e8c654ff24c94dd2898de12051f1ed0692237fb02b2f8d1dc1c73e9b366b529eb436e98a996ee522aef863dd5739d2f29b0", + "encryptions_accumulated": "31769e36bcca13288177eb1c92f616ae", + "exports_accumulated": "fbffd93db9f000f51cf8ab4c1127fbda" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 3, + "aead_id": 3, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "f9d540fde009bb1e5e71617c122a079862306b97144c8c4dca45ef6605c2ec9c43527c150800f5608a7e4cff771226579e7c776fb3def4e22e68e9fdc92340e94b6e", + "ikmR": "5273f7762dea7a2408333dbf8db9f6ef2ac4c475ad9e81a3b0b8c8805304adf5c876105d8703b42117ad8ee350df881e3d52926aafcb5c90f649faf94be81952c78a", + "skRm": "015b59f17366a1d4442e5b92d883a8f35fe8d88fea0e5bac6dfac7153c78fd0c6248c618b083899a7d62ba6e00e8a22cdde628dd5399b9a3377bb898792ff6f54ab9", + "pkRm": "040084698a47358f06a92926ee826a6784341285ee45f4b8269de271a8c6f03d5e8e24f628de13f5c37377b7cabfbd67bc98f9e8e758dfbee128b2fe752cd32f0f3ccd0061baec1ed7c6b52b7558bc120f783e5999c8952242d9a20baf421ccfc2a2b87c42d7b5b806fea6d518d5e9cd7bfd6c85beb5adeb72da41ac3d4f27bba83cff24d7", + "enc": "0400edc201c9b32988897a7f7b19104ebb54fc749faa41a67e9931e87ec30677194898074afb9a5f40a97df2972368a0c594e5b60e90d1ff83e9e35f8ff3ad200fd6d70028b5645debe9f1f335dbc1225c066218e85cf82a05fbe361fa477740b906cb3083076e4d17232513d102627597d38e354762cf05b3bd0f33dc4d0fb78531afd3fd", + "encryptions_accumulated": "aa69356025f552372770ef126fa2e59a", + "exports_accumulated": "1fcffb5d8bc1d825daf904a0c6f4a4d3" + }, + { + "mode": 0, + "kem_id": 18, + "kdf_id": 3, + "aead_id": 65535, + "info": "4f6465206f6e2061204772656369616e2055726e", + "ikmE": "3018d74c67d0c61b5e4075190621fc192996e928b8859f45b3ad2399af8599df69c34b7a3eefeda7ee49ae73d4579300b85dde1654c0dfc3a3f78143d239a628cf72", + "ikmR": "a243eff510b99140034c72587e9f131809b9bce03a9da3da458771297f535cede0f48167200bf49ac123b52adfd789cf0adfd5cded6be2f146aeb00c34d4e6d234fc", + "skRm": "0045fe00b1d55eb64182d334e301e9ac553d6dbafbf69935e65f5bf89c761b9188c0e4d50a0167de6b98af7bebd05b2627f45f5fca84690cd86a61ba5a612870cf53", + "pkRm": "0401635b3074ad37b752696d5ca311da9cc790a899116030e4c71b83edd06ced92fdd238f6c921132852f20e6a2cbcf2659739232f4a69390f2b14d80667bcf9b71983000a919d29366554f53107a6c4cc7f8b24fa2de97b42433610cbd236d5a2c668e991ff4c4383e9fe0a9e7858fc39064e31fca1964e809a2f898c32fba46ce33575b8", + "enc": "0400932d9ff83ca4b799968bda0dd9dac4d02c9232cdcf133db7c53cfbf3d80a299fd99bc42da38bb78f57976bdb69988819b6e2924fadacdad8c05052997cf50b29110139f000af5b2c599b05fc63537d60a8384ca984821f8cd12621577a974ebadaf98bfdad6d1643dd4316062d7c0bda5ba0f0a2719992e993af615568abf19a256993", + "exports_accumulated": "29c0f6150908f6e0d979172f23f1d57b" + } +]