RFC 7253

The OCB Authenticated-Encryption Algorithm

๐Ÿ“… published May 2014, from ietf

Abstract โœจ

okay so this spec is literally all about OCB ๐Ÿ’–, a shared-key, blockcipher-based encryption scheme that gives you confidentiality AND authenticity for plaintexts, plus authenticity for associated data ๐Ÿ”. It was cooked up by the Crypto Forum Research Group (CFRG) ๐Ÿง .


Request for Comments: 7253 ๐Ÿ“ฎ

Title: The OCB Authenticated-Encryption Algorithm ๐ŸŽ€

Stream: Internet Research Task Force (IRTF) ๐ŸŒˆ

Authors: T. Krovetz (Sacramento State) and P. Rogaway (UC Davis) ๐Ÿ‘ฉโ€๐Ÿ’ป

Category: Informational

ISSN: 2070-1721

Date: May 2014 ๐Ÿ—“๏ธ

Obsoletes / Updates: the header doesn't list any RFCs that this one obsoletes or updates โœจ

Status of This Memo ๐Ÿ“œ

this one is NOT an Internet Standards Track spec. It's published purely for informational purposes ๐Ÿค“

It's a product of the Internet Research Task Force (IRTF), which publishes the results of Internet-related research and development. Those results might not be ready for deployment ๐Ÿ™ˆ. This RFC represents the consensus of the CFRG of the IRTF. Documents approved for publication by the IRSG are not a candidate for any level of Internet Standard, see Section 2 of RFC 5741 ๐Ÿ“Ž.

For the current status, any errata, and how to give feedback, check out http://www.rfc-editor.org/info/rfc7253 ๐Ÿ“ฌ

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved ยฉ๏ธ

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

Table of Contents ๐Ÿ“š

1. Introduction ....................................................2
2. Notation and Basic Operations ...................................4
3. OCB Global Parameters ...........................................5
   3.1. Named OCB Parameter Sets and RFC 5116 Constants ............6
4. OCB Algorithms ..................................................6
   4.1. Processing Associated Data: HASH ...........................6
   4.2. Encryption: OCB-ENCRYPT ....................................8
   4.3. Decryption: OCB-DECRYPT ....................................9
5. Security Considerations ........................................11
   5.1. Nonce Requirements ........................................12
6. IANA Considerations ............................................13
7. Acknowledgements ...............................................13
8. References .....................................................14
   8.1. Normative References ......................................14
   8.2. Informative References ....................................14
Appendix A.  Sample Results .......................................15

1. Introduction โœจ

okay so authenticated encryption (AE) is the move where you get confidentiality AND authentication at the same time ๐Ÿ”๐Ÿ’…. Traditionally people glued together separate encryption and authentication mechanisms, each with its own key. Integrated AE schemes instead intertwine what's needed for confidentiality with what's needed for authenticity ๐Ÿงถ. Treating AE as one single goal makes it less likely to get misused compared to conventional encryption schemes, and integrated AE can be significantly faster than stitching separate confidentiality and authenticity pieces together ๐Ÿš€

When an AE scheme also lets you authenticate unencrypted data while you're encrypting and authenticating a plaintext, it's an authenticated encryption with associated data (AEAD) scheme ๐Ÿฆ‹. Associated data is super useful when, for example, a network packet has unencrypted routing info and an encrypted payload ๐Ÿ“ฆ

OCB is an AEAD scheme that runs on top of a blockcipher ๐Ÿงฑ. This doc fully defines OCB encryption and decryption, except for two things: the choice of blockcipher, and the length of the authentication tag that's part of the ciphertext. The blockcipher MUST have a 128-bit blocksize. Each choice of blockcipher and tag length gives you a different variant of OCB, and several AES-based variants are defined in Section 3.1 ๐ŸŽ€

OCB encryption and decryption use a nonce N, which MUST be distinct for each invocation of the OCB encryption operation ๐Ÿ”ข. OCB requires the associated data A to be specified when you encrypt or decrypt, but A can be zero-length ๐Ÿซง. The plaintext P and the associated data A can be any bitlength ๐Ÿ’œ. The ciphertext C you get from encrypting P with A in play is made of a ciphertext-core that's the same length as P, plus an authentication tag. You can look at the result as either the pair (ciphertext-core, tag) or their concatenation ciphertext-core || tag. The only difference is how you assemble and parse ciphertexts. This document uses concatenation ๐Ÿงฉ

