Saphe Implementation - CryptoStuff.cpp
/**
 * 
 * Copyright (C) 2007-2008
 * Uri Sternfeld (saphesolution@yahoo.com)
 * All Rights Reserved
 *
 * Written by Uri Sternfeld
 * Last modified: 3/1/2008
 *
 **/
 
#include <string.h>
#include "CryptoStuff.h"
 
void AESCryptExpandKey(byte basicKey[AES_BLOCK_SIZE], AESExpandedKey& expandedKey) {
    aes_set_key(&(expandedKey.ctx), (uint8*)basicKey, AES_BLOCK_SIZE*8);
}
 
void AESCFBEncrypt(const AESExpandedKey& expandedKey, 
        byte* buffer, 
        dword bufferSize, 
        const byte IV[AES_BLOCK_SIZE]) 
{    
    AESExpandedKey keyCopy(expandedKey);
 
    byte prevBlock[AES_BLOCK_SIZE];
    byte curKey[AES_BLOCK_SIZE];
    memcpy(prevBlock, IV, AES_BLOCK_SIZE);
 
    for (dword i = 0 ; i < bufferSize ; i+= AES_BLOCK_SIZE) {
        dword curBlockSize = AES_BLOCK_SIZE;
        if ((bufferSize - i) < AES_BLOCK_SIZE) {
            curBlockSize = bufferSize - i;
        }
        // Encrypt the previous block
        aes_encrypt(&(keyCopy.ctx), (uint8*)prevBlock, (uint8*)curKey);
        // XOR the current plain with the current key block
        for (dword j = 0 ; j < curBlockSize ; ++j) {
            buffer[i+j] ^= curKey[j];
        }
        // Copy the new cipher as the previous block
        memcpy(prevBlock, buffer+i, curBlockSize);
    }
}
 
void AESCFBDecrypt(const AESExpandedKey& expandedKey, 
        byte* buffer, 
        dword bufferSize, 
        const byte IV[AES_BLOCK_SIZE]) 
{
 
    AESExpandedKey keyCopy(expandedKey);
 
    byte prevBlock[AES_BLOCK_SIZE];
    byte curKey[AES_BLOCK_SIZE];
    memcpy(prevBlock, IV, AES_BLOCK_SIZE);
 
    for (dword i = 0 ; i < bufferSize ; i+= AES_BLOCK_SIZE) {
        dword curBlockSize = AES_BLOCK_SIZE;
        if ((bufferSize - i) < AES_BLOCK_SIZE) {
            curBlockSize = bufferSize - i;
        }
        // Encrypt the previous block
        aes_encrypt(&(keyCopy.ctx), (uint8*)prevBlock, (uint8*)curKey);
        // Copy the current cipher as the previous block
        memcpy(prevBlock, buffer+i, curBlockSize);
        // XOR the current cipher with the current key block
        for (dword j = 0 ; j < curBlockSize ; ++j) {
            buffer[i+j] ^= curKey[j];
        }        
    }
}
 
// Used to convert the digest to bytes
void dword2bytes_be(dword dw, byte b[sizeof(dword)]) {
    for (dword i = 0 ; i < sizeof(dword) ; ++i) {
        b[i] = (byte)(dw>>((sizeof(dword) - 1 - i)*8));
    }
}
 
// Hash a given block of any size
void SHA1(const byte* data, dword dataSize, byte digest[SHA1_DIGEST_SIZE]) {
    SHA1Context ctx;
 
    SHA1Reset(&ctx);
    SHA1Input(&ctx, data, dataSize);
    SHA1Result(&ctx);
 
    for (dword i = 0 ; i < (SHA1_DIGEST_SIZE/sizeof(dword)) ; ++i) {
        dword2bytes_be(ctx.Message_Digest[i], digest + (i*sizeof(dword)));        
    }
}
 
// Implements the FIPS standard
void SHA1_HMAC(const byte key[AES_BLOCK_SIZE],
               const byte* data,
               dword data_size,
               byte hmac[SHA1_DIGEST_SIZE])
{
    byte opad[SHA1_BLOCK_SIZE+SHA1_DIGEST_SIZE];
    byte* ipad = new byte[SHA1_BLOCK_SIZE+data_size];
 
    for (int i = 0 ; i < SHA1_BLOCK_SIZE ; ++i) {
        opad[i] = 0x5C;
        ipad[i] = 0x36;
        if (i < AES_BLOCK_SIZE) {
            opad[i] ^= key[i];
            ipad[i] ^= key[i];            
        }        
    }
 
    memcpy(ipad + SHA1_BLOCK_SIZE, data, data_size);
 
    SHA1(ipad, SHA1_BLOCK_SIZE+data_size, opad+SHA1_BLOCK_SIZE);
 
    delete [] ipad;
 
    SHA1(opad, SHA1_BLOCK_SIZE+SHA1_DIGEST_SIZE, hmac);    
}
 
void DeriveKey(const char* password, 
               const byte client_challenge[CHALLENGE_SIZE], 
               const byte server_challenge[CHALLENGE_SIZE],
               byte output_key[AES_BLOCK_SIZE])
{
    int password_len = strlen(password);
    byte* base = new byte[password_len+(CHALLENGE_SIZE*2)];
 
    // Create the base data (fill the digest space with zeroes)    
    memcpy(base, (const byte*)password, password_len);
    memcpy(base+password_len, client_challenge, CHALLENGE_SIZE);
    memcpy(base+password_len+CHALLENGE_SIZE, server_challenge, CHALLENGE_SIZE);
 
    byte tmp1[SHA1_DIGEST_SIZE];
    byte tmp2[SHA1_DIGEST_SIZE];
    // Calculate SHA-1 over the basic block
    SHA1(base, password_len+(CHALLENGE_SIZE*2), tmp1);
 
    delete [] base;
 
    // Now lets grind that CPU!
    for (unsigned int i = 0 ; i < DERIVE_KEY_ROUNDS_NUMBER ; ++i) {
        // Copy the previous digest
        memcpy(tmp2, tmp1, SHA1_DIGEST_SIZE);
        SHA1(tmp2, SHA1_DIGEST_SIZE, tmp1);
    }    
 
    memcpy(output_key, tmp1, AES_BLOCK_SIZE);
}

Back to CryptoStuff implementation

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