RFC 8645

Re-keying Mechanisms for Symmetric Keys

๐Ÿ“… published August 2019, from ietf

Re-keying Mechanisms for Symmetric Keys ๐ŸŽ€

Part 1 of 13

Title block tea โ˜•: This one is from the Internet Research Task Force (IRTF), with S. Smyshlyaev, Ed. (from CryptoPro) as the editor. It's RFC 8645, the category is Informational, and it was published in August 2019. The ISSN is 2070-1721. It doesn't obsolete or update any other RFCs, so it's just here doing its own thing ๐Ÿ’…

Abstract โœจ

okay so bestie, every key has a limit on how much data you can safely encrypt with it before things start getting risky ๐Ÿ˜ญ That limit is called the "key lifetime" ๐Ÿ”‘ This spec is all about ways to make that lifetime longer! It gives us two kinds of re-keying mechanisms, one based on hash functions and one based on block ciphers, and they play nicely with modes like CTR, GCM, CBC, CFB, and OMAC ๐Ÿฆ‹

This doc is a product of the Crypto Forum Research Group (CFRG) in the IRTF, so the crypto nerds really cooked here ๐Ÿ”ฅ

Status of This Memo ๐ŸŒธ

Real talk: this is not an Internet Standards Track spec. It's published just for information ๐Ÿ“š

It's a product of the Internet Research Task Force (IRTF), which shares Internet-related research and development results. Those results might not be ready for deployment, so don't just yolo them into production ๐Ÿ™ˆ This RFC represents the consensus of the Crypto Forum Research Group of the IRTF. Documents approved for publication by the IRSG are not candidates for any level of Internet Standard, see Section 2 of RFC 7841 ๐Ÿง

If you want the latest status, errata, or a way to send feedback, check https://www.rfc-editor.org/info/rfc8645 ๐Ÿ’œ

Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved. ๐ŸŽ€

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they are in effect on the date this document was published. Please read these carefully, bestie, because they spell out your rights and restrictions for this document ๐Ÿซถ

Table of Contents ๐Ÿงš

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
2.  Conventions Used in This Document . . . . . . . . . . . . . .   7
3.  Basic Terms and Definitions . . . . . . . . . . . . . . . . .   7
4.  Choosing Constructions and Security Parameters  . . . . . . .   9
5.  External Re-keying Mechanisms . . . . . . . . . . . . . . . .  11
  5.1.  Methods of Key Lifetime Control . . . . . . . . . . . . .  14
  5.2.  Parallel Constructions  . . . . . . . . . . . . . . . . .  14
    5.2.1.  Parallel Construction Based on a KDF on a Block
            Cipher  . . . . . . . . . . . . . . . . . . . . . . .  15
    5.2.2.  Parallel Construction Based on a KDF on a Hash
            Function  . . . . . . . . . . . . . . . . . . . . . .  16
    5.2.3.  Tree-Based Construction . . . . . . . . . . . . . . .  16
  5.3.  Serial Constructions  . . . . . . . . . . . . . . . . . .  17
    5.3.1.  Serial Construction Based on a KDF on a Block Cipher   19
    5.3.2.  Serial Construction Based on a KDF on a Hash Function  19
  5.4.  Using Additional Entropy during Re-keying . . . . . . . .  19
6.  Internal Re-keying Mechanisms . . . . . . . . . . . . . . . .  20
  6.1.  Methods of Key Lifetime Control . . . . . . . . . . . . .  22
  6.2.  Constructions that Do Not Require a Master Key  . . . . .  23
    6.2.1.  ACPKM Re-keying Mechanisms  . . . . . . . . . . . . .  23
    6.2.2.  CTR-ACPKM Encryption Mode . . . . . . . . . . . . . .  25
    6.2.3.  GCM-ACPKM Authenticated Encryption Mode . . . . . . .  26
  6.3.  Constructions that Require a Master Key . . . . . . . . .  29
    6.3.1.  ACPKM-Master Key Derivation from the Master Key . . .  29
    6.3.2.  CTR-ACPKM-Master Encryption Mode  . . . . . . . . . .  31
    6.3.3.  GCM-ACPKM-Master Authenticated Encryption Mode  . . .  33
    6.3.4.  CBC-ACPKM-Master Encryption Mode  . . . . . . . . . .  37
    6.3.5.  CFB-ACPKM-Master Encryption Mode  . . . . . . . . . .  39
    6.3.6.  OMAC-ACPKM-Master Authentication Mode . . . . . . . .  40
7.  Joint Usage of External and Internal Re-keying  . . . . . . .  42
8.  Security Considerations . . . . . . . . . . . . . . . . . . .  43
9.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  43
10. References  . . . . . . . . . . . . . . . . . . . . . . . . .  44
  10.1.  Normative References . . . . . . . . . . . . . . . . . .  44
  10.2.  Informative References . . . . . . . . . . . . . . . . .  45
Appendix A.  Test Examples  . . . . . . . . . . . . . . . . . . .  48
  A.1.  Test Examples for External Re-keying  . . . . . . . . . .  48
    A.1.1.  External Re-keying with a Parallel Construction . . .  48
    A.1.2.  External Re-keying with a Serial Construction . . . .  49
  A.2.  Test Examples for Internal Re-keying  . . . . . . . . . .  52
    A.2.1.  Internal Re-keying Mechanisms that Do Not
            Require a Master Key  . . . . . . . . . . . . . . . .  52
    A.2.2.  Internal Re-keying Mechanisms with a Master Key . . .  56
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  69
Contributors  . . . . . . . . . . . . . . . . . . . . . . . . . .  69
Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  69

Part 1 is done, and the actual technical stuff starts in Section 1, Introduction ๐Ÿ’œ

1. Introduction โœจ

okay bestie, let's talk about key lifetime ๐Ÿ”‘. It's the max amount of data you can safely encrypt under a single key before things start getting risky. We call it the "key lifetime" ๐Ÿ’…, and it exists because of three kinds of cryptanalysis (fancy codebreaking ๐Ÿ•ต๏ธโ€โ™€๏ธ):

  1. Methods based on the combinatorial properties of the used block cipher mode of operation

These don't care what the underlying block cipher is ๐Ÿ™ˆ. The mode restrictions that come out of them are of order 2^{n/2}, where n is the block size defined in Section 3. [Sweet32] has an attack example built on this kind of method, and it's giving scary ๐Ÿ’€.

  1. Methods based on side-channel analysis issues

These mostly don't care about the encryption mode, and they only weakly depend on the cipher's features. The limits from these are usually the strictest ones ๐Ÿ˜ญ. [TEMPEST] is an example of an attack based on these methods.

  1. Methods based on the properties of the used block cipher

The big ones here are linear and differential cryptanalysis [LDC]. Mostly these don't depend on the modes of operation either. For secure block ciphers, the bounds from these methods are roughly the same as the natural bounds of 2^n, and they're dominated by the other bounds above ๐ŸŒธ. So we can leave them out of the considerations here.

So the vibe is: replace your key ๐Ÿ”„ when the total size of the processed plaintext under that key starts getting close to the lifetime limit. The exact key lifetime value should be set with some safety margin for protocol security and the methods above ๐Ÿซถ.

Let's say L is a key lifetime limit in some protocol P. To keep it simple, assume every message has the same length m. That means the number of messages q you can process with one key K should satisfy m * q <= L โœจ. You can picture it as a rectangle with sides m and q sitting inside an area L (see Figure 1) ๐Ÿฆ‹.

                  +------------------------+
                  |                      L |
                  | +--------m---------+   |
                  | |==================|   |
                  | |==================|   |
                  | q==================|   |       m * q <= L
                  | |==================|   |
                  | |==================|   |
                  | +------------------+   |
                  +------------------------+

     Figure 1: Graphic Display of the Key Lifetime Limitation

In real life, the amount of data that fits under limit L might not be enough ๐Ÿ˜ฉ. The simplest, most obvious fix is to regularly renegotiate an initial key once you've processed that threshold amount of data. The catch is that it kills performance, since it usually means stopping application data transmission, sending extra service messages, using a random number generator, and lots of other extra calculations, including resource-intensive public key cryptography ๐Ÿ’”.

For protocols built on block ciphers or stream ciphers, a more efficient way to stretch the key lifetime is to use various re-keying mechanisms ๐Ÿงš. This specification only looks at re-keying mechanisms for block ciphers. The re-keying mechanisms typical for stream ciphers (e.g., [Pietrzak2009], [FPS2012]) are out of scope for this document.

Re-keying mechanisms can show up at different protocol levels: the block cipher level (this is called fresh re-keying and is described, for instance, in [FRESHREKEYING]), the block cipher mode of operation level (see Section 6), and the protocol level above the block cipher mode of operation (see Section 5). The first approach is highly inefficient, because the key changes after every single message block is processed ๐Ÿฅด. On top of that, fresh re-keying mechanisms can change the block cipher's internal structure, which can mean extra security analysis for each particular block cipher ๐Ÿ”. So this approach depends on particular primitive properties and can't just be slapped onto any arbitrary block cipher without additional security analysis. That's why fresh re-keying mechanisms are beyond the scope of this document.

So this document is basically a list of recommended re-keying mechanisms you can use in symmetric encryption schemes based on block ciphers ๐ŸŽ€. These mechanisms are independent of the particular block cipher specification, and their security properties rely only on the standard block cipher security assumption ๐Ÿ‘‘.

This specification presents two basic approaches to extending the lifetime of a key without renegotiating, which were introduced in [AAOS2017]:

  1. External re-keying

External re-keying is done by a protocol, and it's independent of the underlying block cipher and the mode of operation ๐Ÿ’…. It can use parallel and serial constructions. In the parallel case, data processing keys K^1, K^2, ... are generated directly from the initial key K, independently of each other. In the serial case, every data-processing key depends on the state that gets updated after each new data-processing key is generated ๐ŸŒˆ.

As a generalization of external parallel re-keying, you can consider an external tree-based mechanism. It's specified in Section 5.2.3 and can be seen as the tree generalization in [GGM]. Similar constructions show up in the one-way tree mechanism ([OWT]) and the [AESDUKPT] standard ๐ŸŒณ.

  1. Internal re-keying

Internal re-keying is built right into the mode, and it depends heavily on the properties of the mode of operation and the block size ๐Ÿงฉ.

Both approaches stretch the key lifetime for a single initial key by limiting leakages (via side channels) and by improving the combinatorial properties of the block cipher mode of operation you're using ๐Ÿ’–.

In practice, re-keying is useful for protocols that have to run in hostile environments or under restricted resource conditions. Think lightweight cryptography, where ciphers have a small block size that brings strict combinatorial limits ๐Ÿฃ. Mechanisms that use external or internal re-keying can also help protect against possible future attacks (by limiting how many plaintext-ciphertext pairs an adversary can collect) and give some forward or backward security properties. That means past or future data-processing keys stay secure even if the current key gets compromised (see [AbBell] for more details) ๐Ÿ›ก๏ธ. External or internal re-keying can be used in network protocols, and also in systems for data-at-rest encryption ๐Ÿ’พ.

Depending on the protocol, there might be situations where both external and internal re-keying mechanisms (see Section 7) can be applied ๐Ÿชž. For example, a similar approach was used in Taha's tree construction (see [TAHA]) ๐ŸŒฟ.

Now, there are key-updating (key regression) algorithms (e.g., [FKK2005] and [KMNT2003]) that also get called "re-keying" ๐Ÿ™„. But they're going after goals other than extending the key lifetime, so key regression algorithms are excluded from the considerations here.

This document represents the consensus of the Crypto Forum Research Group (CFRG) ๐Ÿซถ๐ŸŒธ.

2. Conventions Used in This Document

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐Ÿ“œโœจ.

3. Basic Terms and Definitions

Okay, this part is the glossary ๐Ÿ“–, so let's get the sets and operations straight. This document uses the following terms and definitions for the sets and operations on the elements of these sets ๐Ÿ’œ:

V*      the set of all bit strings of a finite length (hereinafter
        referred to as strings), including the empty string;

V_s     the set of all bit strings of length s, where s is a
        non-negative integer;

|X|     the bit length of the bit string X;

A | B   the concatenation of strings A and B both belonging to V*,
        i.e., a string in V_{|A|+|B|}, where the left substring in
        V_|A| is equal to A and the right substring in V_|B| is equal
        to B;

(xor)   the exclusive-or of two bit strings of the same length;

Z_{2^n} the ring of residues modulo 2^n;

Int_s: V_s -> Z_{2^s}
        the transformation that maps the string a = (a_s, ... , a_1)
        in V_s into the integer Int_s(a) = 2^{s-1} * a_s + ... + 2 *
        a_2 + a_1 (the interpretation of the binary string as an
        integer);

Vec_s: Z_{2^s} -> V_s
        the transformation inverse to the mapping Int_s (the
        interpretation of an integer as a binary string);

MSB_i: V_s -> V_i
        the transformation that maps the string a = (a_s, ... , a_1)
        in V_s into the string MSB_i(a) = (a_s, ... , a_{s-i+1}) in
        V_i (most significant bits);

LSB_i: V_s -> V_i
        the transformation that maps the string a = (a_s, ... , a_1)
        in V_s into the string LSB_i(a) = (a_i, ... , a_1) in V_i
        (least significant bits);

Inc_c: V_s -> V_s
        the transformation that maps the string a = (a_s, ... , a_1)
        in V_s into the string Inc_c(a) = MSB_{|a|-c}(a) |
        Vec_c(Int_c(LSB_c(a)) + 1(mod 2^c)) in V_s (incrementing the
        least significant c bits of the bit string, regarded as the
        binary representation of an integer);