OCB encryption protects the confidentiality of P and the authenticity of A, N, and P ๐Ÿ”’. It does this using, on average, about a + m + 1.02 blockcipher calls, where a is the blocklength of A, m is the blocklength of P, and the nonce N is implemented as a counter. (If N is random, OCB uses a + m + 2 blockcipher calls instead.) If A is fixed during a session, then after preprocessing there's effectively no cost to having A authenticated on later encryptions, and the mode averages m + 1.02 blockcipher calls ๐ŸŒธ. OCB needs a single key K for the underlying blockcipher, and every blockcipher call is keyed by K ๐Ÿ—๏ธ. OCB is online, which means you don't need to know the length of A or P to start encrypting, and you don't need to know the length of A or C to start decrypting โฉ. OCB is parallelizable too: the bulk of its blockcipher calls can run simultaneously ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ. The work beyond the blockcipher calls is a small, fixed number of logical operations per call. OCB enjoys provable security, since the mode is secure as long as the underlying blockcipher is secure ๐Ÿ†. Like most modes of operation, security degrades as the number of blocks processed gets large (see Section 5 for details) ๐Ÿ™ˆ

OCB is defined to operate on arbitrary bitstrings, for generality. But for simplicity and efficiency, most implementations will assume the strings are bytestrings (strings that are a multiple of 8 bits) ๐Ÿงƒ. To promote interoperability, implementations of OCB that communicate with implementations of unknown capabilities SHOULD restrict all provided values (nonces, tags, plaintexts, ciphertexts, and associated data) to bytestrings ๐Ÿค

The version of OCB defined here is a refinement of two prior schemes ๐Ÿช„. The original OCB version was published in 2001 [OCB1] and was listed as an optional component in IEEE 802.11i. A second version was published in 2004 [OCB2] and is specified in ISO 19772. The scheme described here is called OCB3 in the 2011 paper describing the mode [OCB3], but it SHALL be referred to simply as OCB throughout this document ๐Ÿ’–. The only difference between this RFC's algorithm and the one in the [OCB3] paper is that the tag length is now encoded into the internally formatted nonce. See [OCB3] for complete references, timing information, and a discussion of the differences between the algorithms ๐Ÿ“š. Fun fact: OCB was initially the acronym for Offset Codebook, but now it's just the algorithm's full name ๐ŸŽ€

OCB got years of in-depth analysis before it was submitted to the CFRG, and it's been under review by CFRG members for over a year ๐Ÿ”. It's the consensus of the CFRG that the security mechanisms provided by the OCB AEAD algorithm described in this document are suitable for providing confidentiality and authentication ๐Ÿซถ

2. Notation and Basic Operations ๐Ÿงฎ

there are two types of variables in this spec: strings and integers ๐Ÿงต๐Ÿ”ข. Most implementations will process strings made of bytes, but bit-level operations are used throughout the spec to define OCB ๐Ÿง . String variables always start with an uppercase letter, and integer variables are always all lowercase ๐Ÿ” . Following C's convention, a single equals sign (=) means variable assignment and a double equals sign (==) is the equality relation ๐Ÿ’…. When a variable is followed by an underscore (_), that underscore denotes a subscript, and the subscripted expression needs evaluating to resolve the meaning of the variable. For example, when i == 2, P_i refers to the variable P_2 ๐Ÿง

Here's the whole notation cheat sheet, verbatim:

c^i           The integer c raised to the i-th power.

bitlen(S)     The length of string S in bits (e.g., bitlen(101) ==
              3).

zeros(n)      The string made of n zero bits.

ntz(n)        The number of trailing zero bits in the base-2
              representation of the positive integer n.  More
              formally, ntz(n) is the largest integer x for which 2^x
              divides n.

S xor T       The string that is the bitwise exclusive-or of S and T.
              Strings S and T will always have the same length.

S[i]          The i-th bit of the string S (indices begin at 1, so if
              S is 011, then S[1] == 0, S[2] == 1, S[3] == 1).

S[i..j]       The substring of S consisting of bits i through j,
              inclusive.

S || T        String S concatenated with string T (e.g., 000 || 111
              == 000111).

str2num(S)    The base-2 interpretation of bitstring S (e.g.,
              str2num(1110) == 14).

num2str(i,n)  The n-bit string whose base-2 interpretation is i
              (e.g., num2str(14,4) == 1110 and num2str(1,2) == 01).

double(S)     If S[1] == 0, then double(S) == (S[2..128] || 0);
              otherwise, double(S) == (S[2..128] || 0) xor
              (zeros(120) || 10000111).

