RFC 2040

The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms

๐Ÿ“… published October 1996, from ietf

Okay bestie, this is the RFC that gave us RC5 and its whole crew of ciphers ๐Ÿ’–๐Ÿ” The title block is giving early internet royalty: RFC 2040, "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms," from the Network Working Group, dated October 1996. The authors are R. Baldwin (RSA Data Security, Inc.) and R. Rivest (MIT Laboratory for Computer Science and RSA Data Security, Inc.). It's marked Category: Informational, which means it's sharing info, not setting an Internet standard. The title block doesn't list any "obsoletes" or "updates" lines, so there's nothing it replaces or amends ๐ŸŒธ

Status of this Memo

This memo gives information to the Internet community ๐Ÿซถ It does not specify an Internet standard of any kind, and it can be shared freely with no limits on distribution ๐Ÿฆ‹

Acknowledgments

Huge thanks to Steve Dusse, Victor Chang, Tim Mathews, Brett Howard, and Burt Kaliski for their helpful suggestions ๐Ÿ’…โœจ

Table of Contents

  1.        Executive Summary .......................  1
  2.        Overview ................................  2
  3.        Terminology and Notation ................  3
  4.        Description of RC5 Keys .................  4
  5.        Description of RC5 Key Expansion ........  6
  6.        Description of RC5 Block Cipher ......... 10
  7.        Description of RC5-CBC and RC5-CBC-Pad .. 12
  8.        Description of RC5-CTS .................. 18
  9.        Test Program and Vectors ................ 19
  10.       Security Considerations ................. 26
  11.       ASN.1 Identifiers ....................... 28
  References ........................................ 28
  Authors' Addresses ................................ 29

1. Executive Summary โœจ

okay so this document defines four ciphers in enough detail that different implementations can actually talk to each other ๐ŸŽ€ The first is the raw RC5 block cipher. It takes a fixed size input block and spits out a fixed size output block, using a transformation that depends on a key ๐Ÿ”‘

The second is RC5-CBC, which is the Cipher Block Chaining (CBC) mode for RC5. It can handle messages whose length is a multiple of the RC5 block size ๐Ÿงฉ The third is RC5-CBC-Pad, which handles plaintext of any length. The ciphertext can be longer than the plaintext, but by at most the size of a single RC5 block ๐Ÿ“ The fourth is RC5-CTS, the Cipher Text Stealing mode of RC5. It also handles plaintext of any length, and the ciphertext length matches the plaintext length exactly ๐Ÿ’œ

RC5 was invented by Professor Ronald L. Rivest of the Massachusetts Institute of Technology in 1994. It's very fast and very simple, and it's parameterized by the block size, the number of rounds, and the key length. Those parameters can be tuned to balance security, performance, and exportability, which is such a flex ๐Ÿ‘‘

RSA Data Security Incorporated has filed a patent application on the RC5 cipher, and it has also filed for trademark protection for RC5, RC5-CBC, RC5-CBC-Pad, RC5-CTS, and assorted variations ๐Ÿ™ˆ

2. Overview

this memo is a restatement of material that's already been published ๐Ÿ“š The description of RC5 follows the notation and order of explanation in the original RC5 paper by Professor Rivest [2]. The CBC mode shows up in reference works like the one by Bruce Schneier [6]. The CBC-Pad mode is the same as the one in the Public Key Cryptography Standard (PKCS) number five [5]. Sample C code [8] is included just for clarity, and it's equivalent to the English descriptions ๐Ÿซถ

The ciphers get explained in a bottom up, object-oriented way ๐Ÿงš First come the RC5 keys and the key expansion algorithm. Second is the RC5 block cipher. Finally, the RC5-CBC and RC5-CBC-Pad ciphers are specified. To keep things brief, only the encryption process is described. Decryption is just encryption run backwards, by inverting the steps ๐Ÿ”„

The object-oriented description should make it easier to build interoperable systems, even though it isn't as terse as the functional descriptions in the references ๐Ÿ’… There are two classes of objects, keys and cipher algorithms. Both classes share operations that create and destroy these objects in a way that makes sure secret information never gets handed back to the memory manager ๐Ÿ”

Keys also have a "set" operation that copies a secret key into the object. The "set" operation for cipher objects defines the number of rounds and the initialization vector ๐ŸŽ€

There are four operations for the cipher objects in this memo. You can bind a key to a cipher object. You can set a new initialization vector without changing the key. You can encrypt part of a message (which happens multiple times for long messages). And you can process the last part of a message, which may add padding or check the message length ๐ŸŒˆ

So in summary, the cipher is explained in terms of these operations:

RC5_Key_Create           - Create a key object.

RC5_Key_Destroy          - Destroy a key object.

RC5_Key_Set              - Bind a user key to a key object.

RC5_CBC_Create           - Create a cipher object.

RC5_CBC_Destroy          - Destroy a cipher object.

RC5_CBC_Encrypt_Init     - Bind a key object to a cipher object.

RC5_CBC_SetIV            - Set a new IV without changing the key.

RC5_CBC_Encrypt_Update   - Process part of a message.

RC5_CBC_Encrypt_Final    - Process the end of a message.

3. Terminology and Notation

okay the term "word" means a string of bits of a set length that you can operate on as either an unsigned integer or a bit vector ๐Ÿงฎ A word might be 32 or 64 bits long, depending on the block size you want for RC5. A 32 bit word gives you a 64 bit block size. For best performance, the RC5 word size should match the CPU's register size ๐Ÿš€ The term "byte" means eight bits ๐Ÿ’œ

Here are the variables used all through this memo and what they mean:

  • W is the word size for RC5, measured in bits. It's half the block size. The word sizes covered by this memo are 32 and 64 โœจ
  • WW is the word size for RC5, measured in bytes ๐Ÿ“
  • B is the block size for RC5, measured in bits. It's twice the word size. When RC5 is used as a 64 bit block cipher, B is 64 and W is 32. The range is 0 < B < 257. In the sample code, B, is used as a variable instead of a cipher system parameter, but that's obvious from context ๐Ÿ™ˆ
  • BB is the block size for RC5, measured in bytes. BB = B / 8 ๐Ÿง
  • b is the byte length of the secret key, with 0 <= b < 256 ๐Ÿ”‘
  • K is the secret key, treated as a sequence of b bytes indexed by K[0], ..., K[b-1] ๐Ÿ—๏ธ
  • R is the number of rounds of the inner RC5 transform, with 0 <= R < 256 ๐ŸŒ€
  • T is the number of words in the expanded key table. It's always 2*(R + 1), with 1 < T < 513 ๐ŸŽ€
  • S is the expanded key table, treated as a sequence of words indexed by S[0], ..., S[T-1] ๐Ÿงš
  • N is the byte length of the plaintext message ๐Ÿ’Œ
  • P is the plaintext message, treated as a sequence of N bytes indexed by P[0], ..., P[N-1] ๐Ÿ“
  • C is the ciphertext output, treated as a sequence of bytes indexed by C[0], C[1], ... ๐Ÿ”’
  • I is the initialization vector for the CBC mode, treated as a sequence of bytes indexed by I[0], ..., I[BB-1] ๐Ÿซถ