a^s     the string in V_s that consists of s 'a' bits;

E_{K}: V_n -> V_n
        the block cipher permutation under the key K in V_k;

ceil(x) the smallest integer that is greater than or equal to x;

floor(x)
        the biggest integer that is less than or equal to x;

k       the bit length of the K; k is assumed to be divisible by 8;

n       the block size of the block cipher (in bits); n is assumed to
        be divisible by 8;

b       the number of data blocks in the plaintext P (b =
        ceil(|P|/n));

N       the section size (the number of bits that are processed with
        one section key before this key is transformed).

Last but not least, the plaintext message P and its ciphertext C get split into b = ceil(|P|/n) blocks ๐Ÿง. We write them as P = P_1 | P_2 | ... | P_b and C = C_1 | C_2 | ... | C_b. The first b-1 blocks P_i and C_i are in V_n for i = 1, 2, ... , b-1. The last blocks P_b and C_b might be incomplete, meaning they're in V_r, where r <= n, unless specified otherwise ๐Ÿ’…โœจ.

4. Choosing Constructions and Security Parameters โœจ

okay so external re-keying is when a key gets transformed after you've encrypted a limited number of entire messages ๐Ÿ”‘. the method gets picked at the protocol level, no matter which block cipher or encryption mode you're using ๐Ÿ’…. it's recommended for protocols that handle relatively short messages, or protocols that can chop a long message into manageable pieces ๐Ÿงฉ. with external re-keying, the number of messages you can securely process under a single initial key K goes up way more, and you don't lose any message length ๐ŸŒธ

External re-keying has the following advantages:

  1. It increases the lifetime of an initial key by increasing the number of messages processed with this key.
  2. It has minimal impact on performance when the number of messages processed under one initial key is sufficiently large.
  3. It provides forward and backward security of data-processing keys.

However, there's a catch ๐Ÿ™ˆ with restrictive key lifetime limits, the message sizes can get in the way, because you can't process really big messages. so you might need to do extra fragmentation at the protocol level. for example, if the key lifetime L is 1 GB and the message length m = 3 GB, then that message can't be processed as a whole, and it should be split into three fragments that get processed separately ๐Ÿ’€

Internal re-keying is when a key gets transformed during each separate message being processed ๐Ÿฆ‹. these procedures are built right into the base modes of operation, so every internal re-keying mechanism is defined for the particular operation mode and the block size of the cipher being used. internal re-keying is recommended for protocols that process long messages. the size of each single message can get way bigger without losing anything in how many messages you can securely process under one initial key ๐ŸŽ€

Internal re-keying has the following advantages:

  1. It increases the lifetime of an initial key by increasing the size of the messages processed with one initial key.
  2. It has minimal impact on performance.
  3. Internal re-keying mechanisms without a master key do not affect short-message transformation at all.
  4. It is transparent (works like any mode of operation): it does not require changes of initialization vectors (IVs) and a restart of MACing.

Internal re-keying has the following disadvantages:

  1. a specific method must not be chosen independently of a mode of operation.
  2. internal re-keying mechanisms without a master key do not provide backward security of data-processing keys.

Any block cipher modes of operation with internal re-keying can be jointly used with any external re-keying mechanisms. that combo boosts both the number of messages processed with one initial key and their maximum possible size ๐Ÿ”ฅ

If the adversary has access to the data-processing interface, using the same cryptographic primitives for both data processing and re-keying transformation shrinks the code size, but it can lead to some possible vulnerabilities ๐Ÿ˜ญ (mounting a chosen-plaintext attack may lead to the compromise of the following keys). the fix is to use different primitives for data processing and re-keying, e.g., a block cipher for data processing and a hash for re-keying (see Section 5.2.2 and Section 5.3.2). but then the security of the whole scheme can't be reduced to standard notions like a pseudorandom function (PRF) or pseudorandom permutation (PRP), so security estimates get harder and way less clear ๐Ÿ™ˆ

Summing up the issues above, briefly:

  1. If a protocol assumes processing of long records (e.g., [CMS]), internal re-keying should be used. If a protocol assumes processing of a significant number of ordered records, which can be considered as a single data stream (e.g., [TLS], [SSH]), internal re-keying may also be used.
  2. For protocols that allow out-of-order delivery and lost records (e.g., [DTLS], [ESP]), external re-keying should be used, because in this case, records cannot be considered as a single data stream. If the records are also long enough, internal re-keying should also be used during each separate message processing.

For external re-keying:

  1. If it is desirable to separate transformations used for data processing and key updates, hash function-based re-keying should be used.
  2. If parallel data processing is required, then parallel external re-keying should be used.
  3. If restrictive key lifetime limitations are present, external tree-based re-keying should be used.

For internal re-keying:

  1. If the property of forward and backward security is desirable for data-processing keys, and if additional key material can be easily obtained for the data-processing stage, internal re-keying with a master key should be used.

5. External Re-keying Mechanisms ๐ŸŒˆ

this section is all about boosting the initial key lifetime by transforming a data-processing key (the frame key) after a limited number of entire messages (frames) get processed ๐Ÿงš. the approach gives you external parallel and serial re-keying mechanisms (see [AbBell]). these mechanisms only use the initial key K to generate frame keys, and they never use it directly for data processing. they run outside the base modes of operation and don't change them at all, which is why this document calls them "external re-keying" mechanisms โœจ

External re-keying mechanisms are recommended for protocols that process quite small messages, since the biggest gain in initial key lifetime comes from having more messages ๐Ÿ’œ

here's how external re-keying stretches the initial key lifetime. say there's a protocol P with some mode of operation (a base encryption or authentication mode). let L1 be a key lifetime limit set by side-channel analysis methods (the side-channel limitation), let L2 be a key lifetime limit set by methods based on the combinatorial properties of the mode of operation being used (the combinatorial limitation), and let q1, q2 be the total numbers of messages of length m that can safely be processed with an initial key K under these limits, respectively ๐ŸŽ€

Let L = min(L1, L2), q = min(q1, q2), and q * m <= L. since the L1 limit is usually way stricter than the L2 limit (L1 < L2), the final key lifetime restriction is basically the most restrictive limit, L1. so, as Figure 2 shows, without re-keying you can only safely process q1 messages (q1 * m <= L1) ๐Ÿซถ

                         <--------m------->
                         +----------------+ ^ ^
                         |================| | |
                         |================| | |
                     K-->|================| q1|
                         |================| | |
                         |==============L1| | |
                         +----------------+ v |
                         |                |   |
                         |                |   |
                         |                |   q2
                         |                |   |
                         |                |   |
                         |                |   |
                         |                |   |
                         |                |   |
                         |                |   |
                         |                |   |
                         |              L2|   |
                         +----------------+   v

Figure 2: Basic Principles of Message Processing without External Re-keying