3. OCB Global Parameters ๐Ÿ”

okay so to be complete, the algorithms in this doc need two global parameters: a blockcipher operating on 128-bit blocks, and the length of the authentication tags in use ๐ŸŽฏ

Specifying a blockcipher implicitly defines the following symbols:

KEYLEN         The blockcipher's key length in bits.

ENCIPHER(K,P)  The blockcipher function mapping 128-bit plaintext
               block P to its corresponding ciphertext block using
               KEYLEN-bit key K.

DECIPHER(K,C)  The inverse blockcipher function mapping 128-bit
               ciphertext block C to its corresponding plaintext
               block using KEYLEN-bit key K.

The TAGLEN parameter is the length of the authentication tag OCB uses, and it MAY be any value up to 128 ๐Ÿท๏ธ. Bigger values of TAGLEN give you bigger assurances of authenticity, but ciphertexts from OCB come out longer than their plaintexts by TAGLEN bits, so there's a tradeoff ๐Ÿ’ญ. See Section 5 for the details on TAGLEN and security ๐Ÿ›ก๏ธ

As an example, if you want 128-bit authentication tags and AES with 192-bit keys, then KEYLEN is 192, ENCIPHER refers to the AES-192 cipher, DECIPHER refers to the AES-192 inverse cipher, and TAGLEN is 128 [AES] ๐Ÿ’–โœจ

3.1. Named OCB Parameter Sets and RFC 5116 Constants โœจ

okay so here's a table giving names to the common OCB global parameter sets ๐ŸŽ€ each AES variant is defined in [AES] btw

+----------------------------+-------------+--------+
| Name                       | Blockcipher | TAGLEN |
+----------------------------+-------------+--------+
| AEAD_AES_128_OCB_TAGLEN128 |   AES-128   |  128   |
| AEAD_AES_128_OCB_TAGLEN96  |   AES-128   |   96   |
| AEAD_AES_128_OCB_TAGLEN64  |   AES-128   |   64   |
| AEAD_AES_192_OCB_TAGLEN128 |   AES-192   |  128   |
| AEAD_AES_192_OCB_TAGLEN96  |   AES-192   |   96   |
| AEAD_AES_192_OCB_TAGLEN64  |   AES-192   |   64   |
| AEAD_AES_256_OCB_TAGLEN128 |   AES-256   |  128   |
| AEAD_AES_256_OCB_TAGLEN96  |   AES-256   |   96   |
| AEAD_AES_256_OCB_TAGLEN64  |   AES-256   |   64   |
+----------------------------+-------------+--------+

RFC 5116 is the one that defines a common interface for authenticated-encryption schemes [RFC5116] ๐Ÿ’… and it requires you to spell out certain constants for every named AEAD scheme. So for each OCB parameter set above: P_MAX, A_MAX, and C_MAX are all unbounded, N_MIN is 1 byte, and N_MAX is 15 bytes. The sets that mean AES-128, AES-192, and AES-256 have K_LEN equal to 16, 24, and 32 bytes, in that order ๐Ÿ”ฅ

Each ciphertext is longer than its matching plaintext by exactly TAGLEN bits, and TAGLEN is the number tacked onto the end of each name ๐Ÿฆ‹ for example, an AEAD_AES_128_OCB_TAGLEN64 ciphertext is exactly 64 bits longer than its plaintext. iconic, honestly ๐Ÿ˜ญ

4. OCB Algorithms ๐Ÿงš

okay so this section describes OCB using pseudocode ๐Ÿ’– if you feed any inputs of the required types into a function and follow its pseudocode, you'll get the correct output of the promised type. no cap ๐Ÿซถ

4.1. Processing Associated Data: HASH ๐ŸŒธ

this is the bit that lets OCB authenticate unencrypted associated data at the same time as it provides authentication and encrypts a plaintext ๐Ÿ”ฅ HASH is central to all of that. if an application has no associated data, the associated data should be treated as existing and being the empty string ๐Ÿ™ˆ and HASH, conveniently, always returns zeros(128) when the associated data is the empty string. slay ๐Ÿ’…

Function name:
  HASH
Input:
  K, string of KEYLEN bits                      // Key
  A, string of any length                       // Associated data
Output:
  Sum, string of 128 bits                       // Hash result