4. Description of RC5 Keys

so like most block ciphers, RC5 takes a small user key and expands it into a table of internal keys ๐Ÿ—๏ธ The byte length of the user key is one of the cipher's parameters, so the RC5 user key object has to be able to hold keys of variable length. A possible C structure for this looks like:

  /* Definition of RC5 user key object. */
  typedef struct rc5UserKey
  {
    int          keyLength; /* In Bytes. */
    unsigned char   *keyBytes;
  } rc5UserKey;

The basic operations on a key are create, destroy, and set. To avoid exposing key material to other parts of an application, the destroy operation zeros the memory allocated for the key before releasing it to the memory manager ๐Ÿ™ˆ A general key object may support other operations too, like generating a new random key or deriving a key from key-agreement information ๐ŸŒˆ

4.1 Creating an RC5 Key

To create a key, the memory for the key object has to be allocated and initialized. The C code below assumes a function called "malloc" will return a block of uninitialized memory from the heap, or zero if there's an error ๐Ÿ’–

  /* Allocate and initialize an RC5 user key.
   * Return 0 if problems.
   */
  rc5UserKey *RC5_Key_Create ()
  {
    rc5UserKey *pKey;

    pKey = (rc5UserKey *) malloc (sizeof(*pKey));
    if (pKey != ((rc5UserKey *) 0))
    {
        pKey->keyLength = 0;
        pKey->keyBytes = (unsigned char *) 0;
    }
    return (pKey);
  }

4.2 Destroying an RC5 Key

To destroy a key, the memory has to be zeroed and released to the memory manager ๐Ÿงน The C code below assumes a function called "free" will return a block of memory to the heap ๐ŸŒธ

  /* Zero and free an RC5 user key.
   */
  void RC5_Key_Destroy (pKey)
    rc5UserKey      *pKey;
  {
    unsigned char   *to;
    int          count;

    if (pKey == ((rc5UserKey *) 0))
        return;
    if (pKey->keyBytes == ((unsigned char *) 0))
        return;
    to = pKey->keyBytes;
    for (count = 0 ; count < pKey->keyLength ; count++)
        *to++ = (unsigned char) 0;
    free (pKey->keyBytes);
    pKey->keyBytes = (unsigned char *) 0;
    pKey->keyLength = 0;
    free (pKey);

  }

4.3 Setting an RC5 Key

Setting the key object makes a copy of the secret key into a block of memory allocated from the heap ๐Ÿ”

  /* Set the value of an RC5 user key.
   * Copy the key bytes so the caller can zero and
   * free the original.
   * Return zero if problems
   */
  int RC5_Key_Set (pKey, keyLength, keyBytes)
    rc5UserKey  *pKey;
    int          keyLength;
    unsigned char   *keyBytes;
  {
    unsigned char   *keyBytesCopy;
    unsigned char   *from, *to;
    int          count;

    keyBytesCopy = (unsigned char *) malloc (keyLength);
    if (keyBytesCopy == ((unsigned char *) 0))
        return (0);
    from = keyBytes;
    to = keyBytesCopy;
    for (count = 0 ; count < keyLength ; count++)
        *to++ = *from++;
    pKey->keyLength = count;
    pKey->keyBytes = keyBytesCopy;
    return (1);
  }

5. Description of RC5 Key Expansion

this section describes the key expansion algorithm ๐ŸŒŸ To be specific, the sample code assumes the block size is 64 bits, and several programming parameters depend on that block size ๐ŸŽ€

  /* Definitions for RC5 as a 64 bit block cipher. */
  /* The "unsigned int" will be 32 bits on all but */
  /* the oldest compilers, which will make it 16 bits. */
  /* On a DEC Alpha "unsigned long" is 64 bits, not 32. */
  #define RC5_WORD     unsigned int
  #define W            (32)
  #define WW           (W / 8)
  #define ROT_MASK     (W - 1)
  #define BB           ((2 * W) / 8) /* Bytes per block */
  /* Define macros used in multiple procedures. */
  /* These macros assumes ">>" is an unsigned operation, */
  /* and that x and s are of type RC5_WORD. */
  #define SHL(x,s)    ((RC5_WORD)((x)<<((s)&ROT_MASK)))
  #define SHR(x,s,w)  ((RC5_WORD)((x)>>((w)-((s)&ROT_MASK))))
  #define ROTL(x,s,w) ((RC5_WORD)(SHL((x),(s))|SHR((x),(s),(w))))

5.1 Definition of initialization constants ๐ŸŽ€

Okay so, there are two magic constants, Pw and Qw, and they're defined for any word size W like this ๐Ÿ”ฎ

Pw = Odd((e-2)*2**W)

Qw = Odd((phi-1)*2**W)

Where e is the base of the natural logarithm (2.71828 ...), phi is the golden ratio (1.61803 ...), 2**W means 2 raised to the power of W, and Odd(x) gives you x if it's already odd, or x + 1 if it's even. โœจ For W equal to 16, 32, and 64, the Pw and Qw constants are these hex values:

#define P16  0xb7e1
#define Q16  0x9e37
#define P32  0xb7e15163
#define Q32  0x9e3779b9
#define P64  0xb7e151628aed2a6b
#define Q64  0x9e3779b97f4a7c15
#if W == 16
#define Pw   P16 /* Select 16 bit word size */
#define Qw   Q16
#endif
#if W == 32
#define Pw   P32 /* Select 32 bit word size */
#define Qw   Q32
#endif
#if W == 64
#define Pw   P64 /* Select 64 bit word size */
#define Qw   Q64
#endif

5.2 Interface definition ๐Ÿ’…

So the key expansion routine takes your b-byte secret key, K, and turns it into an expanded key, S. S is a sequence of T = 2*(R+1) words, and it's built using two constants that come from e and phi. First those constants initialize S, then S gets modified using K. Here's what a C procedure header for this routine could look like ๐Ÿงš

/* Expand an RC5 user key.
 */