Suppose the safety margin for protocol P is fixed, and the external re-keying approach is applied to the initial key K to generate a sequence of frame keys. the frame keys get generated so that leaking a previous frame key has no impact on the next one, which means the side-channel limitation L1 is switched off ๐Ÿฆ‹. that means the resulting key lifetime limit for the initial key K can be worked out from a new combinatorial limitation, L2'. it's proven (see [AbBell]) that the security of a mode of operation using external re-keying goes up compared to the base mode without re-keying (so, L2 < L2'). therefore, as Figure 3 shows, the resulting key lifetime limit with external re-keying can be pushed up to L2' ๐Ÿ’…

                         <--------m------->
                   K     +----------------+
                   |     |================|
                   v     |================|
                  K^1--> |================|
                   |     |================|
                   |     |==============L1|
                   |     +----------------+
                   |     |================|
                   v     |================|
                  K^2--> |================|
                   |     |================|
                   |     |==============L1|
                   |     +----------------+
                   |     |================|
                   v     |================|
                  ...    |      . . .     |
                         |                |
                         |                |
                         |              L2|
                         +----------------+
                         |                |
                        ...              ...
                         |             L2'|
                         +----------------+

Figure 3: Basic Principles of Message Processing with External Re-keying

Note: The key transformation process is shown in a simplified form. A specific approach (parallel and serial) is described below.

Let's look at an example ๐Ÿ“ Say the message size in protocol P is 1 KB. Suppose L1 = 128 MB and L2 = 1 TB. so, without an external re-keying mechanism, the initial key K has to be renegotiated after processing 128 MB / 1 KB = 131072 messages.

With an external re-keying mechanism, the key lifetime limit L1 goes off. so the resulting key lifetime limit L2' can be set to more than 1 TB ๐ŸŒธ That means that with external re-keying, more than 1 TB / 1 KB = 2^30 messages can be processed before the initial key K gets renegotiated. that's 8192 times more messages than you can process without an external re-keying mechanism ๐Ÿ‘‘

5.1. Methods of Key Lifetime Control ๐ŸŽ€

okay so, imagine L is how much data you can safely push through with one frame key ๐Ÿ”‘. For i in {1, 2, ... , t}, the frame key K^i (check Figures 4 and 6 ๐Ÿ’…) should get swapped out after it's handled q_i messages. And q_i can be worked out with one of these three approaches ๐Ÿ‘‡

Explicit approach:

q_i is such that |M^{i,1}| + ... + |M^{i,q_i}| <= L, |M^{i,1}| +
... + |M^{i,q_i+1}| > L.

This is almost the perfect use of the frame key โœจ, but it only works when messages can't get lost or reordered (think TLS records ๐Ÿงพ).

Implicit approach:

q_i = L / m_max, i = 1, ... , t.

Here we assume every message is the biggest possible size, m_max ๐Ÿ“ฆ. So the data you actually get through one key can be way less than L ๐Ÿ˜ญ. The upside is that this one works even when messages can get lost or reordered (like DTLS records ๐ŸŒธ).

Dynamic key changes:

We can run the key change through the Protected Point to Point ([P3]) solution ๐Ÿฆ‹. That means building a protected tunnel between the endpoints, so the info about updating the frame key can be passed along safely. This is useful when you want the adversary to not notice the key change while the protocol is being evaluated ๐Ÿ™ˆ.

5.2. Parallel Constructions ๐Ÿง

External parallel re-keying mechanisms make frame keys K^1, K^2, ... straight from the initial key K, and each one is made independently of the others. It's giving independence ๐Ÿ’œ.

The big idea behind external re-keying with a parallel construction is in Figure 4 ๐Ÿ‘‡

Maximum message size = m_max.
_____________________________________________________________

                               m_max
                         <---------------->
               M^{1,1}   |===             |
               M^{1,2}   |=============== |
     +->K^1-->   ...            ...
     |         M^{1,q_1} |========        |
     |
     |
     |         M^{2,1}   |================|
     |         M^{2,2}   |=====           |
K-----|->K^2-->   ...            ...
     |         M^{2,q_2} |==========      |
     |
    ...
     |         M^{t,1}   |============    |
     |         M^{t,2}   |=============   |
     +->K^t-->   ...            ...
               M^{t,q_t} |==========      |

_____________________________________________________________

Figure 4: External Parallel Re-keying Mechanisms ๐ŸŒˆ

The frame key K^i, i = 1, ... , t - 1 gets updated after a certain number of messages have been processed (see Section 5.1 ๐Ÿ”).

5.2.1. Parallel Construction Based on a KDF on a Block Cipher ๐Ÿ”

The ExtParallelC re-keying mechanism is built on a key derivation function that runs on a block cipher โœจ. It's used to make t frame keys like this:

K^1 | K^2 | ... | K^t = ExtParallelC(K, t * k) = MSB_{t *
k}(E_{K}(Vec_n(0)) |
E_{K}(Vec_n(1)) | ... | E_{K}(Vec_n(R - 1))),

where R = ceil(t * k/n) ๐Ÿงฎ.

5.2.2. Parallel Construction Based on a KDF on a Hash Function ๐Ÿซง

The ExtParallelH re-keying mechanism is built on the key derivation function HKDF-Expand, described in [RFC5869] ๐Ÿ’–. It's used to make t frame keys like this:

K^1 | K^2 | ... | K^t = ExtParallelH(K, t * k) = HKDF-Expand(K,
label, t * k),

where label is a string (it can be a zero-length string ๐Ÿซถ) that a specific protocol defines.

5.2.3. Tree-Based Construction ๐ŸŒณ

Using an external tree-based mechanism builds a key tree ๐ŸŒฒ. The initial key K is the root key at level 0, and the frame keys K^1, K^2, ... sit at the last level, like in Figure 5 ๐Ÿ‘‘.

                          K_root = K
                    ___________|___________
                   |          ...          |
                   V                       V
                  K{1,1}                K{1,W1}
             ______|______           ______|______
            |     ...     |         |     ...     |
            V             V         V             V
         K{2,1}       K{2,W2}  K{2,(W1-1)*W2+1} K{2,W1*W2}
          __|__         __|__     __|__         __|__
         | ... |       | ... |   | ... |       | ... |
         V     V       V     V   V     V       V     V
      K{3,1}  ...     ...   ... ...   ...     ...   K{3,W1*W2*W3}

       ...                                           ...
      __|__                   ...                   __|__
     | ... |                                       | ... |
     V     V                                       V     V
 K{h,1}   K{h,Wh}         K{h,(W1*...*W{h-1}-1)*Wh+1}  K{h,W1*...*Wh}
   //       \\                                  //       \\
 K^1       K^{Wh}        K^{(W1*...*W{h-1}-1)*Wh+1}     K^{W1*...*Wh}
 ____________________________________________________________________

Figure 5: External Tree-Based Mechanism ๐ŸŒธ

The tree height h, and the number of keys Wj, j in {1, ... , h}, that can be split off from a "parent" key are defined by a specific protocol and the key lifetime limits for the derivation functions being used ๐Ÿ“.

Each j-level key K{j,w}, where j in {1, ... , h} and w in {1, ... , W1 * ... * Wj}, comes from the (j-1)-level "parent" key K{j-1, ceil(w/Wi)} (plus any other relevant input data) ๐Ÿ“. It uses the j-th level derivation function, which can be built on a block cipher or a hash function. A specific protocol defines which one ๐Ÿงš.

The i-th frame K^i, i in {1, 2, ... , W1*...*Wh}, can be calculated like this:

K^i = ExtKeyTree(K, i) = KDF_h(KDF_{h-1}(... KDF_1(K, ceil(i / (W2
* ... * Wh)) ... , ceil(i / Wh)), i),

where KDF_j is the j-th level derivation function. It takes two arguments, the parent key value and an integer from 1 to W1 * ... * Wj, and it outputs the j-th level key value ๐Ÿ’….

The frame key K^i gets updated after a certain number of messages have been processed (see Section 5.1 โฐ).

To make an efficient implementation, the derivation functions KDF_j, j in {1, ... , h-1}, should only be used when ceil(i / (W{j+1} * ... * Wh)) != ceil((i - 1) / (W{j+1} * ... * Wh)) during frame key K^i generation. Otherwise, you need to reuse a value you already generated ๐Ÿ”„. This approach also lets you take countermeasures against side-channel attacks ๐Ÿ›ก๏ธ.

Let's look at an example ๐Ÿ‘€. Suppose h = 3, W1 = W2 = W3 = W, and KDF_1, KDF_2, KDF_3 are key derivation functions based on the KDF_GOSTR3411_2012_256 (hereafter simply KDF) function described in [RFC7836] โœจ. The resulting ExtKeyTree function can be defined like this:

ExtKeyTree(K, i) = KDF(KDF(KDF(K, "level1", ceil(i / W^2)),
"level2", ceil(i / W)), "level3", i).

where i in {1, 2, ... , W^3} ๐Ÿฅน.

A structure similar to the external tree-based mechanism can be found in Section 6 of [NISTSP800-108] ๐Ÿ™Œ.

5.3. Serial Constructions ๐Ÿ”—

External serial re-keying mechanisms make frame keys, and each one depends on a secret state (K*_1, K*_2, ...) that gets updated after every new frame key is generated. See Figure 6 ๐Ÿ‘‡. Similar approaches show up in the [SIGNAL] protocol and the [TLS] updating traffic key mechanism, and they were proposed for use in the [U2F] protocol ๐Ÿฆ‹.

External serial re-keying mechanisms have an obvious downside: they can't be done in parallel ๐Ÿ˜ฉ. But they might be the preferred option if you want extra forward secrecy ๐ŸงŠ. If every key is securely deleted after use, then compromising the current secret state at some point doesn't compromise all the previous secret states and frame keys ๐Ÿ’ช. In [TLS] terms, compromising application_traffic_secret_N doesn't compromise all the previous application_traffic_secret_i, i < N ๐Ÿซถ.

The big idea behind external re-keying with a serial construction is in Figure 6 ๐Ÿ‘‡

Maximum message size = m_max.
_____________________________________________________________
                                     m_max
                               <---------------->
                     M^{1,1}   |===             |
                     M^{1,2}   |=============== |
K*_1 = K --->K^1-->    ...            ...
  |                  M^{1,q_1} |========        |
  |
  |
  |                  M^{2,1}   |================|
  v                  M^{2,2}   |=====           |
K*_2 ------->K^2-->    ...            ...
  |                  M^{2,q_2} |==========      |
  |
 ...
  |                  M^{t,1}   |============    |
  v                  M^{t,2}   |=============   |
K*_t ------->K^t-->    ...            ...
                     M^{t,q_t} |==========      |


_____________________________________________________________

Figure 6: External Serial Re-keying Mechanisms ๐ŸŒˆ

The frame key K^i, i = 1, ... , t - 1, gets updated after a certain number of messages have been processed (see Section 5.1 ๐Ÿ”).

5.3.1. Serial Construction Based on a KDF on a Block Cipher ๐Ÿ”

The frame key K^i is calculated with the ExtSerialC transformation like this:

K^i = ExtSerialC(K, i) =
MSB_k(E_{K*_i}(Vec_n(0)) |E_{K*_i}(Vec_n(1)) | ... |
E_{K*_i}(Vec_n(J - 1))),

where J = ceil(k / n), i = 1, ... , t, and K*_i is calculated like this:

K*_1 = K,

K*_{j+1} = MSB_k(E_{K*_j}(Vec_n(J)) | E_{K*_j}(Vec_n(J + 1)) |
... |
E_{K*_j}(Vec_n(2 * J - 1))),

where j = 1, ... , t - 1 ๐Ÿง .

5.3.2. Serial Construction Based on a KDF on a Hash Function ๐Ÿซง

The frame key K^i is calculated with the ExtSerialH transformation like this:

K^i = ExtSerialH(K, i) = HKDF-Expand(K*_i, label1, k),

where i = 1, ... , t. HKDF-Expand is the HMAC-based key derivation function, as described in [RFC5869] ๐Ÿ’œ. K*_i is calculated like this:

K*_1 = K,

K*_{j+1} = HKDF-Expand(K*_j, label2, k), where j = 1, ... , t - 1,

where label1 and label2 are different strings from V* that a specific protocol defines. For example, check the algorithm for updating traffic keys in TLS 1.3 [TLS] ๐ŸŒธ.

5.4. Using Additional Entropy during Re-keying ๐ŸŽฒ

Honestly? In lots of cases, using extra entropy during re-keying won't make things more secure, but it can give you a false sense of security ๐Ÿ™ˆ. So you should only rely on additional entropy after doing a deep security analysis ๐Ÿ”. For example, good PRF constructions don't need extra entropy for key quality, so most of the time there's no need to add extra entropy to external re-keying mechanisms that use secure KDFs ๐Ÿ’…. However, in some situations mixed-in entropy can still boost security. That's when there's a time-limited but complete breach of the system, and an adversary can reach the frame-key generation interface but can't reveal the master keys (for example, when the master keys live in a Hardware Security Module (HSM)) ๐Ÿ”’.

For example, an external parallel construction based on a KDF on a hash function with mixed-in entropy can be described like this:

K^i = HKDF-Expand(K, label_i, k),

where label_i is additional entropy that must be sent to the recipient (for example, sent together with an encrypted message ๐Ÿ’Œ). The entropy label_i and the corresponding key K^i must be generated right before message processing โณ.

6. Internal Re-keying Mechanisms โœจ

okay bestie, this section is about stretching out how long a key can last by transforming the data-processing key, called the section key, during each message ๐Ÿ’–. Every message starts with the same key (the first section key), and then each section key gets updated after N bits of the message (that chunk is called a section) ๐Ÿฆ‹

This section gives us internal re-keying mechanisms called ACPKM (Advanced Cryptographic Prolongation of Key Material) and ACPKM-Master. ACPKM doesn't use a master key, and ACPKM-Master does. They get built right into the base modes of operation, so they actually become new modes of operation ๐ŸŒธ That's why this document calls them "internal re-keying" mechanisms.

Internal re-keying is recommended for protocols that process large single messages (like CMS messages) ๐ŸŽ€ The biggest key-lifetime boost comes from making a message longer, and it barely helps if you're just trying to push more messages through one initial key ๐Ÿ’…

Here's how internal re-keying bumps up the key lifetime. Say protocol P uses some base mode of operation. Let L1 and L2 be a side-channel limitation and a combinatorial limitation, respectively. For some fixed number of messages q, let m1 and m2 be the lengths of messages that can be safely processed with one initial key K under those limits.

So without re-keying (kinda like Section 5), the final key lifetime restriction is just L1, and only q messages of length m1 can be safely processed. Check out Figure 7 ๐Ÿงš

                K
                |
                v
      ^ +----------------+------------------------------------+
      | |==============L1|                                  L2|
      | |================|                                    |
      q |================|                                    |
      | |================|                                    |
      | |================|                                    |
      v +----------------+------------------------------------+
        <-------m1------->
        <----------------------------m2----------------------->

             Figure 7: Basic Principles of Message Processing
                        without Internal Re-keying

Now suppose the safety margin for protocol P is fixed and we apply internal re-keying to the base mode. Every message gets processed with a section key that transforms after every N bits, where N is a parameter. If q * N doesn't exceed L1, then the side-channel limit L1 goes off ๐Ÿ™ˆ The key lifetime of the initial key K can then be worked out from a new combinatorial limit, L2'. The mode with internal re-keying is more secure than the base mode without re-keying (so L2 < L2'). That means, as Figure 8 shows, the key lifetime limit with internal re-keying can climb up to L2' ๐Ÿ“ˆ

  K-----> K^1-------------> K^2 -----------> . . .
          |                 |
          v                 v
^ +---------------+---------------+------------------+--...--+
| |=============L1|=============L1|======          L2|    L2'|
| |===============|===============|======            |       |
q |===============|===============|====== . . .      |       |
| |===============|===============|======            |       |
| |===============|===============|======            |       |
v +---------------+---------------+------------------+--...--+
  <-------N------->

          Figure 8: Basic Principles of Message Processing
                       with Internal Re-keying
Note: the key transformation is drawn in a simplified way here. The actual approach (the ACPKM and ACPKM-Master re-keying mechanisms) is described below ๐Ÿ‘€

Performance can dip a little when N is pretty small, so for a given protocol the biggest possible N should be picked to get the key lifetime you need for the security models you're looking at ๐Ÿ’œ

Let's do an example! Say L1 = 128 MB and L2 = 10 TB. If messages in the protocol are large or unlimited (which could use up the whole L2 lifetime), the most restrictive limit is 128 MB ๐Ÿ˜ญ

That means we need a cap on the maximum message size, m_max. For instance, if m_max = 32 MB, you might have to renegotiate initial key K after only four messages ๐Ÿ’€

But if you use an internal re-keying mechanism with section size N = 1 MB, more than L1 / N = 128 MB / 1 MB = 128 messages can get processed before initial key K needs renegotiating. Without internal re-keying you'd only get four messages! Since only one section of each message is processed with section key K^i, the L1 limit goes off ๐Ÿ”ฅ So the resulting key lifetime limit L2' can be set to more than 10 TB (when a single large message is processed under the initial key K) ๐Ÿ‘‘

6.1. Methods of Key Lifetime Control

Let L be the amount of data that can be safely processed with one section key, and let N be the section size (a fixed parameter). Let M^{i}_1 be the first section of message M^{i}, for i = 1, ... , q (see Figures 9 and 10). The parameter q can then be computed with one of two approaches ๐ŸŒˆ

  • Explicit approach: q_i is such that |M^{1}_1| + ... + |M^{q}_1| <= L and |M^{1}_1| + ... + |M^{q+1}_1| > L. This approach lets you use the section key K^i in an almost optimal way, but it only works when messages can't be lost or reordered (for example, TLS records) ๐Ÿซถ
  • Implicit approach: q = L / N. The amount of data processed with one section key K^i is calculated assuming every message is at least as long as the section size N, so it can end up way less than the key lifetime limit L. On the flip side, this approach works when messages may be lost or reordered (for example, DTLS records) ๐Ÿฆ‹

6.2. Constructions that Do Not Require a Master Key

This section covers the block cipher modes that use the ACPKM re-keying mechanism, which doesn't use a master key. The initial key is used directly for data encryption ๐Ÿ“

6.2.1. ACPKM Re-keying Mechanisms

This section defines a periodic key transformation without a master key, called the ACPKM re-keying mechanism โœจ It can be applied to one of the base encryption modes (the CTR and GCM block cipher modes) to get an extended version of that encryption mode, which does periodic key transformation without a master key. That extension can be treated as a brand-new encryption mode ๐Ÿ’…

One more parameter defines how base encryption modes work with the ACPKM re-keying mechanism: the section size N. N is measured in bits and is fixed within a specific protocol, based on the system capacity requirements and the key lifetime. The section size N MUST be divisible by the block size n ๐ŸŽ€

The big idea behind internal re-keying without a master key is shown in Figure 9 ๐Ÿงš

Section size = const = N,
maximum message size = m_max.
____________________________________________________________________

             ACPKM       ACPKM              ACPKM
      K^1 = K ---> K^2 ---...-> K^{l_max-1} ----> K^{l_max}
          |          |                |           |
          |          |                |           |
          v          v                v           v
M^{1} |==========|==========| ... |==========|=======:  |
M^{2} |==========|==========| ... |===       |       :  |
  .        .          .        .       .          .  :
  :        :          :        :       :          :  :
M^{q} |==========|==========| ... |==========|=====  :  |
                   section                           :
                 <---------->                      m_max
                    N bit
___________________________________________________________________
l_max = ceil(m_max/N).

          Figure 9: Internal Re-keying without a Master Key

When a message M of length m is processed in some encryption mode that uses the ACPKM key transformation of initial key K, the message is split into l = ceil(m / N) sections. These are written as M = M_1 | M_2 | ... | M_l, where M_i is in V_N for i in {1, 2, ... , l - 1}, and M_l is in V_r with r <= N. The first section of each message is processed with section key K^1 = K. To process the (i + 1)-th section of each message, the section key K^{i+1} is worked out with the ACPKM transformation like this:

K^{i+1} = ACPKM(K^i) = MSB_k(E_{K^i}(D_1) | ... | E_{K^i}(D_J))

where J = ceil(k/n), and D_1, D_2, ... , D_J are in V_n and are calculated like this:

D_1 | D_2 | ... | D_J = MSB_{J * n}(D)

and D is this constant in V_{1024}:

         D = ( 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87
             | 88 | 89 | 8a | 8b | 8c | 8d | 8e | 8f
             | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97
             | 98 | 99 | 9a | 9b | 9c | 9d | 9e | 9f
             | a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7
             | a8 | a9 | aa | ab | ac | ad | ae | af
             | b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7
             | b8 | b9 | ba | bb | bc | bd | be | bf
             | c0 | c1 | c2 | c3 | c4 | c5 | c6 | c7
             | c8 | c9 | ca | cb | cc | cd | ce | cf
             | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7
             | d8 | d9 | da | db | dc | dd | de | df
             | e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7
             | e8 | e9 | ea | eb | ec | ed | ee | ef
             | f0 | f1 | f2 | f3 | f4 | f5 | f6 | f7
             | f8 | f9 | fa | fb | fc | fd | fe | ff)

Note: the constant D is built so that D_1, ... , D_J are pairwise different for any allowed values of n and k ๐Ÿ’–

Note: the highest bit of every octet of the constant D is equal to 1. This condition matters because, together with a certain mode message length limitation, it helps prevent collisions of block cipher permutation inputs during key transformation and message processing (for more details, see Section 4.4 of [AAOS2017]) ๐Ÿ”ฅ

6.2.2. CTR-ACPKM Encryption Mode โœจ

Okay so this section defines CTR-ACPKM ๐ŸŽ€, an encryption mode that uses the ACPKM internal re-keying mechanism for the periodical key transformation. It's basically plain old CTR (see [MODES]) with the ACPKM re-keying glow-up added on top ๐Ÿ’….

The CTR-ACPKM encryption mode can be used with these parameters ๐ŸŒธ:

  • 64 <= n <= 512.
  • 128 <= k <= 512.
  • The number c of bits in the specific part of the block that gets incremented is such that 32 <= c <= 3 / 4 n, and c is a multiple of 8 ๐Ÿ“.
  • The maximum message size is m_max = n * 2^{c-1}.

Here's how the CTR-ACPKM encryption and decryption procedures go ๐Ÿฆ‹:

+----------------------------------------------------------------+
|  CTR-ACPKM-Encrypt(N, K, ICN, P)                               |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - initial counter nonce ICN in V_{n-c},                       |
|  - plaintext P = P_1 | ... | P_b, |P| <= m_max.                |
|  Output:                                                       |
|  - ciphertext C.                                               |
|----------------------------------------------------------------|
|  1. CTR_1 = ICN | 0^c                                          |
|  2. For j = 2, 3, ... , b do                                   |
|         CTR_{j} = Inc_c(CTR_{j-1})                             |
|  3. K^1 = K                                                    |
|  4. For i = 2, 3, ... , ceil(|P| / N)                          |
|         K^i = ACPKM(K^{i-1})                                   |
|  5. For j = 1, 2, ... , b do                                   |
|         i = ceil(j * n / N),                                   |
|         G_j = E_{K^i}(CTR_j)                                   |
|  6. C = P (xor) MSB_{|P|}(G_1 | ... | G_b)                     |
|  7. Return C                                                   |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
|  CTR-ACPKM-Decrypt(N, K, ICN, C)                               |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - initial counter nonce ICN in V_{n-c},                       |
|  - ciphertext C = C_1 | ... | C_b, |C| <= m_max.               |
|  Output:                                                       |
|  - plaintext P.                                                |
|----------------------------------------------------------------|
|  1. P = CTR-ACPKM-Encrypt(N, K, ICN, C)                        |
|  2. Return P                                                   |
+----------------------------------------------------------------+

The initial counter nonce (ICN) value for each message that is encrypted under the given initial key K must be chosen in a unique manner ๐Ÿซถ.

6.2.3. GCM-ACPKM Authenticated Encryption Mode ๐Ÿ‘‘

This section defines the GCM-ACPKM authenticated encryption mode, which uses the ACPKM internal re-keying mechanism for the periodical key transformation. It's giving GCM (see [GCM]) with the ACPKM re-keying mechanism stacked on top ๐Ÿ’œ.

The GCM-ACPKM authenticated encryption mode can be used with these parameters โœจ:

  • n in {128, 256}.
  • 128 <= k <= 512.
  • The number c of bits in the specific part of the block that gets incremented is such that 1 / 4 n <= c <= 1 / 2 n, and c is a multiple of 8 ๐ŸŒˆ.
  • Authentication tag length t.
  • The maximum message size is m_max = min{n * (2^{c-1} - 2), 2^{n/2} - 1}.

The GCM-ACPKM mode encryption and decryption procedures are defined like this ๐Ÿงš:

+-------------------------------------------------------------------+
|  GHASH(X, H)                                                      |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - bit string X = X_1 | ... | X_m, X_1, ... , X_m in V_n.         |
|  Output:                                                          |
|  - block GHASH(X, H) in V_n.                                      |
|-------------------------------------------------------------------|
|  1. Y_0 = 0^n                                                     |
|  2. For i = 1, ... , m do                                         |
|         Y_i = (Y_{i-1} (xor) X_i) * H                             |
|  3. Return Y_m                                                    |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCTR(N, K, ICB, X)                                               |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - initial counter block ICB,                                     |
|  - X = X_1 | ... | X_b.                                           |
|  Output:                                                          |
|  - Y in V_{|X|}.                                                  |
|-------------------------------------------------------------------|
|  1. If X in V_0, then return Y, where Y in V_0                    |
|  2. GCTR_1 = ICB                                                  |
|  3. For i = 2, ... , b do                                         |
|         GCTR_i = Inc_c(GCTR_{i-1})                                |
|  4. K^1 = K                                                       |
|  5. For j = 2, ... , ceil(|X| / N)                                |
|         K^j = ACPKM(K^{j-1})                                      |
|  6. For i = 1, ... , b do                                         |
|         j = ceil(i * n / N),                                      |
|         G_i = E_{K_j}(GCTR_i)                                     |
|  7. Y = X (xor) MSB_{|X|}(G_1 | ... | G_b)                        |
|  8. Return Y                                                      |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCM-ACPKM-Encrypt(N, K, ICN, P, A)                               |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - initial counter nonce ICN in V_{n-c},                          |
|  - plaintext P = P_1 | ... | P_b, |P| <= m_max,                   |
|  - additional authenticated data A.                               |
|  Output:                                                          |
|  - ciphertext C,                                                  |
|  - authentication tag T.                                          |
|-------------------------------------------------------------------|
|  1. H = E_{K}(0^n)                                                |
|  2. ICB_0 = ICN | 0^{c-1} | 1                                     |
|  3. C = GCTR(N, K, Inc_c(ICB_0), P)                               |
|  4. u = n * ceil(|C| / n) - |C|                                   |
|     v = n * ceil(|A| / n) - |A|                                   |
|  5. S = GHASH(A | 0^v | C | 0^u | Vec_{n/2}(|A|) |                |
|               | Vec_{n/2}(|C|), H)                                |
|  6. T = MSB_t(E_{K}(ICB_0) (xor) S)                               |
|  7. Return C | T                                                  |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCM-ACPKM-Decrypt(N, K, ICN, A, C, T)                            |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - initial counter block ICN,                                     |
|  - additional authenticated data A,                               |
|  - ciphertext C = C_1 | ... | C_b, |C| <= m_max,                  |
|  - authentication tag T.                                          |
|  Output:                                                          |
|  - plaintext P or FAIL.                                           |
|-------------------------------------------------------------------|
|  1. H = E_{K}(0^n)                                                |
|  2. ICB_0 = ICN | 0^{c-1} | 1                                     |
|  3. P = GCTR(N, K, Inc_c(ICB_0), C)                               |
|  4. u = n * ceil(|C| / n) - |C|                                   |
|     v = n * ceil(|A| / n) - |A|                                   |
|  5. S = GHASH(A | 0^v | C | 0^u | Vec_{n/2}(|A|) |                |
|               | Vec_{n/2}(|C|), H)                                |
|  6. T' = MSB_t(E_{K}(ICB_0) (xor) S)                              |
|  7. If T = T', then return P; else return FAIL                    |
+-------------------------------------------------------------------+

The * operation on (pairs of) the 2^n possible blocks corresponds to the multiplication operation for the binary Galois (finite) field of 2^n elements defined by the polynomial f as follows (analogous to [GCM]) ๐Ÿ”ฅ:

n = 128:  f = a^128 + a^7 + a^2 + a^1 + 1,

n = 256:  f = a^256 + a^10 + a^5 + a^2 + 1.

The initial counter nonce ICN value for each message that is encrypted under the given initial key K must be chosen in a unique manner ๐Ÿ’….

The key for computing values E_{K}(ICB_0) and H is not updated and is equal to the initial key K ๐ŸŒธ.

6.3. Constructions that Require a Master Key ๐Ÿ”‘

This section describes the block cipher modes that use the ACPKM-Master re-keying mechanism. These modes use the initial key K as a master key, so K is never used directly for data processing and is only used for key derivation โœจ.

6.3.1. ACPKM-Master Key Derivation from the Master Key

okay so this section is all about periodical key transformation with a master key ๐Ÿ”‘, aka the ACPKM-Master re-keying mechanism ๐Ÿ’–. it can be slapped onto one of the base modes of operation (CTR, GCM, CBC, CFB, OMAC modes) to get an extension that does periodical key transformation with a master key, and honestly that extension is giving "brand new mode of operation" energy โœจ

the extra parameters that control how these modes work are the section size N, the change frequency T* of the master keys K*_1, K*_2, ... (see Figure 10), and the size d of the section key material. N and T* are measured in bits and get fixed within a specific protocol based on the system capacity and the key lifetime ๐ŸŒธ two rules to remember bestie: the section size N MUST be divisible by the block size n, and the master key frequency T* MUST be divisible by d and by n ๐Ÿซถ

here's the big picture of internal re-keying with a master key, in Figure 10 ๐Ÿฆ‹

   Master key frequency T*,
   section size N,
   maximum message size = m_max.
   _____________________________________________________________________

                           ACPKM                 ACPKM
                K*_1 = K----------> K*_2 ---------...-----> K*_l_max
               ___|___            ___|___                 ___|___
              |       |          |       |               |       |
              v  ...  v          v  ...  v               v  ...  v
            K[1]     K[t]     K[t+1]  K[2*t]  K[(l_max-1)t+1] K[l_max*t]
              |       |          |       |               |       |
              |       |          |       |               |       |
              v       v          v       v               v       v
   M^{1}||======|...|======||======|...|======||...||======|...|==  : ||
   M^{2}||======|...|======||======|...|======||...||======|...|====: ||
    ... ||      |   |      ||      |   |      ||   ||      |   |    : ||
   M^{q}||======|...|======||====  |...|      ||...||      |...|    : ||
          section                                                   :
         <------>                                                   :
           N bit                                                  m_max
   _____________________________________________________________________
   |K[i]| = d,
   t = T* / d,
   l_max = ceil(m_max / (N * t)).
              Figure 10: Internal Re-keying with a Master Key

so when a message M of length m gets processed in a mode using ACPKM-Master key transformation, with initial key K and master key frequency T*, the message is chopped into l = ceil(m / N) sections. that's written as M = M_1 | M_2 | ... | M_l, where M_i is in V_N for i in {1, 2, ... , l - 1} and M_l is in V_r, r <= N. ๐Ÿ’… each section j gets its own key material K[j] (for j in {1, ... , l}, with |K[j]| = d), worked out by the ACPKM-Master algorithm like this:

   K[1] | ... | K[l] = ACPKM-Master(T*, K, d, l) = CTR-ACPKM-Encrypt
   (T*, K, 1^{n/2}, 0^{d*l}).
Note: The parameters d and l MUST be such that d * l <= n * 2^{n/2-1}. ๐Ÿ™ˆ this one is non-negotiable, no cap.

6.3.2. CTR-ACPKM-Master Encryption Mode

this part defines the CTR-ACPKM-Master encryption mode ๐ŸŽ€, which uses the ACPKM-Master internal re-keying mechanism for the periodical key transformation. โœจ

it can be thought of as the base encryption mode CTR (see [MODES]) with the ACPKM-Master re-keying mechanism bolted on. it's like the classic CTR glow-up ๐Ÿ’œ

you can use CTR-ACPKM-Master with these parameters:

  • 64 <= n <= 512.
  • 128 <= k <= 512.
  • The number c of bits in a specific part of the block to be incremented is such that 32 <= c <= 3 / 4 n, and c is a multiple of 8.
  • The maximum message size m_max = min{N * (n * 2^{n/2-1} / k), n * 2^c}.

the key material K[j] used for one-section processing is equal to K^j, where |K^j| = k bits. ๐ŸŒˆ

here are the encryption and decryption procedures for the CTR-ACPKM-Master mode, verbatim:

+----------------------------------------------------------------+
|  CTR-ACPKM-Master-Encrypt(N, K, T*, ICN, P)                    |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - master key frequency T*,                                    |
|  - initial counter nonce ICN in V_{n-c},                       |
|  - plaintext P = P_1 | ... | P_b, |P| <= m_max.                |
|  Output:                                                       |
|  - ciphertext C.                                               |
|----------------------------------------------------------------|
|  1. CTR_1 = ICN | 0^c                                          |
|  2. For j = 2, 3, ... , b do                                   |
|         CTR_{j} = Inc_c(CTR_{j-1})                             |
|  3. l = ceil(|P| / N)                                          |
|  4. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)                |
|  5. For j = 1, 2, ... , b do                                   |
|         i = ceil(j * n / N),                                   |
|         G_j = E_{K^i}(CTR_j)                                   |
|  6. C = P (xor) MSB_{|P|}(G_1 | ... |G_b)                      |
|  7. Return C                                                   |
|----------------------------------------------------------------+
+----------------------------------------------------------------+
|  CTR-ACPKM-Master-Decrypt(N, K, T*, ICN, C)                    |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - master key frequency T*,                                    |
|  - initial counter nonce ICN in V_{n-c},                       |
|  - ciphertext C = C_1 | ... | C_b, |C| <= m_max.               |
|  Output:                                                       |
|  - plaintext P.                                                |
|----------------------------------------------------------------|
|  1. P = CTR-ACPKM-Master-Encrypt(N, K, T*, ICN, C)             |
|  1. Return P                                                   |
+----------------------------------------------------------------+

๐Ÿซถ last but not least: the initial counter nonce ICN value for each message encrypted under a given initial key must be chosen in a unique manner. no repeats, periodt ๐Ÿ’€

6.3.3. GCM-ACPKM-Master Authenticated Encryption Mode

okay so this section is where we glue โœจ GCM-ACPKM-Master ๐ŸŽ€ together, and bestie, it's giving main character energy ๐Ÿ’… ๐Ÿฆ‹

this mode is basically the classic authenticated encryption mode GCM (see [GCM]) ๐Ÿ’– with the ACPKM-Master re-keying mechanism ๐Ÿ”ฅ bolted on for the periodical key transformation. no cap, it's GCM with a glow-up ๐ŸŒธ

here are the parameters you can use ๐Ÿซถ :

  • n in {128, 256}.
  • 128 <= k <= 512.
  • The number c of bits in a specific part of the block to be incremented is such that 1 / 4 n <= c <= 1 / 2 n, c is a multiple of 8.
  • authentication tag length t.
  • the maximum message size m_max = min{N * ( n * 2^{n/2-1} / k), n * (2^c - 2), 2^{n/2} - 1}.

the key material K[j] used for the j-th section processing is equal to K^j, and |K^j| = k bits ๐Ÿงš

the GCM-ACPKM-Master encryption and decryption procedures are laid out in the boxes below ๐Ÿ’œ (they're shown verbatim, no cap, because implementers need every single character ๐Ÿ™ˆ)

+-------------------------------------------------------------------+
|  GHASH(X, H)                                                      |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - bit string X = X_1 | ... | X_m, X_i in V_n for i in {1, ... ,m}|
|  Output:                                                          |
|  - block GHASH(X, H) in V_n                                       |
|-------------------------------------------------------------------|
|  1. Y_0 = 0^n                                                     |
|  2. For i = 1, ... , m do                                         |
|         Y_i = (Y_{i-1} (xor) X_i) * H                             |
|  3. Return Y_m                                                    |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCTR(N, K, T*, ICB, X)                                           |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - master key frequency T*,                                       |
|  - initial counter block ICB,                                     |
|  - X = X_1 | ... | X_b.                                           |
|  Output:                                                          |
|  - Y in V_{|X|}.                                                  |
|-------------------------------------------------------------------|
|  1. If X in V_0, then return Y, where Y in V_0                    |
|  2. GCTR_1 = ICB                                                  |
|  3. For i = 2, ... , b do                                         |
|         GCTR_i = Inc_c(GCTR_{i-1})                                |
|  4. l = ceil(|X| / N)                                             |
|  5. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)                   |
|  6. For j = 1, ... , b do                                         |
|         i = ceil(j * n / N),                                      |
|         G_j = E_{K^i}(GCTR_j)                                     |
|  7. Y = X (xor) MSB_{|X|}(G_1 | ... | G_b)                        |
|  8. Return Y                                                      |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCM-ACPKM-Master-Encrypt(N, K, T*, ICN, P, A)                    |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - master key frequency T*,                                       |
|  - initial counter nonce ICN in V_{n-c},                          |
|  - plaintext P = P_1 | ... | P_b, |P| <= m_max.                   |
|  - additional authenticated data A.                               |
|  Output:                                                          |
|  - ciphertext C,                                                  |
|  - authentication tag T.                                          |
|-------------------------------------------------------------------|
|  1. K^1 = ACPKM-Master(T*, K, k, 1)                               |
|  2. H = E_{K^1}(0^n)                                              |
|  3. ICB_0 = ICN | 0^{c-1} | 1                                     |
|  4. C = GCTR(N, K, T*, Inc_c(ICB_0), P)                           |
|  5. u = n * ceil(|C| / n) - |C|                                   |
|     v = n * ceil(|A| / n) - |A|                                   |
|  6. S = GHASH(A | 0^v | C | 0^u | Vec_{n/2}(|A|) |                |
|               | Vec_{n/2}(|C|), H)                                |
|  7. T = MSB_t(E_{K^1}(ICB_0) (xor) S)                             |
|  8. Return C | T                                                  |
+-------------------------------------------------------------------+
+-------------------------------------------------------------------+
|  GCM-ACPKM-Master-Decrypt(N, K, T*, ICN, A, C, T)                 |
|-------------------------------------------------------------------|
|  Input:                                                           |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - master key frequency T*,                                       |
|  - initial counter nonce ICN in V_{n-c},                          |
|  - additional authenticated data A.                               |
|  - ciphertext C = C_1 | ... | C_b, |C| <= m_max,                  |
|  - authentication tag T.                                          |
|  Output:                                                          |
|  - plaintext P or FAIL.                                           |
|-------------------------------------------------------------------|
|  1. K^1 = ACPKM-Master(T*, K, k, 1)                               |
|  2. H = E_{K^1}(0^n)                                              |
|  3. ICB_0 = ICN | 0^{c-1} | 1                                     |
|  4. P = GCTR(N, K, T*, Inc_c(ICB_0), C)                           |
|  5. u = n * ceil(|C| / n) - |C|                                   |
|     v = n * ceil(|A| / n) - |A|                                   |
|  6. S = GHASH(A | 0^v | C | 0^u | Vec_{n/2}(|A|) |                |
|               | Vec_{n/2}(|C|), H)                                |
|  7. T' = MSB_t(E_{K^1}(ICB_0) (xor) S)                            |
|  8. If T = T', then return P; else return FAIL.                   |
+-------------------------------------------------------------------+

the * operation on (pairs of) the 2^n possible blocks corresponds to the multiplication operation for the binary Galois (finite) field of 2^n elements defined by the polynomial f as follows (by analogy with [GCM]) ๐ŸŒˆ

  • n = 128: f = a^128 + a^7 + a^2 + a^1 + 1,
  • n = 256: f = a^256 + a^10 + a^5 + a^2 + 1.

one last thing, and it's a big one ๐Ÿšจ the initial counter nonce ICN value for each message that is encrypted under the given initial key must be chosen in a unique manner ๐Ÿ’€ no reusing, no copy-pasting, bestie, every single message gets its own ICN ๐Ÿ”ฅ ๐Ÿ˜ญ

6.3.4. CBC-ACPKM-Master Encryption Mode ๐ŸŽ€

okay so this section defines CBC-ACPKM-Master ๐Ÿ’– which uses the ACPKM-Master internal re-keying mechanism for the periodical key transformation. the key keeps getting refreshed on a schedule while the mode keeps going.

ngl this one is basically the base CBC mode (see [MODES]) with the ACPKM-Master re-keying mechanism stapled on. main character energy ๐Ÿ’…

CBC-ACPKM-Master can be used with these parameters:

  • 64 <= n <= 512.
  • 128 <= k <= 512.
  • The maximum message size m_max = N * (n * 2^{n/2-1} / k).

bestie, the plaintext and ciphertext have to be a sequence of one or more complete data blocks ๐Ÿงฑ. if your data doesn't already fit that, it MUST be padded to form complete data blocks. the padding methods are out of scope for this doc, but there's an example in Appendix A of [MODES] if you're curious ๐ŸŒธ

the key material K[j] for the j-th section processing is K^j, with |K^j| = k bits ๐Ÿ”‘

we use D_{K} to mean the decryption function, which is the permutation inverse to E_{K} ๐Ÿงš

here's how the CBC-ACPKM-Master encryption and decryption procedures go ๐Ÿ‘‘

+----------------------------------------------------------------+
|  CBC-ACPKM-Master-Encrypt(N, K, T*, IV, P)                     |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - master key frequency T*,                                    |
|  - initialization vector IV in V_n,                            |
|  - plaintext P = P_1 | ... | P_b, |P_b| = n, |P| <= m_max.     |
|  Output:                                                       |
|  - ciphertext C.                                               |
|----------------------------------------------------------------|
|  1. l = ceil(|P| / N)                                          |
|  2. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)                |
|  3. C_0 = IV                                                   |
|  4. For j = 1, 2, ... , b do                                   |
|         i = ceil(j * n / N),                                   |
|         C_j = E_{K^i}(P_j (xor) C_{j-1})                       |
|  5. Return C = C_1 | ... | C_b                                 |
|----------------------------------------------------------------+

+----------------------------------------------------------------+
|  CBC-ACPKM-Master-Decrypt(N, K, T*, IV, C)                     |
|----------------------------------------------------------------|
|  Input:                                                        |
|  - section size N,                                             |
|  - initial key K,                                              |
|  - master key frequency T*,                                    |
|  - initialization vector IV in V_n,                            |
|  - ciphertext C = C_1 | ... | C_b, |C_b| = n, |C| <= m_max.    |
|  Output:                                                       |
|  - plaintext P.                                                |
|----------------------------------------------------------------|
|  1. l = ceil(|C| / N)                                          |
|  2. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)                |
|  3. C_0 = IV                                                   |
|  4. For j = 1, 2, ... , b do                                   |
|         i = ceil(j * n / N)                                    |
|         P_j = D_{K^i}(C_j) (xor) C_{j-1}                       |
|  5. Return P = P_1 | ... | P_b                                 |
+----------------------------------------------------------------+