Sum is defined as follows.

  //
  // Key-dependent variables
  //
  L_* = ENCIPHER(K, zeros(128))
  L_$ = double(L_*)
  L_0 = double(L_$)
  L_i = double(L_{i-1}) for every integer i > 0

  //
  // Consider A as a sequence of 128-bit blocks
  //
  Let m be the largest integer so that 128m <= bitlen(A)
  Let A_1, A_2, ..., A_m and A_* be strings so that
    A == A_1 || A_2 || ... || A_m || A_*, and
    bitlen(A_i) == 128 for each 1 <= i <= m.
    Note: A_* may possibly be the empty string.

  //
  // Process any whole blocks
  //
  Sum_0 = zeros(128)
  Offset_0 = zeros(128)
  for each 1 <= i <= m
     Offset_i = Offset_{i-1} xor L_{ntz(i)}
     Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)
  end for

  //
  // Process any final partial block; compute final hash value
  //
  if bitlen(A_*) > 0 then
     Offset_* = Offset_m xor L_*
     CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_*
     Sum = Sum_m xor ENCIPHER(K, CipherInput)
  else
     Sum = Sum_m
  end if

4.2. Encryption: OCB-ENCRYPT ๐Ÿ’œ

this function takes a plaintext, associated data, a nonce, and a key, and spits out a ciphertext that already has the authentication tag bundled in ๐ŸŽ€ the big rule here: for every OCB-ENCRYPT call using the same key K, the nonce input N must be distinct. not optional, bestie ๐Ÿ‘‘

Function name:
  OCB-ENCRYPT
Input:
  K, string of KEYLEN bits                      // Key
  N, string of no more than 120 bits            // Nonce
  A, string of any length                       // Associated data
  P, string of any length                       // Plaintext
Output:
  C, string of length bitlen(P) + TAGLEN bits   // Ciphertext

C is defined as follows.

  //
  // Key-dependent variables
  //
  L_* = ENCIPHER(K, zeros(128))
  L_$ = double(L_*)
  L_0 = double(L_$)
  L_i = double(L_{i-1}) for every integer i > 0

  //
  // Consider P as a sequence of 128-bit blocks
  //
  Let m be the largest integer so that 128m <= bitlen(P)
  Let P_1, P_2, ..., P_m and P_* be strings so that
    P == P_1 || P_2 || ... || P_m || P_*, and
    bitlen(P_i) == 128 for each 1 <= i <= m.
    Note: P_* may possibly be the empty string.

  //
  // Nonce-dependent and per-encryption variables
  //
  Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N
  bottom = str2num(Nonce[123..128])
  Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6))
  Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72])
  Offset_0 = Stretch[1+bottom..128+bottom]
  Checksum_0 = zeros(128)
  //
  // Process any whole blocks
  //
  for each 1 <= i <= m
     Offset_i = Offset_{i-1} xor L_{ntz(i)}
     C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)
     Checksum_i = Checksum_{i-1} xor P_i
  end for

  //
  // Process any final partial block and compute raw tag
  //
  if bitlen(P_*) > 0 then
     Offset_* = Offset_m xor L_*
     Pad = ENCIPHER(K, Offset_*)
     C_* = P_* xor Pad[1..bitlen(P_*)]
     Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*)))
     Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A)
  else
     C_* = <empty string>
     Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A)
  end if

  //
  // Assemble ciphertext
  //
  C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN]

4.3. Decryption: OCB-DECRYPT ๐Ÿฆ‹

this one goes the other way: it takes a ciphertext, associated data, a nonce, and a key, and hands back the plaintext ๐Ÿงš the tag is hiding inside the ciphertext, so if the tag doesn't check out for that ciphertext, associated data, nonce, and key, you get an INVALID signal instead of a plaintext ๐Ÿ˜ญ no tea, no plaintext.

Function name:
  OCB-DECRYPT
Input:
  K, string of KEYLEN bits                      // Key
  N, string of no more than 120 bits            // Nonce
  A, string of any length                       // Associated data
  C, string of at least TAGLEN bits             // Ciphertext
Output:
  P, string of length bitlen(C) - TAGLEN bits,  // Plaintext
       or INVALID indicating authentication failure