void RC5_Key_Expand (b, K, R, S)
  int      b; /* Byte length of secret key */
  char        *K; /* Secret key */
  int      R; /* Number of rounds */
  RC5_WORD *S;    /* Expanded key buffer, 2*(R+1) words */
{

5.3 Convert secret key from bytes to words ๐Ÿซถ

Step one is converting that b-byte key into a bunch of words stored in the array L. On a little-endian processor, you do this by zeroing out L and then copying in the b bytes of K. The C code below gets the same result on all processors ๐ŸŒธ

  int i, j, k, LL, t, T;
  RC5_WORD    L[256/WW];  /* Based on max key size */
  RC5_WORD    A, B;

  /* LL is number of elements used in L. */
  LL = (b + WW - 1) / WW;
  for (i = 0 ; i < LL ; i++)  {
      L[i] = 0;
  }
  for (i = 0 ; i < b ; i++)  {
      t = (K[i] & 0xFF) << (8*(i%4)); /* 0, 8, 16, 24*/
      L[i/WW] = L[i/WW] + t;
  }

5.4 Initialize the expanded key table ๐Ÿฆ‹

Now we fill up the S table with a fixed pattern that doesn't depend on the key at all. It's an arithmetic progression built from Pw and Qw, taken modulo 2**W, so S[i] equals i*Qw + Pw modulo 2**W. You could precompute this table and copy it whenever you need it, or just compute it on the fly. In C it looks like this ๐Ÿ’œ

  T = 2*(R+1);
  S[0] = Pw;
  for (i = 1 ; i < T ; i++)  {
      S[i] = S[i-1] + Qw;
  }

5.5 Mix in the secret key ๐Ÿ”ฅ

This is where your secret key, K, actually gets mixed into the expanded key, S. First, we work out how many iterations of the mixing function we need, called k. It's set to three times the bigger of two numbers: LL, the number of initialized elements of L, and T, the number of elements in S. ๐Ÿ‘‘

Each iteration kinda works like one pass of the encryption inner loop, where two variables, A and B, get updated by the first and second halves of the iteration. At the start, A and B are zero, and so are the indexes into S, which is i, and into L, which is j. In the first half, we add up S[i], A and B to get a partial result. The new A is that partial result rotated left by three bits, and then A goes into S[i]. The second half adds L[j], A and B together to get a second partial result. That gets rotated left by A+B bit positions and becomes the new B, which goes into L[j]. At the end of each iteration, i and j go up by one, wrapping around modulo the size of their own arrays. In C it's:

  i = j = 0;
  A = B = 0;
  if (LL > T)
      k = 3 * LL; /* Secret key len > expanded key. */
  else
      k = 3 * T;  /* Secret key len < expanded key. */
  for ( ; k > 0 ; k--)  {
      A = ROTL(S[i] + A + B, 3, W);
      S[i] = A;
      B = ROTL(L[j] + A + B, A + B, W);
      L[j] = B;
      i = (i + 1) % T;
      j = (j + 1) % LL;
  }
  return;
} /* End of RC5_Key_Expand */

6. Description of RC5 Block Cipher โœจ

This section walks through how the RC5 block cipher encrypts one single input block. Decryption is just the same steps in reverse, so we're not going to spell that out. RC5 is set up by a version number, V, a round count, R, and a word size in bits, W. This description matches the original version of RC5 (V = 16 decimal), and it covers any positive value for R plus the values 16, 32, and 64 for W. ๐Ÿฆ‹

The inputs to this process are the expanded key table, S, the number of rounds, R, the input buffer pointer, in, and the output buffer pointer, out. A possible C procedure header for it would be:

void RC5_Block_Encrypt (S, R, in, out)
  RC5_WORD    *S;
  int  R;
  char    *in;
  char    *out;
{

6.1 Loading A and B values ๐ŸŒˆ

First, we turn the input bytes into two unsigned integers called A and B. When RC5 is used as a 64 bit block cipher, A and B are 32 bit values. The first input byte becomes the least significant byte of A, and the fourth input byte becomes the most significant byte of A. The fifth input byte becomes the least significant byte of B, and the last input byte becomes the most significant byte of B. This is super efficient on little-endian processors like the Intel family ๐Ÿ’– In C it looks like this:

  int  i;
  RC5_WORD    A, B;

  A  =  in[0] & 0xFF;
  A += (in[1] & 0xFF) << 8;
  A += (in[2] & 0xFF) << 16;
  A += (in[3] & 0xFF) << 24;
  B  =  in[4] & 0xFF;
  B += (in[5] & 0xFF) << 8;
  B += (in[6] & 0xFF) << 16;
  B += (in[7] & 0xFF) << 24;

6.2 Iterating the round function ๐Ÿ“

This is the step where the expanded key gets mixed with the input for the core encryption operation. The first two words of the expanded key get added to A and B respectively, and then the round function gets repeated R times. ๐Ÿ”ฅ

The first half of the round function works out a new A from A, B, and the next unused word in the expanded key table. Basically, A gets XOR'ed with B, and that first partial result is rotated to the left by an amount set by B, which gives the second partial result. The rotation happens on a W bit boundary, so it's a 32 bit rotation for the version of RC5 with a 64 bit block size. The actual rotation amount only depends on the least significant log base-2 of W bits of B. Then the next unused word of the expanded key table gets added to that second partial result, and the answer becomes the new A. ๐Ÿ‘‘

The second half of the round function is identical, except the roles of A and B are switched. So B gets exclusive or'ed with A, that first partial result gets rotated to the left by an amount set by A to form the second partial result, and then the next unused word of the expanded key table gets added to it. That becomes the new B. ๐Ÿ’…

Here's one way to write it in C:

  A = A + S[0];
  B = B + S[1];
  for (i = 1 ; i <= R ; i++) {
      A = A ^ B;
      A = ROTL(A, B, W) + S[2*i];
      B = B ^ A;
      B = ROTL(B, A, W) + S[(2*i)+1];
  }

6.3 Storing the A and B values ๐Ÿงš

The last step is turning A and B back into a sequence of bytes. It's basically the reverse of the load step. In C it could look like this:

  out[0] = (A >>  0) & 0xFF;
  out[1] = (A >>  8) & 0xFF;
  out[2] = (A >> 16) & 0xFF;
  out[3] = (A >> 24) & 0xFF;
  out[4] = (B >>  0) & 0xFF;
  out[5] = (B >>  8) & 0xFF;
  out[6] = (B >> 16) & 0xFF;
  out[7] = (B >> 24) & 0xFF;
  return;
} /* End of RC5_Block_Encrypt */

7. Description of RC5-CBC and RC5-CBC-Pad ๐Ÿฆ‹

This section covers the CBC and CBC-Pad modes of the RC5 cipher. It builds on the RC5 key objects and the RC5 block cipher we just went through ๐Ÿ’œ

7.1 Creating cipher objects ๐ŸŽ€

The cipher object has to keep track of the padding mode, the number of rounds, the expanded key, the initialization vector, the CBC chaining block, and an input buffer. In C, a structure definition for that could look like this:

