aes.cxx

来自「MiniSip Client with DomainKeys Authentic」· CXX 代码 · 共 279 行

CXX
279
字号
/*  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien    This library is free software; you can redistribute it and/or  modify it under the terms of the GNU Lesser General Public  License as published by the Free Software Foundation; either  version 2.1 of the License, or (at your option) any later version.  This library is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public  License along with this library; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* * Authors: Erik Eliasson <eliasson@it.kth.se> *          Johan Bilien <jobi@via.ecp.fr>*/#include<config.h>#ifdef HAVE_OPENSSL_AES_H#include <openssl/aes.h>#else# define AES_BLOCK_SIZE 16typedef struct AES_KEY_s AES_KEY;#include <libmcrypto/rijndael-alg-fst.h>#endif#include <libmcrypto/aes.h>//debug:#ifdef DEBUG_OUTPUT#include<iostream>#include<libmutil/print_hex.h>using namespace std;#endif#include<string.h>#ifndef HAVE_OPENSSL_AES_H// Redefinition of this AES type to use Paulo Barreto // <paulo.barreto@terra.com.br> implementation instead, // to avoid the requirement for libssl 0.9.7#define NB_ROUND 10 /* 128 bits keys */struct AES_KEY_s{	unsigned int key[4*(NB_ROUND+1)];};// openssl AES functions using Paulo Barreto <paulo.barreto@terra.com.br>// implementation, to avoid the requirement for version 0.9.7 of libsslstatic void AES_set_encrypt_key( unsigned char * key, int key_nb_bits, AES_KEY * aes_key ){	rijndaelKeySetupEnc( aes_key->key, key, key_nb_bits );}static void AES_encrypt( const unsigned char * input, unsigned char * output, AES_KEY * aes_key ){	rijndaelEncrypt( aes_key->key, NB_ROUND, input, output );}#endifAES::AES():key(NULL){}AES::AES( unsigned char * key, int key_length ){	this->key = (AES_KEY *) malloc( sizeof( AES_KEY ) );	memset( this->key, '\0', sizeof( AES_KEY ) );;	AES_set_encrypt_key( key, key_length*8, (AES_KEY *) this->key );}AES::~AES(){	if( key )		free( key );}void AES::encrypt( const unsigned char * input, unsigned char * output ){	AES_encrypt( input, output, (AES_KEY *) key );}void AES::get_ctr_cipher_stream( unsigned char * output, unsigned int length,				unsigned char * iv ){	unsigned long ctr; // Should be 128 bits, but we	                     // assume that we 32 bits is enough ...	unsigned char * aes_input, * temp;	uint32_t input;		aes_input = (unsigned char *)malloc( AES_BLOCK_SIZE );	temp = (unsigned char *)malloc( AES_BLOCK_SIZE );	memcpy( aes_input, iv, 12 );	iv += 12;	for( ctr = 0; ctr < length/AES_BLOCK_SIZE; ctr++ ){		input = ctr + U32_AT(iv);		//compute the cipher stream		aes_input[12] = (byte_t)((input & 0xFF000000) >> 24);		aes_input[13] = (byte_t)((input & 0x00FF0000) >> 16);		aes_input[14] = (byte_t)((input & 0x0000FF00) >>  8);		aes_input[15] = (byte_t)((input & 0x000000FF));		AES_encrypt( aes_input, &output[ctr*AES_BLOCK_SIZE], (AES_KEY *) key );	}	// Treat the last bytes:	input = ctr + U32_AT(iv);	aes_input[12] = (byte_t)((input & 0xFF000000) >> 24);	aes_input[13] = (byte_t)((input & 0x00FF0000) >> 16);	aes_input[14] = (byte_t)((input & 0x0000FF00) >>  8);	aes_input[15] = (byte_t)((input & 0x000000FF));		AES_encrypt( aes_input, temp, (AES_KEY *) key );	memcpy( &output[ctr*AES_BLOCK_SIZE], temp, length % AES_BLOCK_SIZE );	free( temp );	free( aes_input );}	void AES::ctr_encrypt( const unsigned char * input, unsigned int input_length,		 unsigned char * output, unsigned char * iv ){//	unsigned char cipher_stream[input_length];	unsigned char *cipher_stream = new unsigned char[input_length];		get_ctr_cipher_stream( cipher_stream, input_length, iv );	for( unsigned int i = 0; i < input_length; i++ ){		output[i] = cipher_stream[i] ^ input[i];	}	delete []cipher_stream;}void AES::ctr_encrypt( unsigned char * data, unsigned int data_length,		       unsigned char * iv ){	//unsigned char cipher_stream[data_length];	unsigned char *cipher_stream = new unsigned char[data_length];	get_ctr_cipher_stream( cipher_stream, data_length, iv );	for( unsigned int i = 0; i < data_length; i++ ){		data[i] ^= cipher_stream[i];	}	delete[] cipher_stream;}void AES::f8_encrypt(unsigned char *data, unsigned int data_length,		     unsigned char *iv, unsigned char *origKey, unsigned int keyLen,		     unsigned char *salt, unsigned int saltLen ){        f8_encrypt(data, data_length, data, iv, origKey, keyLen, salt, saltLen);}void AES::f8_encrypt(unsigned char *in, unsigned int in_length, unsigned char *out,		     unsigned char *iv, unsigned char *origKey, unsigned int keyLen,		     unsigned char *salt, unsigned int saltLen ){    unsigned char *saltMask;    unsigned char *maskedKey;    unsigned char *cp_in, *cp_in1, *cp_out;    unsigned int i;    int offset = 0;    F8_CIPHER_CTX f8ctx;       /*     * Get memory for the derived IV (IV')     */    f8ctx.ivAccent = (unsigned char *)malloc(AES_BLOCK_SIZE);        /*     * Get memory for the special key. This is the key to compute the     * derived IV (IV').     */    saltMask = (unsigned char *)malloc(keyLen);    maskedKey = (unsigned char *)malloc(keyLen);    /*     * First copy the salt into the mask field, then fill with 0x55 to     * get a full key.     */    memcpy(saltMask, salt, saltLen);    memset(saltMask+saltLen, 0x55, keyLen-saltLen);        /*     * XOR the original key with the above created mask to     * get the special key.     */    cp_out = maskedKey;    cp_in = origKey;    cp_in1 = saltMask;        for (i = 0; i < keyLen; i++) {        *cp_out++ = *cp_in++ ^ *cp_in1++;    }        /*     * Prepare the a new AES cipher with the special key to compute IV'     */    AES *aes = new AES(maskedKey, keyLen);        /*     * Use the masked key to encrypt the original IV to produce IV'.      *      * After computing the IV' we don't need this cipher context anymore, free it.     */    aes->encrypt(iv, f8ctx.ivAccent);    delete aes;    memset(maskedKey, 0, keyLen);    free(saltMask);    free(maskedKey);                   // both values are no longer needed    f8ctx.J = 0;                       // initialize the counter    f8ctx.S = (unsigned char *)malloc(AES_BLOCK_SIZE);  // get the key stream buffer    memset(f8ctx.S, 0, AES_BLOCK_SIZE); // initial value for key stream     while (in_length >= AES_BLOCK_SIZE) {        processBlock(&f8ctx, in+offset, AES_BLOCK_SIZE, out+offset);        in_length -= AES_BLOCK_SIZE;        offset += AES_BLOCK_SIZE;    }    if (in_length > 0) {        processBlock(&f8ctx, in+offset, in_length, out+offset);    }    memset(f8ctx.ivAccent, 0, AES_BLOCK_SIZE);    memset(f8ctx.S, 0, AES_BLOCK_SIZE);    free(f8ctx.ivAccent);    free(f8ctx.S);}int AES::processBlock(F8_CIPHER_CTX *f8ctx, unsigned char *in, int length, unsigned char *out) {    int i;    unsigned char *cp_in, *cp_in1, *cp_out;    uint32_t *ui32p;    /*     * XOR the previous key stream with IV'     * ( S(-1) xor IV' )     */    cp_in = f8ctx->ivAccent;    cp_out = f8ctx->S;    for (i = 0; i < AES_BLOCK_SIZE; i++) {        *cp_out++ ^= *cp_in++;    }    /*     * Now XOR (S(n-1) xor IV') with the current counter, then increment the counter     */    ui32p = (uint32_t *)f8ctx->S;    ui32p[3] ^= hton32(f8ctx->J);    f8ctx->J++;    /*     * Now compute the new key stream using AES encrypt     */    AES_encrypt(f8ctx->S, f8ctx->S, (AES_KEY *) key);    /*     * as the last step XOR the plain text with the key stream to produce      * the ciphertext.     */    cp_out = out;    cp_in = in;    cp_in1 = f8ctx->S;    for (i = 0; i < length; i++) {        *cp_out++ = *cp_in++ ^ *cp_in1++;    }    return length;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?