the IV for any single run of the encryption process must be unpredictable ๐Ÿ™ˆ no shortcuts here, bestie ๐Ÿซถ

6.3.5. CFB-ACPKM-Master Encryption Mode ๐Ÿฆ‹

this section defines CFB-ACPKM-Master ๐ŸŒˆ which uses the ACPKM-Master internal re-keying mechanism for the periodical key transformation. same energy as the last one, just with CFB as the base.

so the CFB-ACPKM-Master encryption mode is the base CFB mode (see [MODES]) extended by the ACPKM-Master re-keying mechanism โœจ

CFB-ACPKM-Master can be used with these parameters:

  • 64 <= n <= 512.
  • 128 <= k <= 512.
  • The maximum message size m_max = N * (n * 2^{n/2-1} / k).

the key material K[j] for the j-th section processing is K^j, with |K^j| = k bits ๐Ÿ”‘

and here are the CFB-ACPKM-Master encryption and decryption procedures ๐Ÿ’œ

+-------------------------------------------------------------+
|  CFB-ACPKM-Master-Encrypt(N, K, T*, IV, P)                  |
|-------------------------------------------------------------|
|  Input:                                                     |
|  - section size N,                                          |
|  - initial key K,                                           |
|  - master key frequency T*,                                 |
|  - initialization vector IV in V_n,                         |
|  - plaintext P = P_1 | ... | P_b, |P| <= m_max.             |
|  Output:                                                    |
|  - ciphertext C.                                            |
|-------------------------------------------------------------|
|  1. l = ceil(|P| / N)                                       |
|  2. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)             |
|  3. C_0 = IV                                                |
|  4. For j = 1, 2, ... , b - 1 do                            |
|         i = ceil(j * n / N),                                |
|         C_j = E_{K^i}(C_{j-1}) (xor) P_j                    |
|  5. C_b = MSB_{|P_b|}(E_{K^l}(C_{b-1})) (xor) P_b           |
|  6. Return C = C_1 | ... | C_b                              |
|-------------------------------------------------------------+
+-------------------------------------------------------------+
|  CFB-ACPKM-Master-Decrypt(N, K, T*, IV, C)                  |
|-------------------------------------------------------------|
|  Input:                                                     |
|  - section size N,                                          |
|  - initial key K,                                           |
|  - master key frequency T*,                                 |
|  - initialization vector IV in V_n,                         |
|  - ciphertext C = C_1 | ... | C_b, |C| <= m_max.            |
|  Output:                                                    |
|  - plaintext P.                                             |
|-------------------------------------------------------------|
|  1. l = ceil(|C| / N)                                       |
|  2. K^1 | ... | K^l = ACPKM-Master(T*, K, k, l)             |
|  3. C_0 = IV                                                |
|  4. For j = 1, 2, ... , b - 1 do                            |
|         i = ceil(j * n / N),                                |
|         P_j = E_{K^i}(C_{j-1}) (xor) C_j                    |
|  5. P_b = MSB_{|C_b|}(E_{K^l}(C_{b-1})) (xor) C_b           |
|  6. Return P = P_1 | ... | P_b                              |
+-------------------------------------------------------------+