/* Definition of the RC5 CBC algorithm object.
 */
typedef struct rc5CBCAlg
{
  int          Pad;   /* 1 = RC5-CBC-Pad, 0 = RC5-CBC. */
  int          R;     /* Number of rounds. */
  RC5_WORD        *S;     /* Expanded key. */
  unsigned char    I[BB]; /* Initialization vector. */
  unsigned char    chainBlock[BB];
  unsigned char    inputBlock[BB];
  int          inputBlockIndex; /* Next inputBlock byte. */
} rc5CBCAlg;

To create a cipher algorithm object, you check the parameters first, then allocate space for the expanded key table. The expanded key gets initialized with the method we covered earlier. Last, the state variables (padding mode, number of rounds, and the input buffer) get set to their starting values. In C it goes like this ๐ŸŒธ

/* Allocate and initialize the RC5 CBC algorithm object.
 * Return 0 if problems.
 */
rc5CBCAlg *RC5_CBC_Create (Pad, R, Version, bb, I)
  int      Pad;       /* 1 = RC5-CBC-Pad, 0 = RC5-CBC. */
  int      R;         /* Number of rounds. */
  int      Version;   /* RC5 version number. */
  int      bb;        /* Bytes per RC5 block == IV len. */
  char     *I;        /* CBC IV, bb bytes long. */
{

  rc5CBCAlg    *pAlg;
  int           index;

  if ((Version != RC5_FIRST_VERSION) ||
      (bb != BB) ||   (R < 0) || (255 < R))
      return ((rc5CBCAlg *) 0);
  pAlg = (rc5CBCAlg *) malloc (sizeof(*pAlg));
  if (pAlg == ((rc5CBCAlg *) 0))
      return ((rc5CBCAlg *) 0);
  pAlg->S = (RC5_WORD *) malloc (BB * (R + 1));
  if (pAlg->S == ((RC5_WORD *) 0))    {
      free (pAlg);
      return ((rc5CBCAlg *) 0);
  }
  pAlg->Pad = Pad;
  pAlg->R = R;
  pAlg->inputBlockIndex = 0;
  for (index = 0 ; index < BB ; index++)
      pAlg->I[index] = I[index];
  return (pAlg);
}

7.2 Destroying cipher objects ๐Ÿ”

Destroying a cipher object is basically the reverse of creating it. Be careful to zero out the memory before handing it back to the memory manager. In C it could look like this ๐Ÿ™ˆ

/* Zero and free an RC5 algorithm object.
 */
void RC5_CBC_Destroy (pAlg)
  rc5CBCAlg   *pAlg;
{
  RC5_WORD    *to;
  int      count;

  if (pAlg == ((rc5CBCAlg *) 0))
      return;
  if (pAlg->S == ((RC5_WORD *) 0))
      return;
  to = pAlg->S;
  for (count = 0 ; count < (1 + pAlg->R) ; count++)
  {
      *to++ = 0;  /* Two expanded key words per round. */
      *to++ = 0;
  }
 free (pAlg->S);
  for (count = 0 ; count < BB ; count++)
  {
      pAlg->I[count] = (unsigned char) 0;
      pAlg->inputBlock[count] = (unsigned char) 0;
      pAlg->chainBlock[count] = (unsigned char) 0;
  }
  pAlg->Pad = 0;
  pAlg->R = 0;
  pAlg->inputBlockIndex = 0;
  free (pAlg);
}

7.3 Setting the IV for cipher objects โœจ

okay so for CBC cipher objects, the state of the algorithm depends on the expanded key, the CBC chain block, and any internally buffered input ๐Ÿง . Often the same key gets used with tons of messages, and each one has its own unique initialization vector. Making a brand new cipher object every single time is so much overhead ๐Ÿ˜ฉ, so it makes more sense to have an operation that lets the caller swap the IV on an existing cipher object. In C, that could look like this:

  /* Setup a new initialization vector for a CBC operation
   * and reset the CBC object.
   * This can be called after Final without needing to
   * call Init or Create again.
   * Return zero if problems.
   */
  int RC5_CBC_SetIV (pAlg, I)
    rc5CBCAlg   *pAlg;
    char        *I;     /* CBC Initialization vector, BB bytes. */
  {
    int     index;

    pAlg->inputBlockIndex = 0;
    for (index = 0 ; index < BB ; index++)
    {
        pAlg->I[index] = pAlg->chainBlock[index] = I[index];
        pAlg->inputBlock[index] = (unsigned char) 0;
    }
    return (1);
  }

7.4 Binding a key to a cipher object ๐Ÿ”‘

the operation that binds a key to a cipher object is the one that does the key expansion ๐Ÿ’…. Key expansion could technically be an operation on keys, but that would not work correctly for ciphers that modify the expanded key as they operate ๐Ÿ™ˆ. After expanding the key, this operation must initialize the CBC chain block from the initialization vector and prepare the input buffer to receive the first character. In C, it could be done like this:

  /* Initialize the encryption object with the given key.
   * After this routine, the caller frees the key object.
   * The IV for this CBC object can be changed by calling
   * the SetIV routine.  The only way to change the key is
   * to destroy the CBC object and create a new one.
   * Return zero if problems.
   */
  int RC5_CBC_Encrypt_Init (pAlg, pKey)
    rc5CBCAlg       *pAlg;
    rc5UserKey  *pKey;
  {
    if ((pAlg == ((rc5CBCAlg *) 0)) ||
        (pKey == ((rc5UserKey *) 0)))
        return (0);
    RC5_Key_Expand (Key->keyLength, pKey->keyBytes,
                    pAlg->R, pAlg->S);
    return (RC5_CBC_SetIV(pAlg, pAlg->I));
  }

7.5 Processing part of a message ๐Ÿ“ฆ

