# Cipher Library

This library provides functions for encrypting and decrypting data. The following ciphers are currently supported:

AES
  Block cipher
  Symmetric (same key for encryption and decryption)
  Block size: 128 bit (16 bytes)
  Key sizes: 128 bit (16 bytes), 192 bit (24 bytes), 256 bit (32 bytes)
  State of the art. Considered to be secure.

DES
  Block cipher
  Symmetric (same key for encryption and decryption)
  Block size: 64 bit (8 bytes)
  Key size: 64 bit (8 bytes)
  Effective key strength: 56 bit (7 bytes)
  Legacy and insecure. Should not be used unless needed for compatibility with legacy protocols.

RC4
  Stream cipher
  Symmetric (same key for encryption and decryption)
  Block size: none
  Key size: any
  Keys must be unique and must never be reused.
  Should be considered as breakable.

Block ciphers (AES and DES) can be used in different modes of operation. The following modes are currently supported:

ECB (Electronic Code Book Mode)
  The size of the data must be a multiple of the block size.
  Each block is encrypted / decrypted with the same key.
  Prone to statistical cryptanalysis. Should not be used unless needed for compatibility with legacy protocols.

CTR (Counter Mode)
  Turns block ciphers into stream ciphers. So any data size can be processed. It doesn't need to be a multiple of the block size.
  Additional to the key an initialization vector (IV) is needed.
  The combination of key and IV must be unique and must never be reused.
  Considered to be secure (unless key and IV are reused).

CFB (Cipher Feedback Mode)
  Turns block ciphers into stream ciphers. So any data size can be processed. It doesn't need to be a multiple of the block size.
  Additional to the key an initialization vector (IV) is needed.
  The combination of key and IV must be unique and must never be reused.
  Considered to be secure (unless key and IV are reused).

GCM (Galois Counter Mode)
  Turns block ciphers into stream ciphers. So any data size can be processed. It doesn't need to be a multiple of the block size.
  Additional to the key an initialization vector (IV) is needed.
  The combination of key and IV must be unique and must never be reused.
  Also it does a message authentication over the plaintext and some optional associated data, like headers (AEAD cipher). This is useful for avoiding the extra CPU power needed for a keyed hash function like HMAC-SHA256.
  Considered to be secure (unless key and IV are reused).

## File information

File | common/ilib/cipher.h
Classes | Cipher
Data types | cipher_t
Examples | Encryption with AES-256 in counter mode Encryption with AES-128 in cipher feedback mode Single block encryption with DES Encryption with RC4

# Classes

## cipher

    class Cipher {
    public:
        Cipher();
        void Init(cipher_t type, const byte * key, int keyLen, bool encrypt = true, bool makekey = true);
        void Block(const byte * in, byte * out);
        void Crypt(const byte * in, byte * out, int len);
        void CtrCrypt(const byte * in, byte * out, int len, byte * iv);
        bool GcmCrypt(const byte * aad, int aad_len, const byte * in, byte * out, int len, byte * iv, byte * tag);
        void CfbCrypt(const byte * in, byte * out, int len, byte * iv);
        void CbcCrypt(const byte * in, byte * out, int len, byte * iv);
        void Reset();
    };

### Overview

The cipher class defines a uniform interface for encrypting and decrypting data using different algorithms. Please note that currently only a small selection of ciphers and modes of operation is supported.

### Public functions

Init
  Initializes the internal state of the object and sets the algorithm to be used.

  #### Parameters

  cipher_t type | The algorithm to be used.
  const byte * key | A buffer containing the encryption / decryption key.
  int keyLen | The size of the key in bytes. Depending on the type the following key sizes are supported. CIPHER_AES 16 (AES-128) 24 (AES-192) 32 (AES-256) CIPHER_DES 8 CIPHER_RC4 any positive value
  bool encrypt | true if the data shall be encrypted. false if the data shall be decrypted.
  bool makekey | true if the key is to be generated/modified by means of a protocol-specific method. false if the key is to be taken as-is (currently for DES only).

  #### Remarks

  The init function has to be called before using any other functions of the object.
Block
  The function encrypts / decrypts a single block of data.

  #### Parameters

  const byte * in | A buffer containing the data that shall be encrypted / decrypted. The valid buffer sizes for the individual ciphers are: CIPHER_AES 16 CIPHER_DES 8
  const byte * out | A buffer to write the encrypted / decrypted data. It must have the same size as the in buffer.

  #### Remarks

  The function is not implemented for RC4. If the object was initialized with CIPHER_RC4 the function will fail with an assertion.
Crypt
  Implements the ECB mode of operation for AES and DES, and regular encryption for RC4.

  #### Parameters

  const byte * in | A buffer containing the data that shall be encrypted / decrypted.
  byte * out | A buffer to write the encrypted / decrypted data. It must be big enough to contain len bytes.
  int len | The number of bytes that shall be encrypted / decrypted. CIPHER_AES multiple of 16 bytes CIPHER_RC4 any positive value

  #### Remarks

  The function is not implemented for DES. If the object was initialized with CIPHER_DES the function will fail with an assertion.