P is defined as follows.

  //
  // Key-dependent variables
  //
  L_* = ENCIPHER(K, zeros(128))
  L_$ = double(L_*)
  L_0 = double(L_$)
  L_i = double(L_{i-1}) for every integer i > 0

  //
  // Consider C as a sequence of 128-bit blocks
  //
  Let m be the largest integer so that 128m <= bitlen(C) - TAGLEN
  Let C_1, C_2, ..., C_m, C_* and T be strings so that
    C == C_1 || C_2 || ... || C_m || C_* || T,
    bitlen(C_i) == 128 for each 1 <= i <= m, and
    bitlen(T) == TAGLEN.
    Note: C_* may possibly be the empty string.

  //
  // Nonce-dependent and per-decryption variables
  //
  Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N
  bottom = str2num(Nonce[123..128])
  Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6))
  Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72])
  Offset_0 = Stretch[1+bottom..128+bottom]
  Checksum_0 = zeros(128)

  //
  // Process any whole blocks
  //
  for each 1 <= i <= m
     Offset_i = Offset_{i-1} xor L_{ntz(i)}
     P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)
     Checksum_i = Checksum_{i-1} xor P_i
  end for

  //
  // Process any final partial block and compute raw tag
  //
  if bitlen(C_*) > 0 then
     Offset_* = Offset_m xor L_*
     Pad = ENCIPHER(K, Offset_*)
     P_* = C_* xor Pad[1..bitlen(C_*)]
     Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*)))
     Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A)

  else
     P_* = <empty string>
     Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A)
  end if

  //
  // Check for validity and assemble plaintext
  //
  if (Tag[1..TAGLEN] == T) then
     P = P_1 || P_2 || ... || P_m || P_*
  else
     P = INVALID
  end if

5. Security Considerations โœจ

okay bestie, this section is SERIOUS and I need you to take it seriously ๐Ÿซถ๐Ÿ”’ OCB promises two big things: confidentiality and authenticity. Confidentiality means "indistinguishability from random bits", which is a fancy way of saying an attacker can't tell OCB's outputs apart from the same number of random bits ๐Ÿ‘€. Authenticity means "authenticity of ciphertexts", so an attacker can't make up a valid nonce-ciphertext pair they never got their hands on ๐Ÿ™…โ€โ™€๏ธ.

Both of those guarantees depend on the blockcipher being secure as a strong pseudorandom permutation ๐ŸŒธ. So if you pair OCB with a blockcipher that isn't, the guarantees just vanish ๐Ÿ’€. That's why OCB should be used with a conservatively designed, well-trusted blockcipher, like AES ๐Ÿ’–. No cap, that's non-negotiable.

Both confidentiality and authenticity degrade as s^2 / 2^128, where s is the total number of blocks the attacker gets their hands on ๐Ÿ“‰. The tea is that once s hits 2^64, the proven security is gone ๐Ÿ˜ญ. So the user should never use a key to generate an amount of ciphertext near to, or over, 2^64 blocks ๐Ÿšซ. To keep s^2 / 2^128 small, a given key should encrypt at most 2^48 blocks (that's 2^55 bits, or 4 petabytes ๐Ÿคฏ), and that count includes the associated data โœจ. To make sure nobody crosses those limits, automated key management is recommended in systems swapping big amounts of data [RFC4107] ๐Ÿ”‘.

When a ciphertext decrypts as INVALID, the implementor MUST make sure that no information beyond that fact is made adversarially available. Wait, let me say that with the exact wording: it is the implementor's responsibility to make sure that no information beyond this fact is made adversarially available ๐Ÿ™ˆ.

OCB encryption and decryption produce an internal 128-bit authentication tag ๐ŸŽ€. The parameter TAGLEN decides how many bits of that internal tag get included in ciphertexts and used for authentication ๐Ÿงš. TAGLEN has two impacts: an adversary can trivially forge with probability 2^{-TAGLEN}, and ciphertexts end up TAGLEN bits longer than their plaintexts ๐Ÿ“. It's up to the application designer to pick a good TAGLEN ๐Ÿ’…. Long tags cost no more computationally than short ones, so go big if you can ๐Ÿ‘‘.

Normally, a given key should be used to create ciphertexts with a single tag length, TAGLEN, and an application should reject any ciphertext that claims authenticity under the same key but a different tag length ๐Ÿšซ. The ciphertext core and all the tag bits do depend on the tag length, and that's for extra robustness against misuse ๐Ÿ›ก๏ธ. It should NOT be read as permission for receivers to accept ciphertexts with variable tag lengths under a single key ๐Ÿ’€.

Timing attacks aren't part of the formal security model, so an implementation should take care to mitigate them where it matters ๐Ÿ•ฐ๏ธ. The goal is that the time to encrypt or decrypt a string is independent of the key and the contents of the string โœจ. The only explicitly conditional OCB operation that depends on private data is double(), so using constant-time blockcipher and double() implementations gets rid of most (if not all) timing attack sources on OCB ๐Ÿ”ฅ. Power-usage attacks are also outside the formal model, so think about them if your environment is threatening ๐Ÿ”‹.

The OCB encryption scheme reveals the length of the plaintext in the ciphertext ๐Ÿ‘€. Sometimes that length is valuable info that should stay hidden ๐Ÿซฃ. For environments where "traffic analysis" is a concern, you'd need techniques beyond OCB encryption, typically involving padding ๐ŸŽ€.

Defining the ciphertext from OCB-ENCRYPT as the pair (C_1 || C_2 || ... || C_m || C_*, Tag[1..TAGLEN]), instead of the concatenation C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN], introduces no security concerns ๐Ÿฆ‹. Since TAGLEN is fixed, both versions let ciphertexts be parsed unambiguously ๐Ÿ’œ.