the encryption here uses the Init-Update-Final paradigm ๐ŸŽ€. The update operation can run on a sequence of message parts, so you incrementally produce the ciphertext bit by bit (well, byte by byte ๐Ÿ˜ญ). Once the last part is processed, you call Final to grab any plaintext bytes or padding that are still buffered inside the cipher object. A procedure header for this operation would look something like:

  /* Encrypt a buffer of plaintext.
   * The plaintext and ciphertext buffers can be the same.
   * The byte len of the ciphertext is put in *pCipherLen.
   * Call this multiple times passing successive
   * parts of a large message.
   * After the last part has been passed to Update,
   * call Final.
   * Return zero if problems like output buffer too small.
   */
  int RC5_CBC_Encrypt_Update (pAlg, N, P,
                              pCipherLen, maxCipherLen, C)
    rc5CBCAlg   *pAlg;      /* Cipher algorithm object. */
    int          N;         /* Byte length of P. */
    char        *P;         /* Plaintext buffer. */
    int         *pCipherLen;/* Gets byte len of C. */
    int          maxCipherLen;  /* Size of C. */
    char        *C;         /* Ciphertext buffer. */
  {

7.5.1 Output buffer size check. ๐Ÿ‘€

the first step of plaintext processing is making sure the output buffer is big enough to hold the ciphertext ๐Ÿซถ. The ciphertext gets produced in multiples of the block size, and it depends on how many plaintext characters get passed into this operation plus anything already sitting in the cipher object's internal buffer. In C code, that's:

    int      plainIndex, cipherIndex, j;

    /* Check size of the output buffer. */
    if (maxCipherLen < (((pAlg->inputBlockIndex+N)/BB)*BB))
    {
        *pCipherLen = 0;
        return (0);
    }

7.5.2 Divide plaintext into blocks ๐Ÿฐ

next up, we keep adding characters to the internal buffer until a full block is built ๐Ÿงฑ. When that happens, the buffer pointers get reset and the input buffer gets exclusive-or'ed (XORed) with the CBC chaining block ๐Ÿ’œ. The byte order of the chaining block matches the input block. For example, the ninth input byte gets XORed with the first ciphertext byte. The result then goes into the RC5 block cipher we talked about earlier ๐Ÿ”ฅ. To cut down on data movement and byte alignment problems, the RC5 output can be written straight into the CBC chaining block. Finally, that output gets copied into the ciphertext buffer the user gave you, and before returning, the actual size of the ciphertext is passed back to the caller. In C, this step looks like:

    plainIndex = cipherIndex = 0;
    while (plainIndex < N)
    {
        if (pAlg->inputBlockIndex < BB)
        {
            pAlg->inputBlock[pAlg->inputBlockIndex]
                    = P[plainIndex];
            pAlg->inputBlockIndex++;
            plainIndex++;
        }
        if (pAlg->inputBlockIndex == BB)
        {   /* Have a complete input block, process it. */
            pAlg->inputBlockIndex = 0;
            for (j = 0 ; j < BB ; j++)
            {   /* XOR in the chain block. */
                pAlg->inputBlock[j] = pAlg->inputBlock[j]
                                 ^ pAlg->chainBlock[j];
            }
            RC5_Block_Encrypt(pAlg->S, pAlg->R
                             pAlg->inputBlock,
                             pAlg->chainBlock);
            for (j = 0 ; j < BB ; j++)
            {   /* Output the ciphertext. */
                C[cipherIndex] = pAlg->chainBlock[j];
                cipherIndex++;
            }
        }
    }
    *pCipherLen = cipherIndex;
    return (1);
  } /* End of RC5_CBC_Encrypt_Update */

7.6 Final block processing ๐Ÿ

this step handles the last block of plaintext ๐Ÿ’–. For RC5-CBC, it just does error checking to make sure the plaintext length really is a multiple of the block length. For RC5-CBC-Pad, padding bytes get added to the plaintext โœจ. All the pad bytes are the same, and each one is set to a value that tells you how many bytes of padding there are. For example, if there are eight bytes of padding, they'll all be hexadecimal 0x08 ๐ŸŒธ. There will always be between one and BB padding bytes, inclusive. In C code, that's:

  /* Produce the final block of ciphertext including any
   * padding, and then reset the algorithm object.
   * Return zero if problems.
   */
  int RC5_CBC_Encrypt_Final (pAlg, pCipherLen, maxCipherLen, C)
    rc5CBCAlg   *pAlg;
    int         *pCipherLen;    /* Gets byte len of C. */
    int          maxCipherLen;  /* Len of C buffer. */
    char        *C;             /* Ciphertext buffer. */
  {
    int     cipherIndex, j;
    int     padLength;

    /* For non-pad mode error if input bytes buffered. */
    *pCipherLen = 0;
    if ((pAlg->Pad == 0) && (pAlg->inputBlockIndex != 0))
        return (0);

    if (pAlg->Pad == 0)
        return (1);
    if (maxCipherLen < BB)
        return (0);

    padLength = BB - pAlg->inputBlockIndex;
    for (j = 0 ; j < padLength ; j++)
    {
        pAlg->inputBlock[pAlg->inputBlockIndex]
               = (unsigned char) padLength;
        pAlg->inputBlockIndex++;
    }
    for (j = 0 ; j < BB ; j++)
    {   /* XOR the chain block into the plaintext block. */
        pAlg->inputBlock[j] = pAlg->inputBlock[j]
                             ^ pAlg->chainBlock[j];
    }
    RC5_Block_Encrypt(pAlg->S, pAlg->R,
                      pAlg->inputBlock, pAlg->chainBlock);
    cipherIndex = 0;
    for (j = 0 ; j < BB ; j++)
    {   /* Output the ciphertext. */
        C[cipherIndex] = pAlg->chainBlock[j];
        cipherIndex++;
    }
    *pCipherLen = cipherIndex;

    /* Reset the CBC algorithm object. */
    return (RC5_CBC_SetIV(pAlg, pAlg->I));
  } /* End of RC5_CBC_Encrypt_Final */

8. Description of RC5-CTS ๐Ÿฆ‹

the Cipher Text Stealing (CTS) mode for block ciphers is described by Schneier on pages 195 and 196 of [6] ๐Ÿ“š. This mode handles any length of plaintext and produces ciphertext whose length matches the plaintext length, which is so iconic ๐Ÿ‘‘. CTS acts like CBC mode for everything except the last two blocks of the plaintext. Here's how to handle those last two parts, called Pn-1 and Pn, where Pn-1 is exactly one block (BB) long and the last block, Pn, is Ln bytes. Ln ranges from 1 to BB inclusive, so Pn could actually be a complete block ๐Ÿ™ˆ.

  1. Exclusive-or Pn-1 with the previous ciphertext block, Cn-2, to create Xn-1.
  2. Encrypt Xn-1 to create En-1.
  3. Select the first Ln bytes of En-1 to create Cn.
  4. Pad Pn with zeros at the end to create P of length BB.
  5. Exclusive-or En-1 with P to create to create Dn.
  6. Encrypt Dn to create Cn-1
  7. The last two parts of the ciphertext are Cn-1 and Cn respectively.

to implement CTS encryption, the RC5-CTS object has to hold on to (buffer) at most 2*BB bytes of plaintext and process them specially when the RC5_CTS_Encrypt_Final routine is called ๐Ÿซถ.

here's how to decrypt Cn-1 and Cn ๐Ÿ’…:

  1. Decrypt Cn-1 to create Dn.
  2. Pad Cn with zeros at the end to create C of length BB.
  3. Exclusive-or Dn with C to create Xn.
  4. Select the first Ln bytes of Xn to create Pn.
  5. Append the tail (BB minus Ln) bytes of Xn to Cn to create En.
  6. Decrypt En to create Pn-1.
  7. The last two parts of the plaintext are Pn-1 and Pn respectively.

