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