5.1. Nonce Requirements

It is crucial that, as you encrypt, you do not repeat a nonce ๐Ÿšจ. Reusing the same nonce in two OCB encryption calls with the same key but different plaintexts is a disaster ๐Ÿ˜ฑ. It undermines the confidentiality of those plaintexts and undermines all of the authenticity and integrity protection that key provides ๐Ÿ’”. So OCB should only be used whenever nonce uniqueness can be provided with certainty ๐Ÿ”. Inputting the same nonce value multiple times to the decryption operation is acceptable ๐Ÿ‘.

The security consequences are seriously bad if an attacker sees two ciphertexts made with the same nonce and key, unless the plaintext and associated data values in both encrypt calls were identical ๐Ÿ’€. First, confidentiality is lost, because the attacker can infer relationships between the two plaintexts ๐Ÿ•ต๏ธโ€โ™€๏ธ. Second, authenticity is lost, because the attacker can recover the secret information used for authenticity, making later forgeries trivial ๐Ÿ˜ญ. There are AEAD schemes, like the Synthetic Initialization Vector (SIV) [RFC5297], that fit environments where nonces are unavailable or unreliable ๐ŸŒˆ. OCB is NOT one of them ๐Ÿ™…โ€โ™€๏ธ.

Nonces don't need to be secret, and a counter can be used for them ๐Ÿ”ข. If two parties send OCB-encrypted plaintexts to each other with the same key, the nonce space has to be partitioned so no nonce one party could use to encrypt can also be used by the other to encrypt, like using odd and even counters ๐Ÿงšโ€โ™€๏ธโœจ.


6. IANA Considerations ๐ŸŽ€

The Internet Assigned Numbers Authority (IANA) has defined a registry for Authenticated Encryption with Associated Data parameters ๐Ÿ“‹. IANA added the following entries to the AEAD Registry. Each name refers to a set of parameters defined in Section 3.1 ๐Ÿ’–.

      +----------------------------+-------------+------------+
      | Name                       |  Reference  | Numeric ID |
      +----------------------------+-------------+------------+
      | AEAD_AES_128_OCB_TAGLEN128 | Section 3.1 |     20     |
      | AEAD_AES_128_OCB_TAGLEN96  | Section 3.1 |     21     |
      | AEAD_AES_128_OCB_TAGLEN64  | Section 3.1 |     22     |
      | AEAD_AES_192_OCB_TAGLEN128 | Section 3.1 |     23     |
      | AEAD_AES_192_OCB_TAGLEN96  | Section 3.1 |     24     |
      | AEAD_AES_192_OCB_TAGLEN64  | Section 3.1 |     25     |
      | AEAD_AES_256_OCB_TAGLEN128 | Section 3.1 |     26     |
      | AEAD_AES_256_OCB_TAGLEN96  | Section 3.1 |     27     |
      | AEAD_AES_256_OCB_TAGLEN64  | Section 3.1 |     28     |
      +----------------------------+-------------+------------+

7. Acknowledgements ๐Ÿซถ

The original OCB scheme [OCB1] was designed while Rogaway was at Chiang Mai University, Thailand ๐Ÿ‡น๐Ÿ‡ญ. Follow-up work [OCB2] was supported by NSF grant 0208842 and a gift from Cisco ๐Ÿ’œ. The final work by Krovetz and Rogaway [OCB3] that resulted in this specification was supported by NSF grant 0904380 ๐ŸŒŸ. Thanks to the many members of the Crypto Forum Research Group (CFRG) who gave feedback on earlier drafts ๐Ÿ™Œ. Special thanks to David McGrew for contributing some text and managing the RFC approval process ๐Ÿ‘‘, to James Manger for kicking off a productive discussion on tag-length dependency and greatly improving Appendix A ๐ŸŽ€, to Matt Caswell and Peter Dettman for writing implementations and verifying test vectors ๐Ÿงš, and to Stephen Farrell and Spencer Dawkins for their careful reading and suggestions ๐Ÿฆ‹.


