El
algoritmo SHA-1(una función resumen más) se utiliza como firma digital, NO es
un algoritmo criptográfico, sino, como complemento de uno, como detección de
código auténtico, etc.
Dado un
parámetro como entrada 2 veces consecutivas, devuelve el mismo resultado.
Esta
implementado en una clase, para la plataforma Win32.
/*
* "$id: sha1.h,v 1.6 01/01/2007
$"
*
* Abstract:
* Definitions/Declarations
for class Csha.
* Implementación
del Algoritmo SHA-1.
* Función
Resumen para detectar autenticidad de
*
código dentro de un algoritmo criptográfico.
*
* Write By:
* Daniel Tomás Borelli
* daltomi@gmail.com
*
* Revision History:
* "$log:sha1.h,v 1.5
01/01/2007 $"
* Initial
Revision.
* Se
eliminó la inclusión del arch. 'stdafx.h'.
*
* Copyright (C) 2007 Daniel Tomás
Borelli
*/
#ifndef
__SHA_H__
#define
__SHA_H__
#include
"stdlib.h"
#include
"stdio.h"
#include
"string.h"
#define
ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define F( x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G( x, y, z) ((x) ^ (y) ^ (z))
#define H( x, y, z) (((x) & (y)) | ((x) & (z)) |
((y) & (z)))
typedef
unsigned char* POINTER;
typedef
unsigned __int8 UI8;
typedef
unsigned __int16 UI16;
typedef
unsigned __int32 UI32;
static const
UI32 register_state[] =
{0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0};
static const
UI32 register_key[] =
{0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
static UCHAR
register_block[64] = {80, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0};
typedef
struct {
unsigned char buffer_block[64];
UI32 count[2];
UI32 abcde[5];
}SHA_CTX;
/*
* 'Csha'
- Definición de la clase.
*/
class Csha{
public:
void sha1(void*,unsigned
int, unsigned char*);
private:
void update(SHA_CTX*,unsigned
char*, unsigned int);
void init(SHA_CTX*);
void finish(SHA_CTX*);
void ejecute(SHA_CTX*,
unsigned char*);
void encode(unsigned
char*, UI32*, unsigned int);
UI32 iterator(unsigned,unsigned,unsigned,unsigned
int);
};
/*
* 'update'
- Actualiza el bloque de texto.
*
Alinea [buffer] a 512 bits, ejecuta el algoritmo SHA-1
* y lo asigna
[context->buffer_block].
*/
void
Csha::update(SHA_CTX* context, unsigned char* buffer, unsigned int lenbuffer)
{
unsigned int i,index,partLen;
index = (unsigned
int)((context->count[0] >> 3)&0x3F);
if ((context->count[0] +=
((UI32)lenbuffer << 3))< ((UI32)lenbuffer << 3))
{
context->count[1]++;
}
context->count[1] +=
((UI32)lenbuffer >> 29);
partLen = 64 - index;
if (lenbuffer >= partLen)
{
memcpy((POINTER)&context->buffer_block[index],
(POINTER)buffer, partLen);
ejecute(context,context->buffer_block);
for
(i = partLen; i + 63 < lenbuffer; i += 64)
{
ejecute(context,&buffer[i]
);
}
index
= 0;
}else
{
i
= 0;
}
memcpy
((POINTER)&context->buffer_block[index], (POINTER)&buffer[i],
lenbuffer-i);//buffer de 0 a
7 con input
}
/*
* 'finish' - Finaliza
[context->buffer_block].
*/
void
Csha::finish(SHA_CTX* context)
{
unsigned char bits[8];
unsigned int index, padLen;
encode (bits, context->count, 8);
index = (unsigned
int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 -
index) : (120 - index);
update(context,register_block,
padLen);
update(context, bits,
8);
}
/*
* 'encode'
- Asigna [len] bytes en 4 bytes.
*
Se utiliza la notación BIG ENDIAN para
* el algoritmo SHA-1.
*/
void
Csha::encode(unsigned char *output, UI32 *input, unsigned int len)
{
unsigned int i, j;
for (i = 1, j = 0; j < len; i--,
j += 4) {
output[j+3] = (unsigned char)(((input[i])) &
0xff);
output[j+2]
= (unsigned char)(((input[i]) >>
8) & 0xff);
output[j+1]
= (unsigned char)(((input[i]) >> 16) & 0xff);
output[j] = (unsigned char)(((input[i])
>> 24) & 0xff);
}
}
/*
* 'iterator'
- Itera las llamadas a funciones
* según parámetro [t].
*/
UI32
Csha::iterator(unsigned x,unsigned y,unsigned z,unsigned int t)
{
if((t>=0) && (t<=19))
{
return((UI32)F(x,y,z));
}else if( (t>= 20) &&
(t<=39) || (t>=60) && (t <=79))
{
return((UI32)G(x,y,z));
}else if( (t>=40) &&
(t<=59))
{
return((UI32)H(x,y,z));
}
return
0L;
}
/*
* 'init'
- Inicia el contexto.
*/
void
Csha::init(SHA_CTX* context)
{
for(int i = 0;i<=4;i++)
{
context->abcde[i] =
register_state[i];
}
context->count[0] =
context->count[1] = (UI32)0x0;
}
/*
* 'ejecute'
- Ejecuta el bloque de texto alineado.
* En
ésta función se resaltan 3 bloques: A,B,C.
* A
y B son preparativos; C es el proceso principal.
*/
void
Csha::ejecute(SHA_CTX* context, unsigned char* input)
{
unsigned k = 0,j = 0,i = 0,t = 0;
UI32 a,b,c,d,e;
UI32
temp = 0;
UI32
block16[16];
UI32
block80[80];
//se
asignan los contenidos anteriores.
a = context->abcde[0];
b = context->abcde[1];
c = context->abcde[2];
d = context->abcde[3];
e =
context->abcde[4];
// BLOQUE A:
//para
el algoritmo SHA-1 se debe utilizar la notación BIG ENDIAN.
//procesa un bloque de 64 y lo convierte en un bloque
de 16.
for
(k = 0, j = 0; j < 63; k++, j += 4)
{
block16[k]
= (((UI32)input[j])<<24) | (((UI32)input[j+1]) << 16) |
(((UI32)input[j+2]) << 8) | ((UI32)input[j+3]);
}
//BLOQUE
B:
//procesa
un bloque de 16 y lo convierte en un bloque de 80.
//los
primeros 16 se copian tal cual.
//desde
17 a 80
los copia con desplazamiento de bits a la izquierda con retroalimentación.
for(i= 0; i<= 79;i++)
{
if( (i>=0) &&
(i<=15))
{
block80[i] =
block16[i];
}else if( (i>=16)
&& (i<=79))
{
block80[i] =
ROTATE_LEFT(((block80[i-3]) ^ (block80[i-8]) ^ (block80[i-14]) ^
(block80[i-16])),(1));
}
}
//por
seguridad se limpia el contenido.
memset((POINTER)block16,0,sizeof(block16));
//BLOQUE C:
//proceso
principal del algoritmo SHA-1.
for(t; t<=79;t++)
{
i = t / 20;
temp =
ROTATE_LEFT((a),(5)) + iterator(b,c,d,t) + e + block80[t] + register_key[i];
e = d;
d = c;
c =
ROTATE_LEFT((b),(30));
b = a;
a
= temp;
}
//se
asignan sumados los registros obtenidos del bloque C.
context->abcde[0] += a;
context->abcde[1] += b;
context->abcde[2] += c;
context->abcde[3] += d;
context->abcde[4]
+= e;
//por
seguridad se limpia el contenido.
memset(&block80,0,80);
}
/*
* 'sha1'
- Ejecuta el algoritmo SHA-1.
*/
void
Csha::sha1(void *buffer,unsigned int length,unsigned char* out)
{
SHA_CTX ctx;
init(&ctx);
update(&ctx,(unsigned
char*)buffer,length);
finish(&ctx);
memcpy((POINTER)out,&ctx.abcde[0],sizeof(ctx.abcde));
memset ((POINTER)&ctx, 0, sizeof
(ctx));
}
#endif //
_SHA1_H_
/*
* End for "$id: sha1.h,v 1.6
01/01/2007 $"
*/