Saphe Implementation - CryptoStuff.h
/**
 * 
 * Various cryptographic functions:
 *
 * - AES CFB encryption
 * - AES CFB decryption
 * - HMAC calculation
 * - Key derivation
 *
 * CFB is used as it is a stream cipher that can enrypt data streams of any size.
 * Also, it is relatively protected from 'known-plaintext-blocks' attacks.
 *
 * Copyright (C) 2007-2008
 * Uri Sternfeld (saphesolution@yahoo.com)
 * All Rights Reserved
 *
 * Written by Uri Sternfeld
 * Last modified: 30/12/2007
 *
 **/
 
#ifndef __CRYPTOSTUFF_H__
#define __CRYPTOSTUFF_H__
 
#include <windows.h>
 
#include "defs.h"
#include "AES.h"
#include "SHA1.h"
 
#define AES_BLOCK_SIZE 16 // 128 bits
#define CHALLENGE_SIZE 16 // 128 bits
 
/**
 *
 * This struct caries the AES context (expanded key).
 * It also contains a copy constructor that allows quick duplication of contexts.
 *
 **/
struct AESExpandedKey {
    AESExpandedKey() {}
 
    /**
     * copy ctor
     *
     * In:
     *    originalKey - another context to copy from
     **/
    AESExpandedKey(const AESExpandedKey& originalKey) {
        for (uint32 i = 0 ; i < 64 ; ++i) {
            ctx.erk[i] = originalKey.ctx.erk[i];
            ctx.drk[i] = originalKey.ctx.drk[i];
        }
        ctx.nr = originalKey.ctx.nr;
    }
 
    // The context from AES.h
    aes_context ctx;
};    
 
/**
 *
 * Expands the key from the given byte array, and creates a new AESExpandedKey.
 *
 * In:
 *    basicKey - an array of bytes (of AES_BLOCK_SIZE bytes)
 * Out:
 *    expandedKey - AESExpandedKey with a filled context
 * Returns:
 *    nothing
 **/
void AESCryptExpandKey(byte basicKey[AES_BLOCK_SIZE], AESExpandedKey& expandedKey);    
 
/**
 *
 * Encrypts the given block of data using the given expanded key (context)
 * in AES-CFB mode. Note that the context is copied before used (that's why
 * the AESExpandedKey pointer is const). 
 * 
 * No pad is added to the original data.
 * 
 * In:
 *    expandedKey - AESExpandedKey
 *    buffer - an array of bytes to encrypt
 *    bufferSize - the size of the buffer to encrypt
 *    IV - the initialization vector. Should be generated in advance
 * Returns:
 *    nothing
 **/
void AESCFBEncrypt(const AESExpandedKey& expandedKey, 
                   byte* buffer, 
                   dword bufferSize, 
                   const byte IV[AES_BLOCK_SIZE]);
 
/**
 * 
 * Decrypts a given block of data using the given expanded key (context)
 * in AES-CFB mode. Note that the context is copied before used (that's why
 * the AESExpandedKey pointer is const).     
 * 
 * In:
 *  expandedKey - AESExpandedKey
 *  buffer - an array of bytes to decrypt
 *  bufferSize - the size of the buffer to decrypt
 *  IV - the initialization vector
 * Returns:
 *    nothing
 **/
void AESCFBDecrypt(const AESExpandedKey& expandedKey, 
                   byte* buffer, 
                   dword bufferSize, 
                   const byte IV[AES_BLOCK_SIZE]);
 
/**
 * 
 * Computes a SHA-1 hash of the given data (this process comprises of an
 * initialize - update - get results scheme).
 *
 * In:
 *    data - an array of bytes on which the function is computed
 *    dataSize - the size of the data array
 * Out:
 *    digest - the results of the function
 * Returns:
 *    nothing
 **/
void SHA1(const byte* data, dword dataSize, byte digest[SHA1_DIGEST_SIZE]);
 
/**
 *
 * Calculates SHA-1 HMAC (according to FIPS standard) of the given data 
 * using the given key, which is always AES_BLOCK_SIZE bytes long for convenience's
 * sake.
 *
 * In:
 *    key - the encryption key
 *    data - an array of bytes on which the function is calculated
 *    data_size - the size of the data array
 * Out:
 *    hmac - the results of the function
 * Returns:
 *    nothing
 **/
void SHA1_HMAC(const byte key[AES_BLOCK_SIZE],
               const byte* data,
               dword data_size,
               byte hmac[SHA1_DIGEST_SIZE]);
 
// Really big (about 1 second on a home PC)
static const unsigned int DERIVE_KEY_ROUNDS_NUMBER = 1000000;
 
/**
 *
 * Creates an encryption key (of AES_BLOCK_SIZE bytes) from the password and 
 * the challenges. Iterates DERIVE_KEY_ROUNDS_NUMBER times.
 *
 * This is the recommended PBKDF1 implementation.
 * See RFC 2898: http://www.faqs.org/rfcs/rfc2898.html
 *
 * In:
 *    password - a null terminated string representation of the user's password
 *    client_challenge - an array of random bytes generated by the user
 *    server_challenge - an array of random bytes generated by the server
 * Out:
 *    output_key - the newly-generated key
 * Returns:
 *    nothing
 **/ 
void DeriveKey(const char* password, 
               const byte client_challenge[CHALLENGE_SIZE], 
               const byte server_challenge[CHALLENGE_SIZE],
               byte output_key[AES_BLOCK_SIZE]);
 
#endif

Back to CryptoStuff implementation

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License