same rule as before: the IV for any particular execution of the encryption process must be unpredictable ๐Ÿ™ˆ

6.3.6. OMAC-ACPKM-Master Authentication Mode ๐Ÿ’…

this section defines an OMAC-ACPKM-Master message authentication code calculation mode ๐Ÿ” which uses the ACPKM-Master internal re-keying mechanism for the periodical key transformation.

the OMAC-ACPKM-Master mode is the base message authentication code calculation mode OMAC1, which is also known as CMAC (see [RFC4493]), extended by the ACPKM-Master re-keying mechanism ๐ŸŒธ

OMAC-ACPKM-Master can be used with these parameters:

  • n in {64, 128, 256}.
  • 128 <= k <= 512.
  • The maximum message size m_max = N * (n * 2^{n/2-1} / (k + n)).

the key material K[j] for one-section processing is K^j | K^j_1, where |K^j| = k bits and |K^j_1| = n bits ๐Ÿ”‘

here's the subkey generation process for OMAC ๐Ÿง

+-------------------------------------------------------------------+
| Generate_Subkey(K1, r)                                            |
|-------------------------------------------------------------------|
| Input:                                                            |
|  - key K1.                                                        |
|  Output:                                                          |
|  - key SK.                                                        |
|-------------------------------------------------------------------|
|   1. If r = n, then return K1                                     |
|   2. If r < n, then                                               |
|          if MSB_1(K1) = 0                                         |
|              return K1 << 1                                       |
|          else                                                     |
|              return (K1 << 1) (xor) R_n                           |
+-------------------------------------------------------------------+