9. Test Program and Vectors ๐Ÿงช

to help confirm an implementation is correct, this section gives a test program and results from a set of test vectors ๐ŸŒˆ.

9.1 Test Program โœจ

okay so bestie, here's a C test program ๐Ÿ’… it reads test vectors from its input stream and writes results to its output stream. the subsections after this give a set of test vectors for inputs and the matching outputs ๐ŸŽ€

#include <stdio.h>

#define BLOCK_LENGTH     (8 /* bytes */)
#define MAX_KEY_LENGTH   (64 /* bytes */)
#define MAX_PLAIN_LENGTH (128 /* bytes */)
#define MAX_CIPHER_LENGTH(MAX_PLAIN_LENGTH + BLOCK_LENGTH)
#define MAX_ROUNDS       (20)
#define MAX_S_LENGTH     (2 * (MAX_ROUNDS + 1))

typedef struct test_vector
{
  int padding_mode;
  int rounds;
  char    keytext[2*MAX_KEY_LENGTH+1];
  int key_length;
  char    key[MAX_KEY_LENGTH];
  char    ivtext[2*BLOCK_LENGTH+1];
  int iv_length;
  char    iv[BLOCK_LENGTH];
  char    plaintext[2*MAX_PLAIN_LENGTH+1];
  int plain_length;
  char    plain[MAX_PLAIN_LENGTH];
  char    ciphertext[2*MAX_CIPHER_LENGTH+1];
  int cipher_length;
  char    cipher[MAX_CIPHER_LENGTH];
  RC5_WORD    S[MAX_S_LENGTH];
} test_vector;