CtrCrypt
  Implementation of the counter mode of operation.

  #### Parameters

  const byte * in | A buffer containing the data that shall be encrypted / decrypted.
  byte * out | A buffer to write the encrypted / decrypted data. It must be big enough to contain len bytes.
  int len | Any positive number of bytes that shall be encrypted.
  byte * iv | The initialization vector for counter mode. The size must match the block size of the underlying cipher (16 bytes for AES). The number in the iv buffer is incremented, so it can be reused for subsequent encryptions. If it isn't reused but a new iv is set by the application, the Reset() function needs to be called before.

  #### Remarks

  The function is not implemented for DES and RC4. If the object was initialized with CIPHER_DES or CIPHER_RC4 the function will fail with an assertion.
CfbCrypt
  Implementation of the cipher feedback mode of operation.

  #### Parameters

  const byte * in | A buffer containing the data that shall be encrypted / decrypted.
  byte * out | A buffer to write the encrypted / decrypted data. It must be big enough to contain len bytes.
  int len | Any positive number of bytes that shall be encrypted.
  byte * iv | The initialization vector for cipher feedback mode. The size must match the block size of the underlying cipher (16 bytes for AES). The content of the buffer is updated, so it can be reused for subsequent encryptions / decryptions.

  #### Remarks

  The function is not implemented for DES and RC4. If the object was initialized with CIPHER_DES or CIPHER_RC4 the function will fail with an assertion.
CbcCrypt
  Implementation of the cipher block chaining mode of operation.

  #### Parameters

  const byte * in | A buffer containing the data that shall be encrypted / decrypted.
  byte * out | A buffer to write the encrypted / decrypted data. It must be big enough to contain len bytes.
  int len | The number of bytes that shall be encrypted / decrypted. Must be a multiple of the block size (8 bytes for DES).
  byte * iv | The initialization vector for cipher block chaining mode. The size must match the block size of the underlying cipher (8 bytes for DES). The content of the buffer is updated, so it can be reused for subsequent encryptions / decryptions.

  #### Remarks

  The function is not implemented for RC4. If the object was initialized with CIPHER_RC4 the function will fail with an assertion.
Reset
  This function is only needed in combination with CtrCrypt. It must be called each time a new initialization vector defined by the application is used.

  #### Remarks

  The function is not implemented for DES and RC4. If the object was initialized with CIPHER_DES or CIPHER_RC4 the function will fail with an assertion.

# Data types

## cipher_t

    enum cipher_t {
        CIPHER_UNDEFINED,
        CIPHER_DES,
        CIPHER_AES,
        CIPHER_RC4
    };

### Overview

The cipher_t enum defines all ciphers supported by the library.

### Values

CIPHER_UNDEFINED | Used internally to identify uninitialized objects.
CIPHER_DES |
CIPHER_AES |
CIPHER_RC4 |

### Remarks

The old algorithms DES and RC4 are insecure. They should not be used for new projects. Please use AES instead.

# Code Example

## Encryption with AES-256 in counter mode

    byte key[32] = { /*...*/ };
    cipher c;
    c.Init(CIPHER_AES, key, 32, true);

    // encryption of the in1 buffer

    byte iv1[16] = { /*...*/ };
    byte in1[37] = { /*...*/ };
    byte out1[37] = { /*...*/ };

    c.CtrCrypt(in1, out1, 37, iv1);

    // encryption of the in2 buffer in multiple passes

    byte iv2[16] = { /*...*/ };
    byte in2[132] = { /*...*/ };
    byte out2[132] = { /*...*/ };

    c.Reset(); // needed because a new IV is set by the application
    c.CtrCrypt(in2, out2, 64, iv2);
    c.CtrCrypt(in2 + 64, out2 + 64, 64, iv2);
    c.CtrCrypt(in2 + 128, out2 + 128, 4, iv2);

## Encryption with AES-128 in cipher feedback mode

    byte key[16] = { /*...*/ };
    cipher c;
    c.Init(CIPHER_AES, key, 16, true);

    // encryption of the in1 buffer

    byte iv1[16] = { /*...*/ };
    byte in1[37] = { /*...*/ };
    byte out1[37] = { /*...*/ };

    c.CfbCrypt(in1, out1, 37, iv1);

    // encryption of the in2 buffer in multiple passes

    byte iv2[16] = { /*...*/ };
    byte in2[132] = { /*...*/ };
    byte out2[132] = { /*...*/ };

    c.CfbCrypt(in2, out2, 64, iv2);
    c.CfbCrypt(in2 + 64, out2 + 64, 64, iv2);
    c.CfbCrypt(in2 + 128, out2 + 128, 4, iv2);

## Single block encryption with DES

    cipher c;
    byte key[8] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
    byte plaintext[8] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
    byte ciphertext[8];
    byte plaintext_check[8];

    // encrypt
    c.Init(CIPHER_DES, key, 8, true);
    c.Block(plaintext, ciphertext);

    // decrypt
    c.Init(CIPHER_DES, key, 8, false);
    c.Block(ciphertext, plaintext_check);

    if (memcmp(plaintext, plaintext_check, 8) == 0) {
        debug->iprintf("decryption OK");
    }
    else {
        debug->iprintf("decryption failed");
    }

## Encryption with RC4

    byte key[317] = { /*...*/ };
    byte plaintext[510] = { /*...*/ };
    byte ciphertext[510];

    cipher c;
    c.Init(CIPHER_RC4, key, sizeof(key), true);
    c.Crypt(plaintext, ciphertext, sizeof(plaintext));