here, R_n takes these values ๐Ÿ‘‘

  • n = 64: R_{64} = 0^{59} | 11011.
  • n = 128: R_{128} = 0^{120} | 10000111.
  • n = 256: R_{256} = 0^{145} | 10000100101.

and this is how the OMAC-ACPKM-Master message authentication code calculation mode is defined ๐Ÿฆ‹

+-------------------------------------------------------------------+
| OMAC-ACPKM-Master(K, N, T*, M)                                    |
|-------------------------------------------------------------------|
| Input:                                                            |
|  - section size N,                                                |
|  - initial key K,                                                 |
|  - master key frequency T*,                                       |
|  - plaintext M = M_1 | ... | M_b, |M| <= m_max.                   |
|  Output:                                                          |
|  - message authentication code T.                                 |
|-------------------------------------------------------------------|
| 1. C_0 = 0^n                                                      |
| 2. l = ceil(|M| / N)                                              |
| 3. K^1 | K^1_1 | ... | K^l | K^l_1 =                              |
                     = ACPKM-Master(T*, K, (k + n), l)                 |
| 4. For j = 1, 2, ... , b - 1 do                                   |
|        i = ceil(j * n / N),                                       |
|        C_j = E_{K^i}(M_j (xor) C_{j-1})                           |
| 5. SK = Generate_Subkey(K^l_1, |M_b|)                             |
| 6. If |M_b| = n, then M*_b = M_b                                  |
|                  else M*_b = M_b | 1 | 0^{n - 1 -|M_b|}           |
| 7. T = E_{K^l}(M*_b (xor) C_{b-1} (xor) SK)                       |
| 8. Return T                                                       |
+-------------------------------------------------------------------+

7. Joint Usage of External and Internal Re-keying ๐ŸŽ€

okay so external re-keying and internal re-keying both have their own pros and cons (we covered those in Section 1 ๐Ÿ’…). external re-keying can basically limit the message length, while with internal re-keying the section size (picked as big as your operational properties allow) limits how many separate messages you can send. so which one you pick depends on your protocol's features ๐Ÿงš but ngl some protocols need the best of both worlds. like, the protocol mostly sends short messages but also has to handle really long ones. in that case you use external and internal re-keying together, because they cancel out each other's downsides โœจ

any mechanism from Section 5 can be combined with any mechanism from Section 6 ๐Ÿฆ‹

let's look at an example: the GCM-ACPKM mode with external serial re-keying based on a KDF on a hash function. we call the number of messages in each frame (for the implicit approach to key lifetime control) the frame size for external re-keying. ๐Ÿ’œ

let L be the key lifetime limitation. the section size N for internal re-keying and the frame size q for external re-keying must be chosen so that q * N must not exceed L ๐Ÿ™ˆ

now say t messages (ICN_i, P_i, A_i) are going to be processed before renegotiation, where each one has its own initial counter nonce ICN_i, plaintext P_i, and additional authenticated data A_i. for authenticated encryption of each message, with i = 1, ..., t, you can use this algorithm:

1. j = ceil(i / q),
2. K^j = ExtSerialH(K, j),
3. C_i | T_i = GCM-ACPKM-Encrypt(N, K^j, ICN_i, P_i, A_i).
heads up bestie: nonces ICN_i that are used under the same frame key must be unique for each message ๐Ÿšจ

8. Security Considerations ๐Ÿ’€

okay this section is the serious part so read it carefully ๐Ÿซถ re-keying should be used to boost the a priori security properties of ciphers in hostile environments (e.g., with side-channel adversaries). if efficient attacks on a cipher are already known, the cipher must not be used. so re-keying cannot be used as a patch for vulnerable ciphers, periodt ๐Ÿ’… base cipher properties must be well analyzed, because the security of re-keying mechanisms is based on the security of a block cipher as a pseudorandom function.

re-keying is not intended to solve any postquantum security issues for symmetric cryptography. the reduction of security caused by Grover's algorithm isn't connected to the size of the plaintext transformed by a cipher (only a negligible amount of material, enough for key uniqueness, is needed). the whole point of re-keying is to limit the size of plaintext transformed under one initial key, so it's a different problem ๐Ÿ”ฅ

re-keying can provide backward security only if previous key material is securely deleted after usage by all parties. ๐Ÿ˜ญ


9. IANA Considerations ๐ŸŒธ

this document has no IANA actions. nothing to register, nothing to update, we're literally chilling ๐Ÿงš


10. References ๐Ÿ“š

10.1. Normative References

these are the must-read sources the spec leans on ๐Ÿ’œ

10.2. Informative References

these are the extra reading bits for the curious ๐Ÿฆ‹๐Ÿง 


Appendix A. Test Examples ๐Ÿงช

A.1. Test Examples for External Re-keying ๐Ÿ’–

A.1.1. External Re-keying with a Parallel Construction โœจ

okay bestie, first up is the parallel construction ๐ŸŽ€ here's the AES-256 one:

External re-keying with a parallel construction based on AES-256
****************************************************************
k = 256
t = 128

Initial key:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00

K^1:
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1

K^2:
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15
B8 02 92 32 D8 D3 8D 73 FE DC DD C6 C8 36 78 BD

K^3:
B6 40 24 85 A4 24 BD 35 B4 26 43 13 76 26 70 B6
5B F3 30 3D 3B 20 EB 14 D1 3B B7 91 74 E3 DB EC

...

K^126:
2F 3F 15 1B 53 88 23 CD 7D 03 FC 3D FD B3 57 5E
23 E4 1C 4E 46 FF 6B 33 34 12 27 84 EF 5D 82 23

K^127:
8E 51 31 FB 0B 64 BB D0 BC D4 C5 7B 1C 66 EF FD
97 43 75 10 6C AF 5D 5E 41 E0 17 F4 05 63 05 ED

K^128:
77 4F BF B3 22 60 C5 3B A3 8E FE B1 96 46 76 41
94 49 AF 84 2D 84 65 A7 F4 F7 2C DC A4 9D 84 F9

and now the SHA-256 version, which is very much giving ๐Ÿ’…

External re-keying with a parallel construction based on SHA-256
****************************************************************
k = 256
t = 128

label:
SHA2label
Initial key:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00

K^1:
C1 A1 4C A0 30 29 BE 43 9F 35 3C 79 1A 51 48 57
26 7A CD 5A E8 7D E7 D1 B2 E2 C7 AF A4 29 BD 35

K^2:
03 68 BB 74 41 2A 98 ED C4 7B 94 CC DF 9C F4 9E
A9 B8 A9 5F 0E DC 3C 1E 3B D2 59 4D D1 75 82 D4

K^3:
2F D3 68 D3 A7 8F 91 E6 3B 68 DC 2B 41 1D AC 80
0A C3 14 1D 80 26 3E 61 C9 0D 24 45 2A BD B1 AE

...

K^126:
55 AC 2B 25 00 78 3E D4 34 2B 65 0E 75 E5 8B 76
C8 04 E9 D3 B6 08 7D C0 70 2A 99 A4 B5 85 F1 A1

K^127:
77 4D 15 88 B0 40 90 E5 8C 6A D7 5D 0F CF 0A 4A
6C 23 F1 B3 91 B1 EF DF E5 77 64 CD 09 F5 BC AF

K^128:
E5 81 FF FB 0C 90 88 CD E5 F4 A5 57 B6 AB D2 2E
94 C3 42 06 41 AB C1 72 66 CC 2F 59 74 9C 86 B3

A.1.2. External Re-keying with a Serial Construction ๐Ÿฆ‹

here's the serial one! AES-256 first:

External re-keying with a serial construction based on AES-256
**************************************************************
AES 256 examples:
k = 256
t = 128

Initial key:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00

K*_1:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
K^1:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

K*_2:
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15

K^2:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

K*_3:
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15

K^3:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

...

K*_126:
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15

K^126:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

K*_127:
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15

K^127:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

K*_128:
64 7D 5C D5 1C 3D 62 98 BC 09 B1 D8 64 EC D9 B1
6F ED F5 D3 77 57 48 75 35 2B 5F 4D B6 5B E0 15

K^128:
66 B8 BD E5 90 6C EC DF FA 8A B2 FD 92 84 EB F0
51 16 8A B6 C8 A8 38 65 54 85 31 A5 D2 BA C3 86

and the SHA-256 serial version, which is an absolute mood ๐ŸŒˆ

External re-keying with a serial construction based on SHA-256
**************************************************************
k = 256
t = 128

Initial key:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00

label1:
SHA2label1

label2:
SHA2label2

K*_1:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00

K^1:
2D A8 D1 37 6C FD 52 7F F7 36 A4 E2 81 C6 0A 9B
F3 8E 66 97 ED 70 4F B5 FB 10 33 CC EC EE D5 EC

K*_2:
14 65 5A D1 7C 19 86 24 9B D3 56 DF CC BE 73 6F
52 62 4A 9D E3 CC 40 6D A9 48 DA 5C D0 68 8A 04

K^2:
2F EA 8D 57 2B EF B8 89 42 54 1B 8C 1B 3F 8D B1
84 F9 56 C7 FE 01 11 99 1D FB 98 15 FE 65 85 CF

K*_3:
18 F0 B5 2A D2 45 E1 93 69 53 40 55 43 70 95 8D
70 F0 20 8C DF B0 5D 67 CD 1B BF 96 37 D3 E3 EB

K^3:
53 C7 4E 79 AE BC D1 C8 24 04 BF F6 D7 B1 AC BF
F9 C0 0E FB A8 B9 48 29 87 37 E1 BA E7 8F F7 92

...

K*_126:
A3 6D BF 02 AA 0B 42 4A F2 C0 46 52 68 8B C7 E6
5E F1 62 C3 B3 2F DD EF E4 92 79 5D BB 45 0B CA

K^126:
6C 4B D6 22 DC 40 48 0F 29 C3 90 B8 E5 D7 A7 34
23 4D 34 65 2C CE 4A 76 2C FE 2A 42 C8 5B FE 9A
K*_127:
84 5F 49 3D B8 13 1D 39 36 2B BE D3 74 8F 80 A1
05 A7 07 37 BA 15 72 E0 73 49 C2 67 5D 0A 28 A1

K^127:
57 F0 BD 5A B8 2A F3 6B 87 33 CF F7 22 62 B4 D0
F0 EE EF E1 50 74 E5 BA 13 C1 23 68 87 36 29 A2

K*_128:
52 F2 0F 56 5C 9C 56 84 AF 69 AD 45 EE B8 DA 4E
7A A6 04 86 35 16 BA 98 E4 CB 46 D2 E8 9A C1 09

K^128:
9B DD 24 7D F3 25 4A 75 E0 22 68 25 68 DA 9D D5
C1 6D 2D 2B 4F 3F 1F 2B 5E 99 82 7F 15 A1 4F A4

A.2. Test Examples for Internal Re-keying ๐ŸŒธ

now we're getting into the internal re-keying vibes, and the test vectors are sooo detailed ๐Ÿ˜ญ

A.2.1. Internal Re-keying Mechanisms that Do Not Require a Master Key ๐Ÿ’œ

first up is CTR-ACPKM with AES-256:

CTR-ACPKM mode with AES-256
***************************
k = 256
n = 128
c = 64
N = 256

Initial key K:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Plaintext P:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88
00010:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A
00020:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00
00030:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11
00040:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22
00050:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33
00060:   55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 44

ICN:
12 34 56 78 90 AB CE F0 A1 B2 C3 D4 E5 F0 01 12
23 34 45 56 67 78 89 90 12 13 14 15 16 17 18 19

D_1:
00000:   80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
D_2:
00000:   90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F

Section_1

Section key K^1:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Input block CTR_1:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 00

Output block G_1:
00000:   FD 7E F8 9A D9 7E A4 B8 8D B8 B5 1C 1C 9D 6D D0

Input block CTR_2:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 01

Output block G_2:
00000:   19 98 C5 71 76 37 FB 17 11 E4 48 F0 0C 0D 60 B2

Section_2

Section key K^2:
00000:   F6 80 D1 21 2F A4 3D F4 EC 3A 91 DE 2A B1 6F 1B
00010:   36 B0 48 8A 4F C1 2E 09 98 D2 E4 A8 88 E8 4F 3D

Input block CTR_3:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 02

Output block G_3:
00000:   E4 88 89 4F B6 02 87 DB 77 5A 07 D9 2C 89 46 EA

Input block CTR_4:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 03

Output block G_4:
00000:   BC 4F 87 23 DB F0 91 50 DD B4 06 C3 1D A9 7C A4

Section_3

