/* idea.h */
#ifndef _IDEA_DOT_H
#define _IDEA_DOT_H
#include <stdio.h>
#include <time.h>
#include <process.h>
#include <io.h>
#include <string.h>
#include <conio.h>
#define IDEAKEYSIZE 16
#define IDEABLOCKSIZE 8
#define word16 unsigned int
#define word32 unsigned long int
#define ROUNDS 8
#define KEYLEN (6*ROUNDS+4)
#define tempfilename "tempfile.鋘c"
int end_of_file,noisy,overwrite;
/*global vars*/
#define low16(x) ((x) &
0xffff)
typedef unsigned int uint16;
typedef word16 IDEAkey[KEYLEN];
/*IDEA Algorithm functions */
void en_key_idea(word16 userkey[8],IDEAkey Z);
void de_key_idea(IDEAkey Z, IDEAkey DK);
void cipher_idea(word16 in[4],word16 out[4],IDEAkey Z);
uint16 inv(uint16 x);
uint16 mul(uint16 a,uint16 b);
/*file handling functions*/
char read_char_from_file(FILE *fp);
word16 read_word16_from_file(FILE *fp);
void write_char_to_file(char data,FILE *fp);
void write_word16_to_file(word16 data,FILE *fp);
void cipher_file(FILE *in,FILE *out,word16 *key);
void decipher_file(FILE *in,FILE *out,word16 *key);
void swap_files_and_clean_up(char *file);
#endif
/*IDEA.C v2.2
c source code for IDEA block cipher. IDEA (International Data
Encryption Algorithm), formerly known as IPES (Improved Proposed
Encryption Standard). Algorithm developed by Xuejia Lai and James L.
Massey, of ETH Zurich. This implementation modified and derived from
original C code developed by Xuejia Lai. Zero-based indexing added,
names changed from IPES to IDEA. CFB functions added. Random Number
routines added. Optimized for speed 21 Oct 92 by Colin Plumb
<colin@nsq.gts.org> This code assumes that each pair of 8-bit bytes
comprising a 16-bit word in the key and in the cipher block are
externally represented with the Most Significant Byte (MSB) first,
regardless of internal native byte order of the target cpu.
modified for use with PC files by Colin Maroney 4/1/94*/
/* USAGE: pass a key made up of 8 16-bit numbers (word16) in an array
("word16 key[8];"), an input FILE * and an output temporary
FILE * to either encode_file() or decode_file().
where the key comes from is up to you.
then
call swap_files_and_clean_up() with the original file's
name as the argument, to replace the original file
with the encoded data (stored in the temporary file).
you can remname the tempfile to be used in idea.h
noisy is an integer which tells encrypting/decrypting
functions to echo a "." every 256 writes, so the user can
see that something is happening. set it to 0 for quiet
running.
please note that for really good security the original file
is overwritten before being erased if you use the w switch.
otherwise it outputs a file "<filename>.enc"
the main() used here as illustration reads the filename
from the command line arguments, as well as a command
"e" or "d" to tell it whether to encrypt or
decrypt, and a key. the older versions had an interface
for when a command line was not use. lack of editing
features made this buggy, so i axed it. */
#include "idea.h"
static uint16 inv(uint16 x)
{
uint16 t0,t1;
uint16 q,y;
if (x<=1)
return x;
t1=(uint16)(0x10001l/x);
y=(uint16)(0x10001l%x);
if (y==1)
return low16(1-t1);
t0=1;
do
{
q=x/y;
x=x%y;
t0+=q*t1;
if (x==1)
return t0;
q=y/x;
y=y%x;
t1+=q*t0;
} while (y!=1);
return low16(1-t1);
}
static void en_key_idea(word16 *userkey, word16 *Z)
{
int i,j;
/* shifts */
for (j=0;j<8;j++)
Z[j]=*userkey++;
for (i=0;j<KEYLEN;j++)
{
i++;
Z[i+7]=((Z[i&7] << 9) | (Z[i+1 &
7] >> 7));
Z+=i&8;
i&=7;
}
}
static void de_key_idea(IDEAkey Z,IDEAkey DK)
{
int j;
uint16 t1,t2,t3;
IDEAkey T;
word16 *p=T+KEYLEN;
t1=inv(*Z++);
t2=-*Z++;
t3=-*Z++;
*--p=inv(*Z++);
*--p=t3;
*--p=t2;
*--p=t1;
for (j=1;j<ROUNDS;j++)
{
t1=*Z++;
*--p=*Z++;
*--p=t1;
t1=inv(*Z++);
t2=-*Z++;
t3=-*Z++;
*--p=inv(*Z++);
*--p=t2;
*--p=t3;
*--p=t1;
}
t1=*Z++;
*--p=*Z++;
*--p=t1;
t1=inv(*Z++);
t2=-*Z++;
t3=-*Z++;
*--p=inv(*Z++);
*--p=t3;
*--p=t2;
*--p=t1;
/*copy and destroy temp copy*/
for(j=0,p=T;j<KEYLEN;j++)
{
*DK++=*p;
*p++=0;
}
}
uint16 mul(uint16 a, uint16 b)
{
word32 p;
if (a)
{
if (b)
{
p=(word32)a*b;
b=(uint16)(low16(p));
a=(uint16)(p>>16);
return b-a+(b<a);
}
else
{
return 1-a;
}
}
else
return 1-b;
}
#define MUL(x,y) (x=mul(low16(x),y))
#define CONST
static void cipher_idea(word16 in[4],word16 out[4],register CONST IDEAkey Z)
{
register uint16 x1,x2,x3,x4,t1,t2;
int r=ROUNDS;
x1=*in++;
x2=*in++;
x3=*in++;
x4=*in;
do
{
MUL(x1,*Z++);
x2+=*Z++;
x3+=*Z++;
MUL(x4,*Z++);
t2=x1^x3;
MUL(t2,*Z++);
t1=t2+(x2^x4);
MUL(t1,*Z++);
t2=t1+t2;
x1^=t1;
x4^=t2;
t2^=x2;
x2=x3^t1;
x3=t2;
} while (--r);
MUL(x1,*Z++);
*out++=x1;
*out++=(x3+*Z++);
*out++=(x2+*Z++);
MUL(x4,*Z);
*out=x4;
}
char read_char_from_file(FILE *fp)
{
char temp=0;
if ((fread(&temp,sizeof(char),1,fp))!=1)
end_of_file=1;
return (temp);
}
word16 read_word16_from_file(FILE *fp)
{
word16 temp=0;
if ((fread(&temp,sizeof(word16),1,fp))!=1)
end_of_file=1;
return temp;
}
void write_char_to_file(char data,FILE *fp)
{
if ((fwrite(&data,sizeof(char),1,fp))!=1)
{
printf("Fatal Error writing output file!!!/n");
exit(-1);
}
}
void write_word16_to_file(word16 data,FILE *fp)
{
if ((fwrite(&data,sizeof(word16),1,fp))!=1)
{
printf("Fatal Error writing output file!!!/n");
exit(-1);
}
}
void cipher_file(FILE *in,FILE *out,word16 *key)
{
word16 input[4],output[4];
IDEAkey Z;
int x,y;
int count=0;
long length;
int temp;
en_key_idea(key,Z);
end_of_file=0;
length=filelength(fileno(in));
fwrite(&length,sizeof(long),1,out);
while (!end_of_file)
{
x=0;
while (x<4)
{
input[x]=((word16)(read_char_from_file(in)<<8));
if (!end_of_file)
{
temp=read_char_from_file(in);
if (temp<0) temp+=256;
input[x]=input[x]|temp;
x++;
}
if (end_of_file)
{
while (x<4) input[x++]=0;
break;
}
}
cipher_idea(input,output,Z);
for (y=0;y<x;y++)
{
if (noisy) if (count++%256==0) printf(".");
write_word16_to_file(output[y],out);
}
}
}
void decipher_file(FILE *in,FILE *out,word16 *key)
{
word16 input[4],output[4];
int x,y;
IDEAkey Z,DK;
int count=0;
long length=0;
en_key_idea(key,Z);
de_key_idea(Z,DK);
end_of_file=0;
fread(&length,sizeof(long),1,in);
while (!end_of_file)
{
x=0;
while (x<4)
{
input[x]=read_word16_from_file(in);
if (end_of_file)
break;
x++;
}
cipher_idea(input,output,DK);
for (y=0;y<x;y++)
{
if (noisy) if (count++%256==0) printf(".");
if (length-->0)
write_char_to_file(((char)(output[y]>>8)),out);
if (length-->0)
write_char_to_file(((char)(output[y]&255)),out);
}
}
}
void swap_files_and_clean_up(char *file)
{
long fsize,count;
FILE *fp;
char temp[100];
if (overwrite)
{
if ((fp=fopen(file,"r+b"))==NULL)
{
printf("/nError overwriting old file, security compromised./n");
}
else
{
fseek(fp,0l,SEEK_END);
fsize=ftell(fp);
fseek(fp,0l,SEEK_SET);
for (count=0;count<fsize;count++)
fputc('0',fp);
fclose(fp);
}
if ((remove(file))!=0)
{
printf("/nERROR removing old file <%s>/n",file);
printf("encoded data remains in temporary file <%s>/n",tempfilename);
exit(-1);
}
}
else
{
strcpy(temp,file);
file=strtok(temp,".");
strcat(file,".enc");
}
if ((rename(tempfilename,file))!=0)
{
printf("/nERROR renaming temporary file <%s>!!/n",tempfilename);
printf("Data is safely processed and stored in that file./n");
exit(-1);
}
}
/*-----------------------------------------------*/
#define KBYTES 1024
void getuserkeyfromargv(word16 *key,char *arg)
{
int x;
for (x=0;x<strlen(arg) &&
x<8;x++)
{
if (x==0) key[x]=arg[x]<<8;
else
key[x]=((arg[x]<<8)|(key[x-1]>>8));
}
if (strlen(arg)>8) printf ("/nONLY first *8* characters of key used!!!/n");
if (x<8) while (x<8) key[x++]=0;
}
main(int argc, char **argv)
{
word16 userkey[8];
char filename[100];
FILE *fp,*temp;
int to_or_from;
noisy=1;
overwrite=0;
if (argc!=4)
{
printf("/nUsage: idea filename.ext [e|d[w]] key/n");
printf(" e=encode d=decode w=overwrite file/n");
printf(" NOTE: Key must be no longer than 8 characters long!!!/n");
exit(-1);
}
else
{
strncpy(filename,argv[1],99);
filename[99]='/0';
if (argv[2][0]=='e') to_or_from=1;
else
if (argv[2][0]=='d') to_or_from=0;
else
{
printf("/nUsage: idea filename.ext [e|d[w]] key/n");
printf(" e=encrypt d=decrypt w=overwrite file/n");
printf(" NOTE: Key must be no longer than 8 characters long!!!/n");
exit(-1);
}
if (argv[2][1]=='w') overwrite=1;
getuserkeyfromargv(userkey,argv[3]);
}
if ((fp=fopen(filename,"r+b"))==NULL)
{
printf("/nError opening File %s/n",filename);
exit (-1);
}
if ((temp=fopen(tempfilename,"w+b"))==NULL)
{
printf("/nError opening temporary file/n");
exit(-1);
}
if (to_or_from==1)
{
printf("/nEncoding file %s ",filename);
cipher_file(fp,temp,userkey);
}
else
{
printf("/nDecoding file %s ",filename);
decipher_file(fp,temp,userkey);
}
fclose (fp);
fclose(temp);
swap_files_and_clean_up(filename);
return 0;
}
IDEA v2.2
IDEA encryption fordo
s.
IDEA stands for International Data Encryption Algorithm
it was invented by Xuejia Lai and James Massey in Switzerland
its a private key block algorithm, and is thought to be
very secure.
This manifestation of the algorithm is adapted pretty much wholesale from
Dr.do
bbs Journal #208 December 1993. I simplified it, and made it
useable ondo
s files.
the algorithm operates on 64-bit data blocks, divided into 4 16-bit
subblocks. fordo
s files, it packs two characters into a 16-bit word
and treats 4 such words as the subblocks. since not all files have the right
length for this, a header is used to tell idea's decrypter how long the file
will be. thus encrypted files are a few bytes longer than they started. they
are of course put back to normal when decrypted.
the key is a 128-bits. This program uses a simplified key, in that it takes
up to 8 characters and casts each one into a 16-bit word, by shifting it left
8 bits, and OR'ing it with the previous character (0 for the first character),
making 8 16-bit subblocks of the key, which is no where near as complex a key
is possible. this undoubtedly affects the security of the algorithm, but it
should still be good for most purposes. A future version will have an option
for a more complex key. of course, source is included so feel free to write
a better keying function yourself.
the .exe file i include here is a simple demonstration program. Source code
is included and the program is written as a sort of "toolbox"---you can
use the algorithm through the 3 functions provided as a sort of "front-end":
encode, decode, &
clean-up. actually, you can easily change the way it works
too if you like--the algorithm is a bit obtuse but the usage is real easy.
usage is "idea <filename.ext> [e|d[w]] key"
[e|d[w]] stands for either an "e" or a "d", instructing whether to
e-ncode or d-ecode, plus an optional "w", which tells
IDEA to overwrite the original file with the encrypted
data. leaving "w" off creates a new file called
"filename.enc" where "filename" is the same as the input file.
overwriting is more secure--it destroys old data--but may
not be what you want.
key is a word up to 8 characters BUT NOT MORE!!! extra characters
will be truncated offa there.
its not my code sodo
n't send money or anything. (the IDEA algorithm is in
fact patented, but it can be freely used and distributed for non-commercial
use. The patent is held by Ascom-Tech AG in switzerland, tel: +41 65 242-885)
if you want to contact me, i'm on the internet as "shaggy@phantom.com".
Please note that use of this program isdo
ne with no insurance from me that
it will work or anything----use it at your own risk. i've bug checked it
and everything and it looks good, but i'm not gonna be responsible for
failure. While we're on this topic, pleasedo
not forget your key!!!
a brute-force attack on this algorithm "requires 2^128 encryptions to
recover the key.....a billion chips testing a billion keys a second would
take 10^13 years to break IDEA"*----a very secure algorithm (at least against
brute force attacks).
* Dr.do
bbs Journal #208 p.54