void show_banner()
{
  (void) printf("RC5 CBC Tester.\n");
  (void) printf("Each input line should contain the following\n");
  (void) printf("test parameters separated by a single space:\n");
  (void) printf("- Padding mode flag.  Use 1 for RC5_CBC_Pad, else
0.\n");
  (void) printf("- Number of rounds for RC5.\n");
  (void) printf("- Key bytes in hexadecimal.  Two characters per
byte like '01'.\n");
  (void) printf("- IV bytes in hexadecimal.  Must be 16 hex
characters.\n");
  (void) printf("- Plaintext bytes in hexadecimal.\n");
  (void) printf("An end of file or format error terminates the
tester.\n");
  (void) printf("\n");
}
/* Convert a buffer from ascii hex to bytes.
 * Set pTo_length to the byte length of the result.
 * Return 1 if everything went OK.
 */
int hex_to_bytes (from, to, pTo_length)
  char    *from, *to;
  int     *pTo_length;
{
  char    *pHex;  /* Ptr to next hex character. */
  char    *pByte;     /* Ptr to next resulting byte. */
  int  byte_length = 0;
  int  value;

  pByte = to;
  for (pHex = from ; *pHex != 0 ; pHex += 2)  {
      if (1 != sscanf(pHex, "%02x", &value))
          return (0);
      *pByte++ = ((char)(value & 0xFF));
      byte_length++;
  }
  *pTo_length = byte_length;
  return (1);
}

/* Convert a buffer from bytes to ascii hex.
 * Return 1 if everything went OK.
 */
int bytes_to_hex (from, from_length, to)
  char    *from, *to;
  int from_length;
{
  char    *pHex;  /* Ptr to next hex character. */
  char    *pByte;     /* Ptr to next resulting byte. */
  int  value;

  pHex = to;
  for (pByte = from ; from_length > 0 ; from_length--)  {
      value = *pByte++ & 0xFF;
      (void) sprintf(pHex, "%02x", value);
      pHex += 2;
  }
  return (1);
}

/* Return 1 if get a valid test vector. */
int get_test_vector(ptv)
  test_vector *ptv;
{

  if (1 != scanf("%d", &ptv->padding_mode))
      return (0);
  if (1 != scanf("%d", &ptv->rounds))
      return (0);
  if ((ptv->rounds < 0) || (MAX_ROUNDS < ptv->rounds))
      return (0);
  if (1 != scanf("%s", &ptv->keytext))
      return (0);
  if (1 != hex_to_bytes(ptv->keytext, ptv->key,
                       &ptv->key_length))
      return (0);
  if (1 != scanf("%s", &ptv->ivtext))
      return (0);
  if (1 != hex_to_bytes(ptv->ivtext, ptv->iv,
                       &ptv->iv_length))
      return (0);
  if (BLOCK_LENGTH != ptv->iv_length)
      return (0);
  if (1 != scanf("%s", &ptv->plaintext))
      return (0);
  if (1 != hex_to_bytes(ptv->plaintext, ptv->plain,
                       &ptv->plain_length))
      return (0);
  return (1);
}

void run_test (ptv)
  test_vector *ptv;
{
  rc5UserKey  *pKey;
  rc5CBCAlg       *pAlg;
  int          numBytesOut;

  pKey = RC5_Key_Create ();
  RC5_Key_Set (pKey, ptv->key_length, ptv->key);

  pAlg = RC5_CBC_Create (ptv->padding_mode,
                  ptv->rounds,
                  RC5_FIRST_VERSION,
                  BB,
                  ptv->iv);
  (void) RC5_CBC_Encrypt_Init (pAlg, pKey);
  ptv->cipher_length = 0;
  (void) RC5_CBC_Encrypt_Update (pAlg,
                  ptv->plain_length, ptv->plain,
                  &(numBytesOut),
                  MAX_CIPHER_LENGTH - ptv->cipher_length,
                  &(ptv->cipher[ptv->cipher_length]));

  ptv->cipher_length += numBytesOut;
  (void) RC5_CBC_Encrypt_Final (pAlg,
                  &(numBytesOut),
                  MAX_CIPHER_LENGTH - ptv->cipher_length,
                  &(ptv->cipher[ptv->cipher_length]));
  ptv->cipher_length += numBytesOut;
  bytes_to_hex (ptv->cipher, ptv->cipher_length,
               ptv->ciphertext);
  RC5_Key_Destroy (pKey);
  RC5_CBC_Destroy (pAlg);
}

void show_results (ptv)
  test_vector *ptv;
{
  if (ptv->padding_mode)
      printf ("RC5_CBC_Pad ");
  else
      printf ("RC5_CBC     ");
  printf ("R = %2d ", ptv->rounds);
  printf ("Key = %s ", ptv->keytext);
  printf ("IV = %s ", ptv->ivtext);
  printf ("P = %s ", ptv->plaintext);
  printf ("C = %s", ptv->ciphertext);
  printf ("\n");
}

int main(argc, argv)
  int argc;
  char *argv[];
{
  test_vector tv;
  test_vector *ptv = &tv;

  show_banner();
  while (get_test_vector(ptv))  {
      run_test(ptv);
      show_results(ptv);
  }
  return (0);
}

9.2 Test vectors ๐Ÿฆ‹

this is the input file for the test program above ๐Ÿซถ the outputs come in the next subsection, so no peeking yet ๐Ÿ™ˆ

0 00 00                 0000000000000000 0000000000000000
0 00 00                 0000000000000000 ffffffffffffffff
0 00 00                 0000000000000001 0000000000000000
0 00 00                 0000000000000000 0000000000000001
0 00 00                 0102030405060708 1020304050607080
0 01 11                 0000000000000000 0000000000000000
0 02 00                 0000000000000000 0000000000000000
0 02 00000000           0000000000000000 0000000000000000
0 08 00                 0000000000000000 0000000000000000
0 08 00                 0102030405060708 1020304050607080
0 12 00                 0102030405060708 1020304050607080
0 16 00                 0102030405060708 1020304050607080
0 08 01020304           0000000000000000 ffffffffffffffff
0 12 01020304           0000000000000000 ffffffffffffffff
0 16 01020304           0000000000000000 ffffffffffffffff
0 12 0102030405060708   0000000000000000 ffffffffffffffff
0 08 0102030405060708   0102030405060708 1020304050607080
0 12 0102030405060708   0102030405060708 1020304050607080
0 16 0102030405060708   0102030405060708 1020304050607080
0 08 01020304050607081020304050607080
                        0102030405060708 1020304050607080
0 12 01020304050607081020304050607080
                        0102030405060708 1020304050607080
0 16 01020304050607081020304050607080
                        0102030405060708 1020304050607080

0 12 0102030405         0000000000000000 ffffffffffffffff
0 08 0102030405         0000000000000000 ffffffffffffffff
0 08 0102030405         7875dbf6738c6478 0808080808080808
1 08 0102030405         0000000000000000 ffffffffffffffff

0 08 0102030405         0000000000000000 0000000000000000
0 08 0102030405         7cb3f1df34f94811 1122334455667701

1 08 0102030405         0000000000000000
ffffffffffffffff7875dbf6738c647811223344556677

9.3 Test results ๐ŸŒˆ

this is what the test program spits out when you feed it the inputs from 9.2 ๐Ÿ’œ โœจ

RC5 CBC Tester.
Each input line should contain the following
test parameters separated by a single space:
- Padding mode flag.  Use 1 for RC5_CBC_Pad, else 0.
- Number of rounds for RC5.
- Key bytes in hexadecimal.  Two characters per byte
  like '01'.
- IV bytes in hexadecimal.  Must be 16 hex characters.
- Plaintext bytes in hexadecimal.
An end of file or format error terminates the tester.

RC5_CBC     R =  0 Key = 00 IV = 0000000000000000
 P = 0000000000000000 C = 7a7bba4d79111d1e
RC5_CBC     R =  0 Key = 00 IV = 0000000000000000
 P = ffffffffffffffff C = 797bba4d78111d1e
RC5_CBC     R =  0 Key = 00 IV = 0000000000000001
 P = 0000000000000000 C = 7a7bba4d79111d1f
RC5_CBC     R =  0 Key = 00 IV = 0000000000000000
 P = 0000000000000001 C = 7a7bba4d79111d1f
RC5_CBC     R =  0 Key = 00 IV = 0102030405060708
 P = 1020304050607080 C = 8b9ded91ce7794a6
RC5_CBC     R =  1 Key = 11 IV = 0000000000000000
 P = 0000000000000000 C = 2f759fe7ad86a378
RC5_CBC     R =  2 Key = 00 IV = 0000000000000000
 P = 0000000000000000 C = dca2694bf40e0788
RC5_CBC     R =  2 Key = 00000000 IV = 0000000000000000
 P = 0000000000000000 C = dca2694bf40e0788
RC5_CBC     R =  8 Key = 00 IV = 0000000000000000
 P = 0000000000000000 C = dcfe098577eca5ff
RC5_CBC     R =  8 Key = 00 IV = 0102030405060708
 P = 1020304050607080 C = 9646fb77638f9ca8
RC5_CBC     R = 12 Key = 00 IV = 0102030405060708
 P = 1020304050607080 C = b2b3209db6594da4
RC5_CBC     R = 16 Key = 00 IV = 0102030405060708
 P = 1020304050607080 C = 545f7f32a5fc3836
RC5_CBC     R =  8 Key = 01020304 IV = 0000000000000000
 P = ffffffffffffffff C = 8285e7c1b5bc7402
RC5_CBC     R = 12 Key = 01020304 IV = 0000000000000000
 P = ffffffffffffffff C = fc586f92f7080934
RC5_CBC     R = 16 Key = 01020304 IV = 0000000000000000
 P = ffffffffffffffff C = cf270ef9717ff7c4
RC5_CBC     R = 12 Key = 0102030405060708 IV = 0000000000000000
 P = ffffffffffffffff C = e493f1c1bb4d6e8c

RC5_CBC     R =  8 Key = 0102030405060708 IV = 0102030405060708
 P = 1020304050607080 C = 5c4c041e0f217ac3
RC5_CBC     R = 12 Key = 0102030405060708 IV = 0102030405060708
 P = 1020304050607080 C = 921f12485373b4f7
RC5_CBC     R = 16 Key = 0102030405060708 IV = 0102030405060708
 P = 1020304050607080 C = 5ba0ca6bbe7f5fad
RC5_CBC     R =  8 Key = 01020304050607081020304050607080
 IV = 0102030405060708
 P = 1020304050607080 C = c533771cd0110e63
RC5_CBC     R = 12 Key = 01020304050607081020304050607080
 IV = 0102030405060708
 P = 1020304050607080 C = 294ddb46b3278d60
RC5_CBC     R = 16 Key = 01020304050607081020304050607080
 IV = 0102030405060708
 P = 1020304050607080 C = dad6bda9dfe8f7e8
RC5_CBC     R = 12 Key = 0102030405 IV = 0000000000000000
 P = ffffffffffffffff C = 97e0787837ed317f
RC5_CBC     R =  8 Key = 0102030405 IV = 0000000000000000
 P = ffffffffffffffff C = 7875dbf6738c6478
RC5_CBC     R =  8 Key = 0102030405 IV = 7875dbf6738c6478
 P = 0808080808080808 C = 8f34c3c681c99695
RC5_CBC_Pad R =  8 Key = 0102030405 IV = 0000000000000000
 P = ffffffffffffffff C = 7875dbf6738c64788f34c3c681c99695
RC5_CBC     R =  8 Key = 0102030405 IV = 0000000000000000
 P = 0000000000000000 C = 7cb3f1df34f94811
RC5_CBC     R =  8 Key = 0102030405 IV = 7cb3f1df34f94811
 P = 1122334455667701 C = 7fd1a023a5bba217
RC5_CBC_Pad R =  8 Key = 0102030405 IV = 0000000000000000
 P = ffffffffffffffff7875dbf6738c647811223344556677
 C = 7875dbf6738c64787cb3f1df34f948117fd1a023a5bba217

10. Security Considerations ๐Ÿ”’โœจ

okay bestie, this is the serious part, so listen up ๐Ÿ‘‘ RC5 is still pretty new, which means critical reviews are still happening right now. The good news is that its simple structure makes it easy to analyze, so hopefully it's easier to figure out how strong it actually is. And honestly? Reviews so far are very promising ๐Ÿ’–

Early results [1] suggest that for RC5 with a 64 bit block size (32 bit word size), 12 rounds will suffice to resist linear and differential cyptanalysis. The 128 bit block version hasn't been studied as much as the 64 bit one, but it looks like 16 rounds would be an appropriate minimum ๐Ÿฆ‹ Block sizes less than 64 bits are academically interesting, but they should not be used for cryptographic security ๐Ÿ™…โ€โ™€๏ธ Greater security can be achieved by increasing the number of rounds, but that costs you throughput, so it's a trade-off ๐Ÿ’…

The length of the secret key helps decide how well the cipher holds up against brute force key searching attacks. A key length of 128 bits should give adequate protection against brute force key searching by a well funded opponent for a couple decades [7] โœจ For RC5 with 12 rounds, the key setup time and data encryption time are the same for all key lengths less than 832 bits, so there's no performance reason to pick short keys ๐Ÿ™ˆ For larger keys, the key expansion step will run slower because the user key table, L, will be longer than the expanded key table, S. However, the encryption time stays unchanged, since it only depends on the number of rounds ๐ŸŒธ

To comply with export regulations it may be necessary to choose keys that only have 40 unknown bits. A poor way to do this would be to choose a simple 5 byte key. This should be avoided, because it would be easy for an opponent to pre-compute key searching information ๐Ÿ’€ Another common mechanism is to pick a 128 bit key and publish the first 88 bits. This method reveals a large number of the entries in the user key table, L, and whether RC5 key expansion provides adequate security in this situation has not been studied, though it may be fine ๐Ÿคทโ€โ™€๏ธ A conservative way to conform to a 40 bit limitation is to pick a seed value of 128 bits, publish 88 bits of this seed, run the entire seed through a hash function like MD5 [4], and use the 128 bit output of the hash function as the RC5 key ๐Ÿงš

In the case of 40 unknown key bits with 88 known key bits (i.e., 88 salt bits) there should still be 12 or more rounds for the 64 bit block version of RC5, otherwise the value of adding salt bits to the key is likely to be lost. ๐Ÿ˜ญ

The lifetime of the key also affects security. For high security applications, the key to any 64 bit block cipher should be changed after encrypting 2**32 blocks (2**64 blocks for a 128 bit block cipher). This helps guard against linear and differential cryptanalysis ๐Ÿ”ฅ For the case of 64 bit blocks, this rule would recommend changing the key after 2**40 (i.e. 10**12) bytes are encrypted. See Schneier [6] page 183 for further discussion ๐Ÿ“š


11. ASN.1 Identifiers ๐Ÿงพ๐Ÿ’œ

For applications that use ASN.1 descriptions, it's necessary to define the algorithm identifier for these ciphers, along with their parameter block formats. The ASN.1 definition of an algorithm identifier already exists, and it's listed below for reference ๐ŸŽ€

AlgorithmIdentifier ::= SEQUENCE {
  algorithm    OBJECT IDENTIFIER,
  parameters   ANY DEFINED BY algorithm OPTIONAL
}

The values for the algorithm field are:

RC5_CBC  OBJECT IDENTIFIER ::=
  { iso (1) member-body (2) US (840) rsadsi (113549)
    encryptionAlgorithm (3) RC5CBC (8) }

RC5_CBC_Pad OBJECT IDENTIFIER ::=
{ iso (1) member-body (2) US (840) rsadsi (113549)
  encryptionAlgorithm (3) RC5CBCPAD (9) }

The structure of the parameters field for these algorithms is given below. NOTE: if the iv field is not included, then the initialization vector defaults to a block of zeros whose size depends on the blockSizeInBits field. โญ

RC5_CBC_Parameters ::= SEQUENCE {
  version           INTEGER (v1_0(16)),
  rounds            INTEGER (8..127),
  blockSizeInBits   INTEGER (64, 128),
  iv                OCTET STRING OPTIONAL
}

References ๐Ÿ“–

[1] Kaliski, Burton S., and Yinqun Lisa Yin, "On Differential and Linear Cryptanalysis of the RC5 Encryption Algorithm", In Advances in Cryptology - Crypto '95, pages 171-184, Springer-Verlag, New York, 1995.

[2] Rivest, Ronald L., "The RC5 Encryption Algorithm", In Proceedings of the Second International Workshop on Fast Software Encryption, pages 86-96, Leuven Belgium, December 1994.

[3] Rivest, Ronald L., "RC5 Encryption Algorithm", In Dr. Dobbs Journal, number 226, pages 146-148, January 1995.

[4] Rivest, Ronald L., "The MD5 Message-Digest Algorithm", RFC 1321.

[5] RSA Laboratories, "Public Key Cryptography Standards (PKCS)", RSA Data Security Inc. See ftp.rsa.com.

[6] Schneier, Bruce, "Applied Cryptography", Second Edition, John Wiley and Sons, New York, 1996. Errata: on page 195, line 13, the reference number should be [402].

[7] Business Software Alliance, Matt Blaze et al., "Minimum Key Length for Symmetric Ciphers to Provide Adequate Commercial Security", http://www.bsa.org/bsa/cryptologists.html.

[8] RSA Data Security Inc., "RC5 Reference Code in C", See the web site: www.rsa.com, for availability. Not available with the first draft of this document.


Authors' Addresses ๐Ÿ’Œ

Robert W. Baldwin
RSA Data Security, Inc.
100 Marine Parkway
Redwood City, CA 94065

Phone: (415) 595-8782
Fax:   (415) 595-1873
EMail: baldwin@rsa.com, or baldwin@lcs.mit.edu


Ronald L. Rivest
Massachusetts Institute of Technology
Laboratory for Computer Science
NE43-324
545 Technology Square
Cambridge, MA 02139-1986

Phone: (617) 253-5880
EMail: rivest@theory.lcs.mit.edu
๐Ÿ“ฆ where this page comes from