Section key K^3:
00000:   8E B9 7E 43 27 1A 42 F1 CA 8E E2 5F 5C C7 C8 3B
00010:   1A CE 9E 5E D0 6A A5 3B 57 B9 6A CF 36 5D 24 B8

Input block CTR_5:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 04
Output block G_5:
00000:   68 6F 22 7D 8F B2 9C BD 05 C8 C3 7D 22 FE 3B B7

Input block CTR_6:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 05

Output block G_6:
00000:   C0 1B F9 7F 75 6E 12 2F 80 59 55 BD DE 2D 45 87

Section_4

Section key K^4:
00000:   C5 71 6C C9 67 98 BC 2D 4A 17 87 B7 8A DF 94 AC
00010:   E8 16 F8 0B DB BC AD 7D 60 78 12 9C 0C B4 02 F5

Block number 7:

Input block CTR_7:
00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 06

Output block G_7:
00000:   03 DE 34 74 AB 9B 65 8A 3B 54 1E F8 BD 2B F4 7D


The result G = G_1 | G_2 | G_3 | G_4 | G_5 | G_6 | G_7:
00000:   FD 7E F8 9A D9 7E A4 B8 8D B8 B5 1C 1C 9D 6D D0
00010:   19 98 C5 71 76 37 FB 17 11 E4 48 F0 0C 0D 60 B2
00020:   E4 88 89 4F B6 02 87 DB 77 5A 07 D9 2C 89 46 EA
00030:   BC 4F 87 23 DB F0 91 50 DD B4 06 C3 1D A9 7C A4
00040:   68 6F 22 7D 8F B2 9C BD 05 C8 C3 7D 22 FE 3B B7
00050:   C0 1B F9 7F 75 6E 12 2F 80 59 55 BD DE 2D 45 87
00060:   03 DE 34 74 AB 9B 65 8A 3B 54 1E F8 BD 2B F4 7D

The result ciphertext C = P (xor) MSB_{|P|}(G):
00000:   EC 5C CB DE 8C 18 D3 B8 72 56 68 D0 A7 37 F4 58
00010:   19 89 E7 42 32 62 9D 60 99 7D E2 4B C0 E3 9F B8
00020:   F5 AA BA 0B E3 64 F0 53 EE F0 BC 15 C2 76 4C EA
00030:   9E 7C C3 76 BD 87 19 C9 77 0F CA 2D E2 A3 7C B5
00040:   5B 2B 77 1B F8 3A 05 17 BE 04 2D 82 28 FE 2A 95
00050:   84 4E 9F 08 FD F7 B8 94 4C B7 AA B7 DE 3C 67 B4
00060:   56 B8 43 FC 32 31 DE 46 D5 AB 14 F8 AC 09 C7 39

and then GCM-ACPKM with AES-128, which is sooo pretty ๐Ÿงš

GCM-ACPKM mode with AES-128
***************************
k = 128
n = 128
c = 32
N = 256

Initial key K:
00000:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Additional data A:
00000:   11 22 33

Plaintext:
00000:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00010:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00020:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

ICN:
00000:   00 00 00 00 00 00 00 00 00 00 00 00

Number of sections: 2

Section key K^1:
00000:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Section key K^2:
00000:   15 1A 9F B0 B6 AC C5 97 6A FB 50 31 D1 DE C8 41

Encrypted GCTR_1 | GCTR_2 | GCTR_3:
00000:   03 88 DA CE 60 B6 A3 92 F3 28 C2 B9 71 B2 FE 78
00010:   F7 95 AA AB 49 4B 59 23 F7 FD 89 FF 94 8B C1 E0
00020:   D6 B3 12 46 E9 CE 9F F1 3A B3 42 7E E8 91 96 AD

Ciphertext C:
00000:   03 88 DA CE 60 B6 A3 92 F3 28 C2 B9 71 B2 FE 78
00010:   F7 95 AA AB 49 4B 59 23 F7 FD 89 FF 94 8B C1 E0
00020:   D6 B3 12 46 E9 CE 9F F1 3A B3 42 7E E8 91 96 AD

GHASH input:
00000:   11 22 33 00 00 00 00 00 00 00 00 00 00 00 00 00
00010:   03 88 DA CE 60 B6 A3 92 F3 28 C2 B9 71 B2 FE 78
00020:   F7 95 AA AB 49 4B 59 23 F7 FD 89 FF 94 8B C1 E0
00030:   D6 B3 12 46 E9 CE 9F F1 3A B3 42 7E E8 91 96 AD
00040:   00 00 00 00 00 00 00 18 00 00 00 00 00 00 01 80

GHASH output S:
00000:   E8 ED E9 94 9A DD 55 30 B0 F4 4E F5 00 FC 3E 3C
Authentication tag  T:
00000:   B0 0F 15 5A 60 A3 65 51 86 8B 53 A2 A4 1B 7B 66

The result C | T:
00000:   03 88 DA CE 60 B6 A3 92 F3 28 C2 B9 71 B2 FE 78
00010:   F7 95 AA AB 49 4B 59 23 F7 FD 89 FF 94 8B C1 E0
00020:   D6 B3 12 46 E9 CE 9F F1 3A B3 42 7E E8 91 96 AD
00030:   B0 0F 15 5A 60 A3 65 51 86 8B 53 A2 A4 1B 7B 66

A.2.2. Internal Re-keying Mechanisms with a Master Key ๐ŸŽ€

last but not least, the master key one! CTR-ACPKM-Master with AES-256:

CTR-ACPKM-Master mode with AES-256
**********************************
k = 256
n = 128
c for CTR-ACPKM mode = 64
c for CTR-ACPKM-Master mode = 64
N = 256
T* = 512

Initial key K:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Initial vector ICN:
00000:   12 34 56 78 90 AB CE F0 A1 B2 C3 D4 E5 F0 01 12

Plaintext P:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88
00010:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A
00020:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00
00030:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11
00040:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22
00050:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33
00060:   55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 44

Okay bestie, the keys are about to get SO cute ๐ŸŽ€๐Ÿ’–

   K^1 | K^2 | K^3 | K^4:
   00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
   00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60
   00020:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
   00030:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3
   00040:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
   00050:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94
   00060:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
   00070:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12
   Section_1

   K^1:
   00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
   00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60

   Input block CTR_1:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 00

   Output block G_1:
   00000:   8C A2 B6 82 A7 50 65 3F 8E BF 08 E7 9F 99 4D 5C

   Input block CTR_2:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 01

   Output block G_2:
   00000:   F6 A6 A5 BA 58 14 1E ED 23 DC 31 68 D2 35 89 A1


   Section_2

   K^2:
   00000:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
   00010:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3

   Input block CTR_3:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 02

   Output block G_3:
   00000:   4A 07 5F 86 05 87 72 94 1D 8E 7D F8 32 F4 23 71

   Input block CTR_4:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 03

   Output block G_4:
   00000:   23 35 66 AF 61 DD FE A7 B1 68 3F BA B0 52 4A D7


   Section_3

   K^3:
   00000:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
   00010:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94

   Input block CTR_5:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 04
   Output block G_5:
   00000:   A8 09 6D BC E8 BB 52 FC DE 6E 03 70 C1 66 95 E8

   Input block CTR_6:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 05

   Output block G_6:
   00000:   C6 E3 6E 8E 5B 82 AA C4 A6 6C 14 8D B1 F6 9B EF


   Section_4

   K^4:
   00000:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
   00010:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12

   Input block CTR_7:
   00000:   12 34 56 78 90 AB CE F0 00 00 00 00 00 00 00 06

   Output block G_7:
   00000:   82 2B E9 07 96 37 44 95 75 36 3F A7 07 F8 40 22


   The result G = G_1 | G_2 | G_3 | G_4 | G_5 | G_6 | G_7:
   00000:   8C A2 B6 82 A7 50 65 3F 8E BF 08 E7 9F 99 4D 5C
   00010:   F6 A6 A5 BA 58 14 1E ED 23 DC 31 68 D2 35 89 A1
   00020:   4A 07 5F 86 05 87 72 94 1D 8E 7D F8 32 F4 23 71
   00030:   23 35 66 AF 61 DD FE A7 B1 68 3F BA B0 52 4A D7
   00040:   A8 09 6D BC E8 BB 52 FC DE 6E 03 70 C1 66 95 E8
   00050:   C6 E3 6E 8E 5B 82 AA C4 A6 6C 14 8D B1 F6 9B EF
   00060:   82 2B E9 07 96 37 44 95 75 36 3F A7 07 F8 40 22

   The result ciphertext C = P (xor) MSB_{|P|}(G):
   00000:   9D 80 85 C6 F2 36 12 3F 71 51 D5 2B 24 33 D4 D4
   00010:   F6 B7 87 89 1C 41 78 9A AB 45 9B D3 1E DB 76 AB
   00020:   5B 25 6C C2 50 E1 05 1C 84 24 C6 34 DC 0B 29 71
   00030:   01 06 22 FA 07 AA 76 3E 1B D3 F3 54 4F 58 4A C6
   00040:   9B 4D 38 DA 9F 33 CB 56 65 A2 ED 8F CB 66 84 CA
   00050:   82 B6 08 F9 D3 1B 00 7F 6A 82 EB 87 B1 E7 B9 DC
   00060:   D7 4D 9E 8F 0F 9D FF 59 9B C9 35 A7 16 DA 73 66

Next up is GCM-ACPKM-Master with AES-256, and this part is giving main character energy โœจ๐Ÿฆ‹

GCM-ACPKM-Master mode with AES-256
**********************************
k = 192
n = 128
c for the CTR-ACPKM mode = 64
c for the GCM-ACPKM-Master mode = 32
T* = 384
N = 256

Initial key K:
00000:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00010:   00 00 00 00 00 00 00 00

Additional data A:
00000:   11 22 33

Plaintext:
00000:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00010:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00020:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00030:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00040:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

ICN:
00000:   00 00 00 00 00 00 00 00 00 00 00 00

Number of sections: 3

K^1 | K^2 | K^3:
00000:   93 BA AF FB 35 FB E7 39 C1 7C 6A C2 2E EC F1 8F
00010:   7B 89 F0 BF 8B 18 07 05 96 48 68 9F 36 A7 65 CC
00020:   CD 5D AC E2 0D 47 D9 18 D7 86 D0 41 A8 3B AB 99
00030:   F5 F8 B1 06 D2 71 78 B1 B0 08 C9 99 0B 72 E2 87
00040:   5A 2D 3C BE F1 6E 67 3C

Encrypted GCTR_1 | ... | GCTR_5
00000:   43 FA 71 81 64 B1 E3 D7 1E 7B 65 39 A7 02 1D 52
00010:   69 9B 9E 1B 43 24 B7 52 95 74 E7 90 F2 BE 60 E8
00020:   11 62 C9 90 2A 2B 77 7F D9 6A D6 1A 99 E0 C6 DE
00030:   4B 91 D4 29 E3 1A 8C 11 AF F0 BC 47 F6 80 AF 14
00040:   40 1C C1 18 14 63 8E 76 24 83 37 75 16 34 70 08

Ciphertext C:
00000:   43 FA 71 81 64 B1 E3 D7 1E 7B 65 39 A7 02 1D 52
00010:   69 9B 9E 1B 43 24 B7 52 95 74 E7 90 F2 BE 60 E8
00020:   11 62 C9 90 2A 2B 77 7F D9 6A D6 1A 99 E0 C6 DE
00030:   4B 91 D4 29 E3 1A 8C 11 AF F0 BC 47 F6 80 AF 14
00040:   40 1C C1 18 14 63 8E 76 24 83 37 75 16 34 70 08
GHASH input:
00000:   11 22 33 00 00 00 00 00 00 00 00 00 00 00 00 00
00010:   43 FA 71 81 64 B1 E3 D7 1E 7B 65 39 A7 02 1D 52
00020:   69 9B 9E 1B 43 24 B7 52 95 74 E7 90 F2 BE 60 E8
00030:   11 62 C9 90 2A 2B 77 7F D9 6A D6 1A 99 E0 C6 DE
00040:   4B 91 D4 29 E3 1A 8C 11 AF F0 BC 47 F6 80 AF 14
00050:   40 1C C1 18 14 63 8E 76 24 83 37 75 16 34 70 08
00060:   00 00 00 00 00 00 00 18 00 00 00 00 00 00 02 80

GHASH output S:
00000:   6E A3 4B D5 6A C5 40 B7 3E 55 D5 86 D1 CC 09 7D

Authentication tag  T:
00050:   CC 3A BA 11 8C E7 85 FD 77 78 94 D4 B5 20 69 F8

The result C | T:
00000:   43 FA 71 81 64 B1 E3 D7 1E 7B 65 39 A7 02 1D 52
00010:   69 9B 9E 1B 43 24 B7 52 95 74 E7 90 F2 BE 60 E8
00020:   11 62 C9 90 2A 2B 77 7F D9 6A D6 1A 99 E0 C6 DE
00030:   4B 91 D4 29 E3 1A 8C 11 AF F0 BC 47 F6 80 AF 14
00040:   40 1C C1 18 14 63 8E 76 24 83 37 75 16 34 70 08
00050:   CC 3A BA 11 8C E7 85 FD 77 78 94 D4 B5 20 69 F8

Now CBC-ACPKM-Master with AES-256, and it's a whole vibe ๐Ÿ’…๐ŸŒธ

CBC-ACPKM-Master mode with AES-256
**********************************
k = 256
n = 128
c for the CTR-ACPKM mode = 64
N = 256
T* = 512

Initial key K:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Initial vector IV:
00000:   12 34 56 78 90 AB CE F0 A1 B2 C3 D4 E5 F0 01 12