8. References ๐Ÿ“š

8.1. Normative References

[AES]      National Institute of Standards and Technology, "Advanced
           Encryption Standard (AES)", FIPS PUB 197, November 2001.

[RFC5116]  McGrew, D., "An Interface and Algorithms for Authenticated
           Encryption", RFC 5116, January 2008.

8.2. Informative References

[OCB1]     Rogaway, P., Bellare, M., Black, J., and T. Krovetz, "OCB:
           A Block-Cipher Mode of Operation for Efficient
           Authenticated Encryption", ACM Conference on Computer and
           Communications Security 2001 - CCS 2001, ACM Press, 2001.

[OCB2]     Rogaway, P., "Efficient Instantiations of Tweakable
           Blockciphers and Refinements to Modes OCB and PMAC",
           Advances in Cryptology - ASIACRYPT 2004, Springer, 2004.

[OCB3]     Krovetz, T. and P. Rogaway, "The Software Performance of
           Authenticated-Encryption Modes", Fast Software Encryption
           - FSE 2011 Springer, 2011.

[RFC4107]  Bellovin, S. and R. Housley, "Guidelines for Cryptographic
           Key Management", BCP 107, RFC 4107, June 2005.

[RFC5297]  Harkins, D., "Synthetic Initialization Vector (SIV)
           Authenticated Encryption Using the Advanced Encryption
           Standard (AES)", RFC 5297, October 2008.

Appendix A. Sample Results โœจ

Okay bestie, this is the fun part ๐Ÿงš Here are sample outputs for OCB with AES, using the parameters from Section 3.1 ๐ŸŽ€ All strings are in hexadecimal, so 0F is the bitstring 00001111 ๐Ÿ”ฅ

Next up are 16 (N,A,P,C) tuples showing the ciphertext C from OCB-ENCRYPT(K,N,A,P) for different lengths of associated data (A) and plaintext (P). The key (K) stays the same, the tag is 128 bits, and the nonce (N) counts up ๐Ÿ’– An empty entry means the empty string ๐ŸŒธ

K : 000102030405060708090A0B0C0D0E0F

N: BBAA99887766554433221100
A:
P:
C: 785407BFFFC8AD9EDCC5520AC9111EE6

N: BBAA99887766554433221101
A: 0001020304050607
P: 0001020304050607
C: 6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009

N: BBAA99887766554433221102
A: 0001020304050607
P:
C: 81017F8203F081277152FADE694A0A00

N: BBAA99887766554433221103
A:
P: 0001020304050607
C: 45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9

N: BBAA99887766554433221104
A: 000102030405060708090A0B0C0D0E0F
P: 000102030405060708090A0B0C0D0E0F
C: 571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5
   701C1CCEC8FC3358

N: BBAA99887766554433221105
A: 000102030405060708090A0B0C0D0E0F
P:
C: 8CF761B6902EF764462AD86498CA6B97
N: BBAA99887766554433221106
A:
P: 000102030405060708090A0B0C0D0E0F
C: 5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436B
   DF06D8FA1ECA343D

N: BBAA99887766554433221107
A: 000102030405060708090A0B0C0D0E0F1011121314151617
P: 000102030405060708090A0B0C0D0E0F1011121314151617
C: 1CA2207308C87C010756104D8840CE1952F09673A448A122
   C92C62241051F57356D7F3C90BB0E07F

N: BBAA99887766554433221108
A: 000102030405060708090A0B0C0D0E0F1011121314151617
P:
C: 6DC225A071FC1B9F7C69F93B0F1E10DE

N: BBAA99887766554433221109
A:
P: 000102030405060708090A0B0C0D0E0F1011121314151617
C: 221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3C
   E725F32494B9F914D85C0B1EB38357FF

N: BBAA9988776655443322110A
A: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F
P: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F
C: BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE
   AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240

N: BBAA9988776655443322110B
A: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F
P:
C: FE80690BEE8A485D11F32965BC9D2A32

N: BBAA9988776655443322110C
A:
P: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F
C: 2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4
   6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF

N: BBAA9988776655443322110D
A: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
P: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
C: D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460
   6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483
   A7035490C5769E60

N: BBAA9988776655443322110E
A: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
P:
C: C5CD9D1850C141E358649994EE701B68

