/* PSCHF - Pukall Stream Cipher Hash Function */
/* 256-bit HASH */

/* written in Borland Turbo C 2.0 on PC */
/* based on PC1 Cipher Algorithm ( Pukall Cipher 1 ) */
/* By Alexander PUKALL 1991 */
/* free code no restriction to use */

#include <stdio.h>
#include <string.h>
unsigned short ax,bx,cx,dx,si,tmp,x1a2,x1a0[8],res,i,inter,cfc,cfd,compte;
unsigned char cle[17];
short c;
FILE *in;

assemble()
{

x1a0[0]= ( cle[0]*256 )+ cle[1];
code();
inter=res;

x1a0[1]= x1a0[0] ^ ( (cle[2]*256) + cle[3] );
code();
inter=inter^res;

x1a0[2]= x1a0[1] ^ ( (cle[4]*256) + cle[5] );
code();
inter=inter^res;

x1a0[3]= x1a0[2] ^ ( (cle[6]*256) + cle[7] );
code();
inter=inter^res;

x1a0[4]= x1a0[3] ^ ( (cle[8]*256) + cle[9] );
code();
inter=inter^res;

x1a0[5]= x1a0[4] ^ ( (cle[10]*256) + cle[11] );
code();
inter=inter^res;

x1a0[6]= x1a0[5] ^ ( (cle[12]*256) + cle[13] );
code();
inter=inter^res;

x1a0[7]= x1a0[6] ^ ( (cle[14]*256) + cle[15] );
code();
inter=inter^res;

i=0;
}

code()
{
dx=x1a2+i;
ax=x1a0[i];
cx=0x015a;
bx=0x4e35;

tmp=ax;
ax=si;
si=tmp;

tmp=ax;
ax=dx;
dx=tmp;

if (ax!=0)
{
ax=ax*bx;
}

tmp=ax;
ax=cx;
cx=tmp;

if (ax!=0)
{
ax=ax*si;
cx=ax+cx;
}

tmp=ax;
ax=si;
si=tmp;
ax=ax*bx;
dx=cx+dx;

ax=ax+1;

x1a2=dx;
x1a0[i]=ax;

res=ax^dx;
i=i+1;
}
main()
{

unsigned int x,ix,z,fin;
unsigned char tab[32]; /* HASH */

x=32; /* Size of the HASH */
si=0;
x1a2=0;
i=0;


/* ('Remsaalps!123456') is a fixed key for the HASH function */

strcpy(cle,"Remsaalps!123456");

/* IN.BIN is the source file to HASH*/

if ((in=fopen("in.bin","rb")) == NULL) {printf("\nError reading file IN.BIN !\n");exit(0);}

ix=0;

for (z=0;z<=x;z++)
{
tab [z]=0;
}

while ( (c=fgetc(in)) != EOF) /* c contains the byte read in the file */
{
assemble();
cfc=inter>>8;
cfd=inter&255; /* cfc^cfd = random byte */

for (compte=0;compte<=15;compte++)
{
cle[compte]=cle[compte]^c;
}

c = c ^ (cfc^cfd);

tab [ix] = tab [ix] ^ c;

ix = ix + 1;
if ( ix >= x ) ix = 0;

}
fclose (in);

fin = (x+1)*32;

for (z=1;z<=fin;z++)
{

c = tab [ix];

assemble();
cfc=inter>>8;
cfd=inter&255; /* cfc^cfd = random byte */

for (compte=0;compte<=15;compte++)
{
cle[compte]=cle[compte]^c;
}

c = c ^ (cfc^cfd);

tab [ix] = tab [ix] ^ c;

ix = ix + 1;
if ( ix >= x ) ix = 0;

}

printf("HASH : ");

for (z=0;z<x;z++)
{
 printf("%X ",tab [z]); /* tab [0..31] contains the 256-bit HASH of the file */
}

 printf("\n");

}