Plaintext P:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88
00010:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A
00020:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00
00030:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11
00040:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22
00050:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33
00060:   55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 44
K^1 | K^2 | K^3 | K^4:
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60
00020:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
00030:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3
00040:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
00050:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94
00060:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00070:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12

Section_1

K^1:
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60

Plaintext block P_1:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88

Input block P_1 (xor) C_0:
00000:   03 16 65 3C C5 CD B9 F0 5E 5C 1E 18 5E 5A 98 9A

Output block C_1:
00000:   59 CB 5B CA C2 69 2C 60 0D 46 03 A0 C7 40 C9 7C

Plaintext block P_2:
00000:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A

Input block P_2 (xor) C_1:
00000:   59 DA 79 F9 86 3C 4A 17 85 DF A9 1B 0B AE 36 76

Output block C_2:
00000:   80 B6 02 74 54 8B F7 C9 78 1F A1 05 8B F6 8B 42

Section_2

K^2:
00000:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
00010:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3

Plaintext block P_3:
00000:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00

Input block P_3 (xor) C_2:
00000:   91 94 31 30 01 ED 80 41 E1 B5 1A C9 65 09 81 42

Output block C_3:
00000:   8C 24 FB CF 68 15 B1 AF 65 FE 47 75 95 B4 97 59
Plaintext block P_4:
00000:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11

Input block P_4 (xor) C_3:
00000:   AE 17 BF 9A 0E 62 39 36 CF 45 8B 9B 6A BE 97 48

Output block C_4:
00000:   19 65 A5 00 58 0D 50 23 72 1B E9 90 E1 83 30 E9

Section_3

K^3:
00000:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
00010:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94

Plaintext block P_5:
00000:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22

Input block P_5 (xor) C_4:
00000:   2A 21 F0 66 2F 85 C9 89 C9 D7 07 6F EB 83 21 CB

Output block C_5:
00000:   56 D8 34 F4 6F 0F 4D E6 20 53 A9 5C B5 F6 3C 14

Plaintext block P_6:
00000:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33

Input block P_6 (xor) C_5:
00000:   12 8D 52 83 E7 96 E7 5D EC BD 56 56 B5 E7 1E 27

Output block C_6:
00000:   66 68 2B 8B DD 6E B2 7E DE C7 51 D6 2F 45 A5 45

Section_4

K^4:
00000:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00010:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12

Plaintext block P_7:
00000:   55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 44

Input block P_7 (xor) C_6:
00000:   33 0E 5C 03 44 C4 09 B2 30 38 5B D6 3E 67 96 01

Output block C_7:
00000:   7F 4D 87 F9 CA E9 56 09 79 C4 FA FE 34 0B 45 34
Ciphertext C:
00000:   59 CB 5B CA C2 69 2C 60 0D 46 03 A0 C7 40 C9 7C
00010:   80 B6 02 74 54 8B F7 C9 78 1F A1 05 8B F6 8B 42
00020:   8C 24 FB CF 68 15 B1 AF 65 FE 47 75 95 B4 97 59
00030:   19 65 A5 00 58 0D 50 23 72 1B E9 90 E1 83 30 E9
00040:   56 D8 34 F4 6F 0F 4D E6 20 53 A9 5C B5 F6 3C 14
00050:   66 68 2B 8B DD 6E B2 7E DE C7 51 D6 2F 45 A5 45
00060:   7F 4D 87 F9 CA E9 56 09 79 C4 FA FE 34 0B 45 34

Last bit of this part: CFB-ACPKM-Master with AES-256, and it's giving pure elegance ๐Ÿงš๐Ÿ’œ

CFB-ACPKM-Master mode with AES-256
**********************************
k = 256
n = 128
c for the CTR-ACPKM mode = 64
N = 256
T* = 512

Initial key K:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Initial vector IV:
00000:   12 34 56 78 90 AB CE F0 A1 B2 C3 D4 E5 F0 01 12

Plaintext P:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88
00010:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A
00020:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00
00030:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11
00040:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22
00050:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33
00060:   55 66 77 88 99 AA BB CC

K^1 | K^2 | K^3 | K^4
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60
00020:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
00030:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3
00040:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
00050:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94
00060:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00070:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12
Section_1

K^1:
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60

Plaintext block P_1:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88

Encrypted block E_{K^1}(C_0):
00000:   1C 39 9D 59 F8 5D 91 91 A9 D2 12 9F 63 15 90 03

Output block C_1 = E_{K^1}(C_0) (xor) P_1:
00000:   0D 1B AE 1D AD 3B E6 91 56 3C CF 53 D8 BF 09 8B

Plaintext block P_2:
00000:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A

Encrypted block E_{K^1}(C_1):
00000:   6B A2 C5 42 52 69 C6 0B 15 14 06 87 90 46 F6 2E

Okay, the test vectors keep going, and the numbers are giving me chills ๐Ÿฆ‹

Output block C_2 = E_{K^1}(C_1) (xor) P_2:
00000:   6B B3 E7 71 16 3C A0 7C 9D 8D AC 3C 5C A8 09 24

Section_2

K^2:
00000:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
00010:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3

Plaintext block P_3:
00000:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00

Encrypted block E_{K^2}(C_2):
00000:   95 45 5F DB C3 9E 0A 13 9F CB 10 F5 BD 79 A3 88

Output block C_3 = E_{K^2}(C_2) (xor) P_3:
00000:   84 67 6C 9F 96 F8 7D 9B 06 61 AB 39 53 86 A9 88

Plaintext block P_4:
00000:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11

Encrypted block E_{K^2}(C_3):
00000:   E0 AA 32 5D 80 A4 47 95 BA 42 BF 63 F8 4A C8 B2

Output block C_4 = E_{K^2}(C_3) (xor) P_4:
00000:   C2 99 76 08 E6 D3 CF 0C 10 F9 73 8D 07 40 C8 A3
Section_3

K^3:
00000:   E8 76 2B 30 8B 08 EB CE 3E 93 9A C2 C0 3E 76 D4
00010:   60 9A AB D9 15 33 13 D3 CF D3 94 E7 75 DF 3A 94

Plaintext block P_5:
00000:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22

Encrypted block E_{K^3}(C_4):
00000:   FE 42 8C 70 C2 51 CE 13 36 C1 BF 44 F8 49 66 89

Output block C_5 = E_{K^3}(C_4) (xor) P_5:
00000:   CD 06 D9 16 B5 D9 57 B9 8D 0D 51 BB F2 49 77 AB

Plaintext block P_6:
00000:   44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33

Encrypted block E_{K^3}(C_5):
00000:   01 24 80 87 86 18 A5 43 11 0A CC B5 0A E5 02 A3

Output block C_6 = E_{K^3}(C_5) (xor) P_6:
00000:   45 71 E6 F0 0E 81 0F F8 DD E4 33 BF 0A F4 20 90

Section_4

K^4:
00000:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00010:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12

Plaintext block P_7:
00000:   55 66 77 88 99 AA BB CC

Encrypted block MSB_{|P_7|}(E_{K^4}(C_6)):
00000:   97 5C 96 37 55 1E 8C 7F

Output block C_7 = MSB_{|P_7|}(E_{K^4}(C_6)) (xor) P_7
00000:   C2 3A E1 BF CC B4 37 B3

Ciphertext C:
00000:   0D 1B AE 1D AD 3B E6 91 56 3C CF 53 D8 BF 09 8B
00010:   6B B3 E7 71 16 3C A0 7C 9D 8D AC 3C 5C A8 09 24
00020:   84 67 6C 9F 96 F8 7D 9B 06 61 AB 39 53 86 A9 88
00030:   C2 99 76 08 E6 D3 CF 0C 10 F9 73 8D 07 40 C8 A3
00040:   CD 06 D9 16 B5 D9 57 B9 8D 0D 51 BB F2 49 77 AB
00050:   45 71 E6 F0 0E 81 0F F8 DD E4 33 BF 0A F4 20 90
00060:   C2 3A E1 BF CC B4 37 B3

Now the OMAC-ACPKM-Master run with AES-256 setup, which is the parameter list and all the starting inputs bestie needs ๐Ÿ’…

OMAC-ACPKM-Master mode with AES-256
***********************************
k = 256
n = 128
c for the CTR-ACPKM mode = 64
N = 256
T* = 768

Initial key K:
00000:   88 99 AA BB CC DD EE FF 00 11 22 33 44 55 66 77
00010:   FE DC BA 98 76 54 32 10 01 23 45 67 89 AB CD EF

Plaintext M:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88
00010:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A
00020:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00
00030:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11
00040:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22

K^1 | K^1_1 | K^2 | K^2_1 | K^3 | K^3_1:
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60
00020:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0
00030:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3
00040:   9D CC 66 42 0D FF 45 5B 21 F3 93 F0 D4 D6 6E 67
00050:   BB 1B 06 0B 87 66 6D 08 7A 9D A7 49 55 C3 5B 48
00060:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00070:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12
00080:   78 21 C7 C7 6C BD 79 63 56 AC F8 8E 69 6A 00 07

Section_1

K^1:
00000:   9F 10 BB F1 3A 79 FB BD 4A 4C A8 64 C4 90 74 64
00010:   39 FE 50 6D 4B 86 9B 21 03 A3 B6 A4 79 28 3C 60

K^1_1:
00000:   77 91 17 50 E0 D1 77 E5 9A 13 78 2B F1 89 08 D0

Plaintext block M_1:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88

Input block M_1 (xor) C_0:
00000:   11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88

Output block C_1:
00000:   0B A5 89 BF 55 C1 15 42 53 08 89 76 A0 FE 24 3E
Plaintext block M_2:
00000:   00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A

Input block M_2 (xor) C_1:
00000:   0B B4 AB 8C 11 94 73 35 DB 91 23 CD 6C 10 DB 34

Output block C_2:
00000:   1C 53 DD A3 6D DC E1 17 ED 1F 14 09 D8 6A F3 2C

Section_2 is next, and the key schedule gets spicy here ๐Ÿ”ฅ

Section_2

K^2:
00000:   AB 6B 59 EE 92 49 05 B3 AB C7 A4 E3 69 65 76 C3
00010:   9D CC 66 42 0D FF 45 5B 21 F3 93 F0 D4 D6 6E 67

K^2_1:
00000:   BB 1B 06 0B 87 66 6D 08 7A 9D A7 49 55 C3 5B 48

Plaintext block M_3:
00000:   11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00

Input block M_3 (xor) C_2:
00000:   0D 71 EE E7 38 BA 96 9F 74 B5 AF C5 36 95 F9 2C

Output block C_3:
00000:   4E D4 BC A6 CE 6D 6D 16 F8 63 85 13 E0 48 59 75

Plaintext block M_4:
00000:   22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11

Input block M_4 (xor) C_3:
00000:   6C E7 F8 F3 A8 1A E5 8F 52 D8 49 FD 1F 42 59 64

Output block C_4:
00000:   B6 83 E3 96 FD 30 CD 46 79 C1 8B 24 03 82 1D 81

Section_3, and this is the last stretch of the message-authentication part ๐Ÿฆ‹

Section_3

K^3:
00000:   F2 EE 91 45 6B DC 3D E4 91 2C 87 C3 29 CF 31 A9
00010:   2F 20 2E 5A C4 9A 2A 65 31 33 D6 74 8C 4F F9 12

K^3_1:
00000:   78 21 C7 C7 6C BD 79 63 56 AC F8 8E 69 6A 00 07

MSB1(K1) == 0 -> K2 = K1 << 1
K1:
00000:   78 21 C7 C7 6C BD 79 63 56 AC F8 8E 69 6A 00 07

K2:
00000:   F0 43 8F 8E D9 7A F2 C6 AD 59 F1 1C D2 D4 00 0E

Plaintext M_5:
00000:   33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22

Using K1, padding is not required

Input block M_5 (xor) C_4:
00000:   FD E6 71 37 E6 05 2D 8F 94 A1 9D 55 60 E8 0C A4

Output block C_5:
00000:   B3 AD B8 92 18 32 05 4C 09 21 E7 B8 08 CF A0 B8

Message authentication code T:
00000:   B3 AD B8 92 18 32 05 4C 09 21 E7 B8 08 CF A0 B8

Acknowledgments ๐Ÿซถ

Huge thank-yous to Mihir Bellare, Scott Fluhrer, Dorothy Cooley, Yoav Nir, Jim Schaad, Paul Hoffman, Dmitry Belyavsky, Yaron Sheffer, Alexey Melnikov, and Spencer Dawkins for their useful comments. You all made this better, literally iconic ๐Ÿ’–

Contributors ๐Ÿ’…

These are the people who helped write the thing. Their details are below, exactly as they appear:

Russ Housley
Vigil Security, LLC
housley@vigilsec.com

Evgeny Alekseev
CryptoPro
alekseev@cryptopro.ru

Ekaterina Smyshlyaeva
CryptoPro
ess@cryptopro.ru

Shay Gueron
University of Haifa, Israel
Intel Corporation, Israel Development Center, Israel
shay.gueron@gmail.com

Daniel Fox Franke
Akamai Technologies
dfoxfranke@gmail.com

Lilia Ahmetzyanova
CryptoPro
lah@cryptopro.ru

Author's Address ๐Ÿฆ‹

The editor, who did a lot of the heavy lifting, is listed here with contact details. Everything is exact, no cap โœจ

Stanislav Smyshlyaev (editor)
CryptoPro
18, Suschevskiy val
Moscow  127018
Russian Federation

Phone: +7 (495) 995-48-20
Email: svs@cryptopro.ru
๐Ÿ“ฆ where this page comes from