N: BBAA9988776655443322110F
A:
P: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
C: 4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15
   A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95
   A98CA5F3000B1479

Next, here are some of the internal values generated during the OCB-ENCRYPT computation for the last test vector above ๐Ÿ” Main character energy, honestly ๐Ÿ‘‘

L_*       : C6A13B37878F5B826F4F8162A1C8D879
L_$       : 8D42766F0F1EB704DE9F02C54391B075
L_0       : 1A84ECDE1E3D6E09BD3E058A8723606D
L_1       : 3509D9BC3C7ADC137A7C0B150E46C0DA
bottom    : 15 (decimal)
Ktop      : 9862B0FDEE4E2DD56DBA6433F0125AA2
Stretch   : 9862B0FDEE4E2DD56DBA6433F0125AA2FAD24D13A063F8B8
Offset_0  : 587EF72716EAB6DD3219F8092D517D69
Offset_1  : 42FA1BF908D7D8D48F27FD83AA721D04
Offset_2  : 77F3C24534AD04C7F55BF696A434DDDE
Offset_*  : B152F972B3225F459A1477F405FC05A7
Checksum_1: 000102030405060708090A0B0C0D0E0F
Checksum_2: 10101010101010101010101010101010
Checksum_*: 30313233343536379010101010101010

Then comes a result with a 96-bit tag and a different key ๐Ÿฆ‹

K: 0F0E0D0C0B0A09080706050403020100

N: BBAA9988776655443322110D
A: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
P: 000102030405060708090A0B0C0D0E0F1011121314151617
   18191A1B1C1D1E1F2021222324252627
C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1
   A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD
   AC4F02AA

The next algorithm tests a much wider range of inputs, with results for every parameter set in Section 3.1 ๐ŸŒˆ It's giving thorough ๐Ÿ’…

K = zeros(KEYLEN-8) || num2str(TAGLEN,8)
C = <empty string>
for i = 0 to 127 do
   S = zeros(8i)
   N = num2str(3i+1,96)
   C = C || OCB-ENCRYPT(K,N,S,S)
   N = num2str(3i+2,96)
   C = C || OCB-ENCRYPT(K,N,<empty string>,S)
   N = num2str(3i+3,96)
   C = C || OCB-ENCRYPT(K,N,S,<empty string>)
end for
N = num2str(385,96)
Output : OCB-ENCRYPT(K,N,C,<empty string>)

Each loop iteration adds 2i + (3 * TAGLEN / 8) bytes to C ๐Ÿง That makes C end up at 22,400 bytes when TAGLEN == 128, 20,864 bytes when TAGLEN == 192, and 19,328 bytes when TAGLEN == 64. The final OCB-ENCRYPT has an empty plaintext, so it only exists to authenticate C ๐Ÿ” The output should be:

AEAD_AES_128_OCB_TAGLEN128 Output: 67E944D23256C5E0B6C61FA22FDF1EA2
AEAD_AES_192_OCB_TAGLEN128 Output: F673F2C3E7174AAE7BAE986CA9F29E17
AEAD_AES_256_OCB_TAGLEN128 Output: D90EB8E9C977C88B79DD793D7FFA161C
AEAD_AES_128_OCB_TAGLEN96 Output : 77A3D8E73589158D25D01209
AEAD_AES_192_OCB_TAGLEN96 Output : 05D56EAD2752C86BE6932C5E
AEAD_AES_256_OCB_TAGLEN96 Output : 5458359AC23B0CBA9E6330DD
AEAD_AES_128_OCB_TAGLEN64 Output : 192C9B7BD90BA06A
AEAD_AES_192_OCB_TAGLEN64 Output : 0066BC6E0EF34E24
AEAD_AES_256_OCB_TAGLEN64 Output : 7D4EA5D445501CBE

Authors' Addresses ๐ŸŽ€

Ted Krovetz, who's an absolute legend, is at the Computer Science Department of California State University, Sacramento. Phillip Rogaway is at the Computer Science Department of the University of California, Davis. Here are their details, exactly as they appear in the RFC ๐Ÿซถ

Ted Krovetz
Computer Science Department
California State University, Sacramento
6000 J Street
Sacramento, CA  95819-6021
USA

EMail: ted@krovetz.net


Phillip Rogaway
Computer Science Department
University of California, Davis
One Shields Avenue
Davis, CA  95616-8562
USA

EMail: rogaway@cs.ucdavis.edu
๐Ÿ“ฆ where this page comes from