FEAL暗号プログラム



[ 簡単な説明 ]

NTT開発のFEALアルゴリズムを用いたファイル暗号化/復号化プログラムです。
C++版のプログラム・ソースは、実行ファイルと共に、NIFTY-Serve に公開しました。
使用法の詳細は、後述のマニュアルと、使用例を参照して下さい。。


プログラム・ソース("feal.c")           top (トップに戻る)
/*		feal.c		FEAL(Fast Data Encipherment Algorithm) Program	*/
#include <stdio.h>

#define		ULONG		unsigned long
#define		UINT		unsigned int

#define		I4			16			/* 4 * sizeof(UINT) */
#define		I8			32			/* 8 * sizeof(UINT) */
#define		I16			64			/* 16 * sizeof(UINT) */

#define		NBUF		51200		/* 50kB */
#define		NBUF8		6400		/* = NBUF / 8 */
#define		NMAX		128			/* maximum value of N */

#define		S0(x)		*(rot0 + (0xff & (x)))
#define		S1(x)		*(rot1 + (0xff & (x)))

void (*ini_s)();
void (*rot_i)();
void (*xor)();

FILE *fp1, *fp2;
int f1, f2;

char buffer[NBUF], bufo[8], keybuf[32];

unsigned int mem, mem1, nbuf, nnbuf, count, lshift, rshift;

static int edflag = -1, exflag = 0, mode = 1;
static int blen = 8, blena = 0, llen = 64, nn = 8;

static char initial[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
char *initial4 = initial + 4;

static char x[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
char *xb1, *xb2;

static UINT ks[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };

UINT key[NMAX * 2 + 16];
UINT *key_nn;
UINT kn0, kn1, kn2, kn3, kn4, kn5, kn6, kn7;
UINT kn8, kn9, kn10, kn11, kn12, kn13, kn14, kn15;

static UINT rot0[257] = {
	  0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
	 64, 68, 72, 76, 80, 84, 88, 92, 96,100,104,108,112,116,120,124,
	128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,
	192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,
	  1,  5,  9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
	 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125,
	129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,
	193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,
	  2,  6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
	 66, 70, 74, 78, 82, 86, 90, 94, 98,102,106,110,114,118,122,126,
	130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,
	194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,
	  3,  7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
	 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127,
	131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,
	195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255, 0};

UINT *rot1 = rot0 + 1;

/* prototype declaration */
int hexcode();
void initial_set();
void key_set();
void rot_initial1(), rot_initial2(), rot_initial3(), rot_initial4();
void xor1(), xor2(), xor3(), xor4(), xor5(), xor6(), xor7(), xor8();
void ini_shift1(), ini_shift2(), ini_shift3(), ini_shift4();
void makekey();
void feal();
void ecb(), cbc(), ofb(), cfb();
void openerr();
void usage();

int hexcode(c)
char c;
{
	if(c >= '0' && c <= '9')	return (c - '0');
	else if(c >= 'A' && c <= 'F')	return (c - 'A' + 10);
	else if(c >= 'a' && c <= 'f')	return (c - 'a' + 10);
	else return (c & 0x0f);
}

void initial_set()
{
	char *p = initial, *q;
	int i;

	i = 16;
	while(*p != '\0' && i-- != 0)	*p++ = hexcode(*p);

	p = q = initial;
	i = 8;
	do
	{
		*q++ = (*p * 16) | *(p + 1);
		p += 2;
	} while(--i);
}

void key_set()
{
	char *p = keybuf;
	UINT *q = ks;
	int i;

	i = (exflag)? 32: 16;
	while(*p != '\0' && i-- != 0)	*p++ = hexcode(*p);

	p = keybuf;
	i = (exflag)? 16: 8;
	do
	{
		*q++ = (*p * 16) | *(p + 1);
		p += 2;
	} while(--i);
}

void rot_initial1(set)
char *set;
{
	memcpy(initial, initial4, 4);
	memcpy(initial4, set, 4);
}

void rot_initial2(set)
char *set;
{
	memcpy(initial, set, 8);
}

void rot_initial3(set)
char *set;
{
	ULONG m1, m2, s1;

	memcpy(&m1, initial, 4);
	memcpy(&m2, initial4, 4);
	memcpy(&s1, set, 4);
	m1 = (m1 << lshift)|(m2 >> rshift);
	m2 = (m2 << lshift)|(s1 >> rshift);
	memcpy(initial, &m1, 4);
	memcpy(initial4, &m2, 4);
}

void rot_initial4(set)
char *set;
{
	ULONG m2, s1, s2;

	memcpy(&m2, initial4, 4);
	memcpy(&s1, set, 4);
	memcpy(&s2, set + 4, 4);
	m2 = (m2 << lshift)|(s1 >> rshift);
	s1 = (s1 << lshift)|(s2 >> rshift);
	memcpy(initial, &m2, 4);
	memcpy(initial4, &s1, 4);
}

void xor1(in, out)
char *in, *out;
{
	out[0] ^= in[0];
}

void xor2(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
}

void xor3(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
}

void xor4(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
}

void xor5(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
}

void xor6(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
}

void xor7(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
	out[6] ^= in[6];
}

void xor8(in, out)
char *in, *out;
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
	out[6] ^= in[6];
	out[7] ^= in[7];
}

void ini_shift1()
{
	memcpy(initial4, initial, 4);
	memset(initial, 0, 4);
}

void ini_shift2()
{
	memset(initial, 0, 8);
}

void ini_shift3()
{
	ULONG m;

	memcpy(&m, initial, 4);
	m >>= rshift;
	memset(initial, 0, 4);
	memcpy(initial4, &m, 4);
}

void ini_shift4()
{
	ULONG m1, m2;

	memcpy(&m1, initial, 4);
	memcpy(&m2, initial4, 4);
	m2 = (m1 << lshift)|(m2 >> rshift);
	m1 >>= rshift; 
	memcpy(initial, &m1, 4);
	memcpy(initial4, &m2, 4);
}

void makekey(flag)
int flag;
{
	UINT *p, *q;
	UINT work;
	UINT a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11;
	UINT s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11;
	UINT p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11;
	register int m;

	a0 = a1 = a2 = a3 = 0;
	a4  = ks[0];
	a5  = ks[1];
	a6  = ks[2];
	a7  = ks[3];
	a8  = ks[4];
	a9  = ks[5];
	a10 = ks[6];
	a11 = ks[7];
	s0  = ks[8];
	s1  = ks[9];
	s2  = ks[10];
	s3  = ks[11];
	s4  = ks[12];
	s5  = ks[13];
	s6  = ks[14];
	s7  = ks[15];
	s8  = ks[8] ^ ks[12];
	s9  = ks[9] ^ ks[13];
	s10 = ks[10] ^ ks[14];
	s11 = ks[11] ^ ks[15];

	m = nn / 2 + 4;
	p = key;
	do
	{
		p1 = S1((a4 ^ a5) + (a6 ^ a7 ^ a0 ^ a8 ^ s0));
		p2 = S0((a6 ^ a7) + (p1 ^ a1 ^ a9 ^ s1));
		p0 = S0(a4 + (p1 ^ a2 ^ a10 ^ s2));
		p3 = S1(a7 + (p2 ^ a3 ^ a11 ^ s3));

		*p       = p0;
		*(p + 1) = p1;
		*(p + 2) = p2;
		*(p + 3) = p3;
		if(--m == 0)	break;

		p5 = S1((a8  ^ a9 ) + (a10 ^ a11 ^ a4 ^ p0 ^ s4));
		p6 = S0((a10 ^ a11) + (p5 ^ a5 ^ p1 ^ s5));
		p4 = S0(a8  + (p5 ^ a6 ^ p2 ^ s6));
		p7 = S1(a11 + (p6 ^ a7 ^ p3 ^ s7));

		*(p + 4) = p4;
		*(p + 5) = p5;
		*(p + 6) = p6;
		*(p + 7) = p7;
		if(--m == 0)	break;

		p9  = S1((p0 ^ p1) + (p2 ^ p3 ^ a8 ^ p4 ^ s8));
		p10 = S0((p2 ^ p3) + (p9 ^ a9 ^ p5 ^ s9));
		p8  = S0(p0 + (p9  ^ a10 ^ p6 ^ s10));
		p11 = S1(p3 + (p10 ^ a11 ^ p7 ^ s11));

		a0 = p0;
		a1 = p1;
		a2 = p2;
		a3 = p3;
		a4 = p4;
		a5 = p5;
		a6 = p6;
		a7 = p7;
		a8  = *(p + 8)  = p8;
		a9  = *(p + 9)  = p9;
		a10 = *(p + 10) = p10;
		a11 = *(p + 11) = p11;
		p += 12;
	} while(--m);

	if(flag == 0)
	{
		p = key;
		q = key + nn * 2 - 2;
		m = nn / 2;
		do
		{
			work = *p;
			*p   = *q;
			*q   = work;
			work     = *(p + 1);
			*(p + 1) = *(q + 1);
			*(q + 1) = work;
			p += 2;
			q -= 2;
		} while(--m);
	}

	key_nn = key + nn * 2;

	p = (flag)? key_nn: key_nn + 8;
	kn0 = *p;
	kn1 = *(p + 1); 
	kn2 = *(p + 2); 
	kn3 = *(p + 3); 
	kn4 = *(p + 4); 
	kn5 = *(p + 5); 
	kn6 = *(p + 6); 
	kn7 = *(p + 7); 

	p = (flag)? key_nn + 8: key_nn;
	kn8  = *p;  
	kn9  = *(p + 1); 
	kn10 = *(p + 2); 
	kn11 = *(p + 3); 
	kn12 = *(p + 4); 
	kn13 = *(p + 5); 
	kn14 = *(p + 6); 
	kn15 = *(p + 7);
}

void feal(in, out)
char *in, *out;
{
	UINT *t;
	UINT l0, l1, l2, l3, r0, r1, r2, r3, w1, w2;

	l0 = in[0] ^ kn0;
	l1 = in[1] ^ kn1;
	l2 = in[2] ^ kn2;
	l3 = in[3] ^ kn3;
	r0 = in[4] ^ kn4 ^ l0;
	r1 = in[5] ^ kn5 ^ l1;
	r2 = in[6] ^ kn6 ^ l2;
	r3 = in[7] ^ kn7 ^ l3;

	t = key;
	do
	{
		l1 ^= (w1 = S1((r0 ^ r1 ^ *t) + (w2 = r3 ^ r2 ^ *(t + 1))));
		l2 ^= (w2 = S0(w1 + w2));
		l0 ^= S0(r0 + w1);
		l3 ^= S1(r3 + w2);
		r1 ^= (w1 = S1((l0 ^ l1 ^ *(t + 2)) + (w2 = l3 ^ l2 ^ *(t + 3))));
		r2 ^= (w2 = S0(w1 + w2));
		r0 ^= S0(l0 + w1);
		r3 ^= S1(l3 + w2);
	} while((t += 4) != key_nn);

	out[0] = r0 ^ kn8;
	out[1] = r1 ^ kn9;
	out[2] = r2 ^ kn10;
	out[3] = r3 ^ kn11;
	out[4] = l0 ^ r0 ^ kn12;
	out[5] = l1 ^ r1 ^ kn13;
	out[6] = l2 ^ r2 ^ kn14;
	out[7] = l3 ^ r3 ^ kn15;
}

void ecb()
{
	char *p;

	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + 7) / 8;
			mem = mem1 * 8;
			memset(buffer + count, 0, mem - count);
		}
		do
		{
			feal(p, p);
			p += 8;
		} while(--mem1);
		write(f2, buffer, mem);
	}
}

void cbc()
{
	char *p;

	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + 7) / 8;
			mem = mem1 * 8;
			memset(buffer + count, 0, mem - count);
		}
		if(edflag)
		{
			do
			{
				xor8(initial, p);
				feal(p, initial);
				memcpy(p, initial, 8);
				p += 8;
			} while(--mem1);
		}
		else
		{
			do
			{
				feal(p, bufo);
				xor8(initial, bufo);
				memcpy(initial, p, 8);
				memcpy(p, bufo, 8);
				p += 8;
			} while(--mem1);
		}
		write(f2, buffer, mem);
	}
}

void ofb()
{
	char *p;

	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + blen - 1) / blen;
			mem = mem1 * blen;
			memset(buffer + count, 0, mem - count);
		}
		do
		{
			feal(initial, bufo);
			xor(bufo, p);
			rot_i(bufo);
			p += blen;
		} while(--mem1);
		write(f2, buffer, mem);
	}
}

void cfb()
{
	char *p;

	ini_s();
	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + blen - 1) / blen;
			mem = mem1 * blen;
			memset(buffer + count, 0, mem - count);
		}
		if(edflag)
		{
			do
			{
				feal(initial, bufo);
				xor(bufo, p);
				memcpy(x, xb1, blena);
				memcpy(xb2, p, blen);
				rot_i(x);
				p += blen;
			} while(--mem1);
		}
		else
		{
			do
			{
				feal(initial, bufo);
				memcpy(x, xb1, blena);
				memcpy(xb2, p, blen);
				rot_i(x);
				xor(bufo, p);
				p += blen;
			} while(--mem1);
		}
		write(f2, buffer, mem);
	}
}

void openerr(kind, file)
char *kind, *file;
{
	fprintf(stderr, "Error : %s file(%s) can't open.\n", kind, file);
	exit(-1);
}

void usage(prog)
char *prog;
{
	fprintf(stderr, "Usage : %s [-Mn] [-Kkey] [-Finit] [-Bn] [-Ln] [-X] [-Nn] <-E|-D> file1 file2\n", prog);
	fprintf(stderr, "   -M : Modes of Operations\n");
	fprintf(stderr, "        n : Mode Number (default = 1)\n");
	fprintf(stderr, "           1 = ECB(Electric CodeBook)\n");
	fprintf(stderr, "           2 = CBC(Cipher Block Chaining)\n");
	fprintf(stderr, "           3 = OFB(Output FeedBack)\n");
	fprintf(stderr, "           4 = CFB(Cipher FeedBack)\n");
	fprintf(stderr, "   -K : key file definition\n");
	fprintf(stderr, "        key : key file name\n");
	fprintf(stderr, "   -F : Initial Value of CBC,OFB,CFB mode(default = all'0')\n");
	fprintf(stderr, "        init : initial value file name\n");
	fprintf(stderr, "   -B : Block length direction\n");
	fprintf(stderr, "        n : Bleck length(1 - 8 Bytes, default = 8)\n");
	fprintf(stderr, "   -L : Key Feedback bit length direction\n");
	fprintf(stderr, "        n : Feedback length(1 - 64, default = 64)\n");
	fprintf(stderr, "   -X : FEAL-NX  Expanded version select.\n");
	fprintf(stderr, "   -N : Cycle Count in Expanded version\n");
	fprintf(stderr, "        n : 4 ≦ n ≦ %d, must be even(default = 8)\n", NMAX);
	fprintf(stderr, "   -E : Encryption mode\n");
	fprintf(stderr, "   -D : Decryption mode\n");
	fprintf(stderr, "  file1 : source file\n");
	fprintf(stderr, "  file2 : destination file\n");
	exit(0);
}

main(argc, argv)
int argc;
char *argv[];
{
	char *prog = argv[0];
	long tm0, tm1;
	int ki = 0, kk = 0, tflag = 0;
	int i, k, k1;

	setvbuf(stderr, (char *)NULL, _IONBF, 0);
	setvbuf(stdout, (char *)NULL, _IONBF, 0);

	if(argc < 2 || *argv[1] != '-')	usage(argv[0]);
	k = 1;
	do
	{
		switch(tolower(*(argv[k] + 1)))
		{
		case 'n':	nn = atoi(argv[k] + 2);
					if((nn < 4) || ((nn % 2) != 0))	usage(argv[0]);
					break;
		case 'x':	exflag = 1;
					break;
		case 'm':	mode = atoi(argv[k] + 2);
					if(mode < 1 || mode > 4)	usage(argv[0]);
					break;
		case 'k':	kk = k;
					break;
		case 'f':	ki = k;
					break;
		case 'b':	blen = atoi(argv[k] + 2);
					if(blen < 1 || blen > 8)	usage(argv[0]);
					break;
		case 'l':	llen = atoi(argv[k] + 2);
					if(llen < 1 || llen > 64)	usage(argv[0]);
					break;
		case 'd':	if(edflag == 1)	usage(argv[0]);
					edflag = 0;
					break;
		case 'e':	if(edflag == 0)	usage(argv[0]);
					edflag = 1;
					break;
		case 't':	tflag = 1;
					break;
		case 'h':	fp1 = fopen("des.man", "r");
					if(fp1 == NULL)	usage(argv[0]);
					while(fgets(buffer, 256, fp1) != NULL)
						fprintf(stderr, "%s", buffer);
					exit(0);
		case '?':	usage(argv[0]);
		default:	fprintf(stderr, "Error : illegal option input!\n");
					usage(argv[0]);
		}
	} while(*argv[++k] == '-');

	if((mode == 4 && blen * 8 > llen) || edflag == -1 || (k + 1) >= argc)
		usage(argv[0]);
	if(mode <= 2 && blen != 8)
	{
		fprintf(stderr, "Warning : -J option not allowed in ECB & CBC mode.\n");
		blen = 8;
	}
	blena = 8 - blen;
	k1 = k++;

	if(kk != 0)
	{
		fp1 = fopen(argv[kk] + 2, "r");
		if(fp1 == NULL)	openerr("key", argv[kk] + 2);
		read(fileno(fp1), keybuf, 16);
		fclose(fp1);
		key_set(keybuf, key);
	}
	if(mode >= 2)
	{
		switch(blen)
		{
		case 1:	xor = xor1;		break;
		case 2:	xor = xor2;		break;
		case 3:	xor = xor3;		break;
		case 4:	xor = xor4;		break;
		case 5:	xor = xor5;		break;
		case 6:	xor = xor6;		break;
		case 7:	xor = xor7;		break;
		case 8:	xor = xor8;		break;
		}
		if(ki)
		{
			fp1 = fopen(argv[ki] + 2, "r");
			if(fp1 == NULL)	openerr("initial", argv[ki] + 2);
			read(fileno(fp1), initial, 16);
			fclose(fp1);
			initial_set();
		}
		if(mode == 4)
		{
			xb1 = x + blen;
			xb2 = x + blena;
		}
		if(mode >= 3)
		{
			if(llen == 32)
			{
				ini_s = ini_shift1;
				rot_i = rot_initial1;
			}
			else if(llen == 64)
			{
				ini_s = ini_shift2;
				rot_i = rot_initial2;
			}
			else if(llen < 32)
			{
				ini_s = ini_shift3;
				rot_i = rot_initial3;
				lshift = llen;
				rshift = 32 - lshift;
			}
			else
			{
				ini_s = ini_shift4;
				rot_i = rot_initial4;
				lshift = llen - 32;
				rshift = 32 - lshift;
			}
		}
	}

	fp1 = fopen(argv[k1], "r");
	if(fp1 == NULL)	openerr("source", argv[k1]);
	fp2 = fopen(argv[k], "r");
	if(fp2 != NULL)
	{
		fprintf(stderr, "Error : destination file(%s) already exist.\n", argv[k]);
		exit(-1);
	}
	fp2 = fopen(argv[k], "w");
	f1 = fileno(fp1);
	f2 = fileno(fp2);

	nnbuf = NBUF / blen;
	mem = nbuf = nnbuf * blen;

	tm0 = clock();

	makekey((mode <= 2)? edflag: 1);

	switch(mode)
	{
	case 1:	ecb();		break;
	case 2:	cbc();		break;
	case 3:	ofb();		break;
	case 4:	cfb();		break;
	}
	tm1 = clock();

	fclose(fp1);
	fclose(fp2);
	if(tflag)	fprintf(stderr, "lap time : %7.3f [s]\n", (double)(tm1 - tm0) * 1.e-6);

	return 0;
}

プログラム・ソース("feal.cpp")           top (トップに戻る)
//
//		feal.cpp		FEAL(Fast Data Encipherment Algorithm) Program
//
const char *COPYRIGHT = "by Tomy(NIFTY:SGV01401) all rights reserved.";
const char *VER = "1.1";
const char *DATE = "1995/03/20";

#include <stdio.h>
#include <mem.h>
#include <io.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys\stat.h>

//#define		NODISP

#define		ULONG		unsigned long
#define		UINT		unsigned int

#define		S0(x)		*(rot0 + (0xff & (x)))
#define		S1(x)		*(rot1 + (0xff & (x)))

#ifndef NODISP
static ULONG filesize, outsize = 0, outcount = 0;
int blen50;
#endif

union
{
	ULONG a;
	char b[4];
} m;

char *mb0 = m.b, *mb1 = m.b + 1, *mb2 = m.b + 2, *mb3 = m.b + 3;

const ULONG NBUF = 51200;		// 50kB
const int NBUF8 = 6400;			// = NBUF / 8
const int NMAX = 128;			// maximum value of N

FILE *fp;
int f1, f2;

char buffer[NBUF], bufo[8];

unsigned int mem, mem1, nbuf, nnbuf, count, lshift, rshift;

static int edflag = -1, exflag = 0, mode = 1;
static int blen = 8, blena = 0, llen = 64, nn = 8;

static char initial[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
char *initial4 = initial + 4;

static char x[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
char *xb1, *xb2, *set, *set4;

static UINT ks[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };

UINT key[NMAX * 2 + 16];
UINT *key_nn;
UINT kn0, kn1, kn2, kn3, kn4, kn5, kn6, kn7;
UINT kn8, kn9, kn10, kn11, kn12, kn13, kn14, kn15;

static UINT rot0[257] = {
	  0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
	 64, 68, 72, 76, 80, 84, 88, 92, 96,100,104,108,112,116,120,124,
	128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,
	192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,
	  1,  5,  9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
	 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125,
	129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,
	193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,
	  2,  6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
	 66, 70, 74, 78, 82, 86, 90, 94, 98,102,106,110,114,118,122,126,
	130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,
	194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,
	  3,  7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
	 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127,
	131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,
	195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255, 0 };

UINT *rot1 = rot0 + 1;

/* prototype declaration */
void (*rot_i)(void);
void (*ini_s)(void);
void (*xor)(char *in, char *out);

int hexcode(char c);
void initial_set(void);
void key_set(char *buf);
void rot_initial1(void);
void rot_initial2(void);
void rot_initial3(void);
void rot_initial4(void);
void ini_shift1(void);
void ini_shift2(void);
void ini_shift3(void);
void ini_shift4(void);
void xor1(char *in, char *out);
void xor2(char *in, char *out);
void xor3(char *in, char *out);
void xor4(char *in, char *out);
void xor5(char *in, char *out);
void xor6(char *in, char *out);
void xor7(char *in, char *out);
void xor8(char *in, char *out);
void makekey(int flag);
void feal(char *in, char *out);
void ecb(void);
void cbc(void);
void ofb(void);
void cfb(void);
void openerr(char *kind, char *file);
void usage(char *prog);

int hexcode(char c)
{
	if(c >= '0' && c <= '9')	return (c - '0');
	else if(c >= 'A' && c <= 'F')	return (c - 'A' + 10);
	else if(c >= 'a' && c <= 'f')	return (c - 'a' + 10);
	else return (c & 0x0f);
}

void initial_set(void)
{
	char *p = initial, *q;

	register int i = 16;
	while(*p != '\0' && i-- != 0)	*p++ = hexcode(*p);

	p = q = initial;
	i = 8;
	do
	{
		*q++ = (*p * 16) | *(p + 1);
		p += 2;
	} while(--i);
}

void key_set(char *buf)
{
	char *p = buf;
	register int i = (exflag)? 32: 16;
	while(*p != '\0' && i-- != 0)	*p++ = hexcode(*p);

	UINT *q = ks;
	p = buf;
	i = (exflag)? 16: 8;
	do
	{
		*q++ = (*p * 16) | *(p + 1);
		p += 2;
	} while(--i);
}

ULONG char_to_long(char *a)
{
	*mb3 = a[0];
	*mb2 = a[1];
	*mb1 = a[2];
	*mb0 = a[3];
	return m.a;
}

void long_to_char(ULONG m1, ULONG m2)
{
	m.a = m1;
	initial[0] = *mb3;
	initial[1] = *mb2;
	initial[2] = *mb1;
	initial[3] = *mb0;
	m.a = m2;
	initial[4] = *mb3;
	initial[5] = *mb2;
	initial[6] = *mb1;
	initial[7] = *mb0;
}

void rot_initial1(void)
{
	memcpy(initial, initial4, 4);
	memcpy(initial4, set, 4);
}

void rot_initial2(void)
{
	memcpy(initial, set, 8);
}

void rot_initial3(void)
{
	ULONG m2 = char_to_long(initial4);
	long_to_char((char_to_long(initial) << lshift) | (m2 >> rshift),
				 (m2 << lshift) | (char_to_long(set) >> rshift));
}

void rot_initial4(void)
{
	ULONG s1 = char_to_long(set);
	long_to_char((char_to_long(initial4) << lshift) | (s1 >> rshift),
				 (s1 << lshift) | (char_to_long(set4) >> rshift));
}

void ini_shift1(void)
{
	memcpy(initial4, initial, 4);
	setmem(initial, 4, 0);
}

void ini_shift2(void)
{
	setmem(initial, 8, 0);
}

void ini_shift3(void)
{
	setmem(initial, 4, 0);
	m.a = char_to_long(initial) >> rshift;
	initial[4] = *mb3;
	initial[5] = *mb2;
	initial[6] = *mb1;
	initial[7] = *mb0;
}

void ini_shift4(void)
{
	ULONG m1 = char_to_long(initial);
	long_to_char((m1 >> rshift),
				 ((m1 << lshift) | (char_to_long(initial4) >> rshift)));
}

void xor1(char *in, char *out)
{
	out[0] ^= in[0];
}

void xor2(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
}

void xor3(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
}

void xor4(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
}

void xor5(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
}

void xor6(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
}

void xor7(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
	out[6] ^= in[6];
}

void xor8(char *in, char *out)
{
	out[0] ^= in[0];
	out[1] ^= in[1];
	out[2] ^= in[2];
	out[3] ^= in[3];
	out[4] ^= in[4];
	out[5] ^= in[5];
	out[6] ^= in[6];
	out[7] ^= in[7];
}

void makekey(int flag)
{
	UINT a0 = 0;
	UINT a1 = 0;
	UINT a2 = 0;
	UINT a3 = 0;
	UINT a4 = ks[0];
	UINT a5 = ks[1];
	UINT a6 = ks[2];
	UINT a7 = ks[3];
	UINT a8 = ks[4];
	UINT a9 = ks[5];
	UINT a10 = ks[6];
	UINT a11 = ks[7];

	UINT s0  = ks[8] ^ ks[12];
	UINT s1  = ks[9] ^ ks[13];
	UINT s2  = ks[10] ^ ks[14];
	UINT s3  = ks[11] ^ ks[15];
	UINT s4  = ks[8];
	UINT s5  = ks[9];
	UINT s6  = ks[10];
	UINT s7  = ks[11];
	UINT s8  = ks[12];
	UINT s9  = ks[13];
	UINT s10 = ks[14];
	UINT s11 = ks[15];

	register int m = nn / 2 + 4;
	UINT *p = key;
	UINT p1, p2;
	do
	{
		p1 = *(p + 1) = S1((a4 ^ a5) + (a6 ^ a7 ^ a0 ^ a8 ^ s0));
		p2 = *(p + 2) = S0((a6 ^ a7) + (p1 ^ a1 ^ a9 ^ s1));
		a0 = *p       = S0(a4 + ((a1 = p1) ^ a2 ^ a10 ^ s2));
		a3 = *(p + 3) = S1(a7 + ((a2 = p2) ^ a3 ^ a11 ^ s3));
		if(--m == 0)	break;

		p1 = *(p + 5) = S1((a8  ^ a9 ) + (a10 ^ a11 ^ a4 ^ a0 ^ s4));
		p2 = *(p + 6) = S0((a10 ^ a11) + (p1 ^ a5 ^ a1 ^ s5));
		a4 = *(p + 4) = S0(a8  + ((a5 = p1) ^ a6 ^ a2 ^ s6));
		a7 = *(p + 7) = S1(a11 + ((a6 = p2) ^ a7 ^ a3 ^ s7));
		if(--m == 0)	break;

		p1  = *(p + 9)  = S1((a0 ^ a1) + (a2 ^ a3 ^ a8 ^ a4 ^ s8));
		p2  = *(p + 10) = S0((a2 ^ a3) + (p1 ^ a9 ^ a5 ^ s9));
		a8  = *(p + 8)  = S0(a0 + ((a9  = p1) ^ a10 ^ a6 ^ s10));
		a11 = *(p + 11) = S1(a3 + ((a10 = p2) ^ a11 ^ a7 ^ s11));
		p += 12;
	} while(--m);

	if(flag == 0)
	{
		UINT *q = key + nn * 2 - 2;
		p = key;
		m = nn / 2;
		do
		{
			UINT work = *p;
			*p   = *q;
			*q   = work;
			work     = *(p + 1);
			*(p + 1) = *(q + 1);
			*(q + 1) = work;
			p += 2;
			q -= 2;
		} while(--m);
	}

	key_nn = key + nn * 2;

	p = (flag)? key_nn: key_nn + 8;
	kn0 = *p;
	kn1 = *(p + 1); 
	kn2 = *(p + 2); 
	kn3 = *(p + 3); 
	kn4 = *(p + 4); 
	kn5 = *(p + 5); 
	kn6 = *(p + 6); 
	kn7 = *(p + 7); 

	p = (flag)? key_nn + 8: key_nn;
	kn8  = *p;  
	kn9  = *(p + 1); 
	kn10 = *(p + 2); 
	kn11 = *(p + 3); 
	kn12 = *(p + 4); 
	kn13 = *(p + 5); 
	kn14 = *(p + 6); 
	kn15 = *(p + 7);
}

void feal(char *in, char *out)
{
	UINT l0 = in[0] ^ kn0;
	UINT l1 = in[1] ^ kn1;
	UINT l2 = in[2] ^ kn2;
	UINT l3 = in[3] ^ kn3;
	UINT r0 = in[4] ^ kn4 ^ l0;
	UINT r1 = in[5] ^ kn5 ^ l1;
	UINT r2 = in[6] ^ kn6 ^ l2;
	UINT r3 = in[7] ^ kn7 ^ l3;

	UINT w1, w2;
	UINT *t = key;
	do
	{
		l1 ^= (w1 = S1((r0 ^ r1 ^ *t) + (w2 = r3 ^ r2 ^ *(t + 1))));
		l2 ^= (w2 = S0(w1 + w2));
		l0 ^= S0(r0 + w1);
		l3 ^= S1(r3 + w2);
		r1 ^= (w1 = S1((l0 ^ l1 ^ *(t + 2)) + (w2 = l3 ^ l2 ^ *(t + 3))));
		r2 ^= (w2 = S0(w1 + w2));
		r0 ^= S0(l0 + w1);
		r3 ^= S1(l3 + w2);
	} while((t += 4) != key_nn);

	out[0] = r0 ^ kn8;
	out[1] = r1 ^ kn9;
	out[2] = r2 ^ kn10;
	out[3] = r3 ^ kn11;
	out[4] = l0 ^ r0 ^ kn12;
	out[5] = l1 ^ r1 ^ kn13;
	out[6] = l2 ^ r2 ^ kn14;
	out[7] = l3 ^ r3 ^ kn15;
}

void ecb(void)
{
	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		char *p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + 7) / 8;
			mem = mem1 * 8;
			memset(buffer + count, 0, mem - count);
		}
		do
		{
			feal(p, p);
			p += 8;
#ifndef NODISP
			if((outsize += blen50) >= outcount)
			{
				fputc('.', stderr);
				outcount += filesize;
			}
#endif
		} while(--mem1);
		write(f2, buffer, mem);
	}
}

void cbc(void)
{
	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		char *p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + 7) / 8;
			mem = mem1 * 8;
			memset(buffer + count, 0, mem - count);
		}
		if(edflag)
		{
			do
			{
				xor8(initial, p);
				feal(p, initial);
				memcpy(p, initial, 8);
				p += 8;
#ifndef NODISP
				if((outsize += blen50) >= outcount)
				{
					fputc('.', stderr);
					outcount += filesize;
				}
#endif
			} while(--mem1);
		}
		else
		{
			do
			{
				feal(p, bufo);
				xor8(initial, bufo);
				memcpy(initial, p, 8);
				memcpy(p, bufo, 8);
				p += 8;
#ifndef NODISP
				if((outsize += blen50) >= outcount)
				{
					fputc('.', stderr);
					outcount += filesize;
				}
#endif
			} while(--mem1);
		}
		write(f2, buffer, mem);
	}
}

void ofb(void)
{
	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		char *p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + blen - 1) / blen;
			mem = mem1 * blen;
			memset(buffer + count, 0, mem - count);
		}
		do
		{
			feal(initial, bufo);
			xor(bufo, p);
			rot_i();
			p += blen;
#ifndef NODISP
			if((outsize += blen50) >= outcount)
			{
				fputc('.', stderr);
				outcount += filesize;
			}
#endif
		} while(--mem1);
		write(f2, buffer, mem);
	}
}

void cfb(void)
{
	ini_s();
	while((count = read(f1, buffer, nbuf)) != 0)
	{
		mem1 = nnbuf;
		char *p = buffer;
		if(count != nbuf)
		{
			mem1 = (count + blen - 1) / blen;
			mem = mem1 * blen;
			memset(buffer + count, 0, mem - count);
		}
		if(edflag)
		{
			do
			{
				feal(initial, bufo);
				xor(bufo, p);
				memcpy(x, xb1, blena);
				memcpy(xb2, p, blen);
				rot_i();
				p += blen;
#ifndef NODISP
				if((outsize += blen50) >= outcount)
				{
					fputc('.', stderr);
					outcount += filesize;
				}
#endif
			} while(--mem1);
		}
		else
		{
			do
			{
				feal(initial, bufo);
				memcpy(x, xb1, blena);
				memcpy(xb2, p, blen);
				rot_i();
				xor(bufo, p);
				p += blen;
#ifndef NODISP
				if((outsize += blen50) >= outcount)
				{
					fputc('.', stderr);
					outcount += filesize;
				}
#endif
			} while(--mem1);
		}
		write(f2, buffer, mem);
	}
}

void openerr(char *kind, char *file)
{
	fprintf(stderr, "Error : %s file(%s) can't open.\n", kind, file);
	exit(-1);
}

void usage(char *prog)
{
	fprintf(stderr, "Usage : %s [-X] [-Nn] [-Mn] [-Kkey] [-Finit] [-Bn] [-Ln] <-E|-D> file1 file2\n", prog);
	fprintf(stderr, "   -X : FEAL-NX  Expanded version select.\n");
	fprintf(stderr, "   -N : Rotation count\n");
	fprintf(stderr, "        n : 4 ≦ n ≦ %d, must be even(default = 8)\n", NMAX);
	fprintf(stderr, "   -M : Modes of Operations\n");
	fprintf(stderr, "        n : Mode Number (default = 1)\n");
	fprintf(stderr, "           1 = ECB(Electric CodeBook)\n");
	fprintf(stderr, "           2 = CBC(Cipher Block Chaining)\n");
	fprintf(stderr, "           3 = OFB(Output FeedBack)\n");
	fprintf(stderr, "           4 = CFB(Cipher FeedBack)\n");
	fprintf(stderr, "   -K : key file definition\n");
	fprintf(stderr, "        key : key file name\n");
	fprintf(stderr, "   -F : Initial Value of CBC,OFB,CFB mode(default = all'0')\n");
	fprintf(stderr, "        init : initial value file name\n");
	fprintf(stderr, "   -B : Block length direction\n");
	fprintf(stderr, "        n : Bleck length(1 - 8 Bytes, default = 8)\n");
	fprintf(stderr, "   -L : Key Feedback bit length direction\n");
	fprintf(stderr, "        n : Feedback length(8 - 64, default = 64)\n");
	fprintf(stderr, "   -E : Encryption mode\n");
	fprintf(stderr, "   -D : Decryption mode\n");
	fprintf(stderr, "  file1 : source file\n");
	fprintf(stderr, "  file2 : destination file\n");
	exit(0);
}

main(int argc, char *argv[])
{
	int fi = 0, fk = 0;

	if(argc < 2 || *argv[1] != '-')	usage(argv[0]);
	int k = 1;
	do
	{
		switch(tolower(*(argv[k] + 1)))
		{
		case 'n':	nn = atoi(argv[k] + 2);
					if((nn < 4) || ((nn % 2) != 0))	usage(argv[0]);
					break;
		case 'x':	exflag = 1;
					break;
		case 'm':	mode = atoi(argv[k] + 2);
					if(mode < 1 || mode > 4)	usage(argv[0]);
					break;
		case 'k':	fk = k;
					break;
		case 'f':	fi = k;
					break;
		case 'b':	blen = atoi(argv[k] + 2);
					if(blen < 1 || blen > 8)	usage(argv[0]);
					break;
		case 'l':	llen = atoi(argv[k] + 2);
					if(llen < 1 || llen > 64)	usage(argv[0]);
					break;
		case 'd':	if(edflag == 1)	usage(argv[0]);
					edflag = 0;
					break;
		case 'e':	if(edflag == 0)	usage(argv[0]);
					edflag = 1;
					break;
		case 'h':	fp = fopen("feal.man", "r");
					if(fp == NULL)	usage(argv[0]);
					while(fgets(buffer, 256, fp) != NULL)
						fprintf(stderr, "%s", buffer);
					fclose(fp);
					exit(0);
		case '?':	usage(argv[0]);
		default:	fprintf(stderr, "Error : illegal option input!\n");
					usage(argv[0]);
		}
	} while(*argv[++k] == '-');

	if((mode == 4 && blen * 8 > llen) || edflag == -1 || (k + 1) >= argc)
		usage(argv[0]);
	if(mode <= 2 && blen != 8)
	{
		fprintf(stderr, "Warning : -B option not allowed in ECB & CBC mode.\n");
		blen = 8;
	}
	blena = 8 - blen;
#ifndef NODISP
	blen50 = blen * 50;
#endif


	int k1 = k++;
	int k2 = k;

	if(fk != 0)
	{
		if(*(argv[fk] + 2) == '=')	key_set(argv[fk] + 3);
		else if(*(argv[fk] + 2) == ':')
		{
			int i = (exflag)? 16: 8;
			char *p = argv[fk] + 3;
			UINT *q = ks;
			while(*p != '\0' && i-- != 0)	*q++ = *p++;
		}
		else
		{
			char keybuf[32];
			f1 = open(argv[fk] + 2, O_RDONLY | O_BINARY);
			if(f1 == -1)	openerr("key", argv[fk] + 2);
			read(f1, keybuf, (exflag)? 32: 16);
			key_set(keybuf);
			close(f1);
		}
	}

	if(mode >= 2 && fi != 0)
	{
		f1 = open(argv[fi] + 2, O_RDONLY | O_BINARY);
		if(f1 == -1)	openerr("initial", argv[fi] + 2);
		read(f1, initial, 16);
		initial_set();
		close(f1);
	}

	if(mode >= 2)
	{
		switch(blen)
		{
		case 1:	xor = xor1;		break;
		case 2:	xor = xor2;		break;
		case 3:	xor = xor3;		break;
		case 4:	xor = xor4;		break;
		case 5:	xor = xor5;		break;
		case 6:	xor = xor6;		break;
		case 7:	xor = xor7;		break;
		case 8:	xor = xor8;		break;
		}

		if(mode == 4)
		{
			xb1 = x + blen;
			xb2 = x + blena;
		}
		if(mode >= 3)
		{
			set = (mode == 3)? bufo: x;
			if(llen == 32)
			{
				ini_s = ini_shift1;
				rot_i = rot_initial1;
			}
			else if(llen == 64)
			{
				ini_s = ini_shift2;
				rot_i = rot_initial2;
			}
			else if(llen < 32)
			{
				ini_s = ini_shift3;
				rot_i = rot_initial3;
				lshift = llen;
				rshift = 32 - lshift;
			}
			else
			{
				ini_s = ini_shift4;
				rot_i = rot_initial4;
				lshift = llen - 32;
				rshift = 32 - lshift;
				set4 = set + 4;
			}
		}
	}

	f1 = open(argv[k1], O_RDONLY | O_BINARY);
	if(f1 == -1)	openerr("source", argv[k1]);
	fp = fopen(argv[k2], "rb");
	if(fp != NULL)
	{
		fprintf(stderr, "Error : destination file(%s) already exist.\n",
			argv[k2]);
		exit(-1);
	}
	f2 = open(argv[k2], O_WRONLY | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);

#ifndef NODISP
	outcount = filesize = filelength(f1);

	fprintf(stderr, "\nFEAL%s (Ver.%s)     ( %s --> %s )\n",
		(edflag)? "暗号化": "復号化", VER, argv[k1], argv[k2]);
	fprintf(stderr, "  Copyright(C) %s %s\n         ----+----!----+----!----+----!----+----!----+----!\n処理進行 ",
		DATE, COPYRIGHT);
#endif

	nnbuf = NBUF / blen;
	mem = nbuf = nnbuf * blen;

	makekey((mode <= 2)? edflag: 1);

	switch(mode)
	{
	case 1:	ecb();		break;
	case 2:	cbc();		break;
	case 3:	ofb();		break;
	case 4:	cfb();		break;
	}
#ifndef NODISP
	fputc('\n', stderr);
#endif
	close(f1);
	close(f2);
	return 0;
}

使用例 1           top (トップに戻る)

下記、コマンド群を処理した例を示します。
feal コマンドの様々なオプション使用方法を紹介しています。
( bmatch コマンドは、2つのファイルのバイナリレベルの一致を検査する機能を持ちます。)
また、あらかじめ、初期値および暗号鍵を記述したファイル initial、key を準備しています。
	feal -e -kkey feal.man dummy1
	feal -d -kkey dummy1 dummy1m
	bmatch dummy1m feal.man
	feal -m2 -finitial -e -kkey feal.man dummy2
	feal -m2 -finitial -d -kkey dummy2 dummy2m
	bmatch dummy2m feal.man
	feal -m3 -finitial -b6 -e -kkey feal.man dummy3
	feal -m3 -finitial -b6 -d -kkey dummy3 dummy3m
	bmatch dummy3m feal.man
	feal -m4 -finitial -b6 -l50 -e -kkey feal.man dummy4
	feal -m4 -finitial -b6 -l50 -d -kkey dummy4 dummy4m
	bmatch dummy4m feal.man
	feal -x -e -k=0123456789abcdef0123456789abcdef feal.man dummy5
	feal -x -d -k=0123456789abcdef0123456789abcdef dummy5 dummy5m
	bmatch dummy5m feal.man
	feal -x -e -k:色即是空、空即是色。 feal.man dummy6
	feal -x -d -k:色即是空、空即是色。 dummy6 dummy6m
	bmatch dummy6m feal.man

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy1 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy1 --> dummy1m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy1m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy2 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy2 --> dummy2m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy2m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy3 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy3 --> dummy3m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy3m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy4 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy4 --> dummy4m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy4m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy5 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy5 --> dummy5m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy5m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy6 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................

FEAL復号化 (Ver.1.1)     ( dummy6 --> dummy6m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
file1(dummy6m) & file2(feal.man) matched in 6838 byte.

使用例 2           top (トップに戻る)

下記、コマンド群を処理した例を示します。
feal コマンドの様々なオプション使用方法を紹介しています。
( lap コマンドは、パラメータで与えられるコマンドの実行時間を測定・表示する機能があります。bmatch コマンドは、2つのファイルのバイナリレベルの一致を検査する機能です。)
また、あらかじめ、初期値および暗号鍵を記述したファイル initial、key を準備しています。
	lap feal -e -kkey feal.man dummy1
	lap feal -d -kkey dummy1 dummy1m
	bmatch dummy1m feal.man
	lap feal -m2 -finitial -e -kkey feal.man dummy2
	lap feal -m2 -finitial -d -kkey dummy2 dummy2m
	bmatch dummy2m feal.man
	lap feal -m3 -finitial -b6 -e -kkey feal.man dummy3
	lap feal -m3 -finitial -b6 -d -kkey dummy3 dummy3m
	bmatch dummy3m feal.man
	lap feal -m4 -finitial -b6 -l50 -e -kkey feal.man dummy4
	lap feal -m4 -finitial -b6 -l50 -d -kkey dummy4 dummy4m
	bmatch dummy4m feal.man
	lap feal -x -n8 -e -kkey feal.man dummy5
	lap feal -x -n8 -d -kkey dummy5 dummy5m
	bmatch dummy5m feal.man
	lap feal -x -n64 -e -kkey feal.man dummy6
	lap feal -x -n64 -d -kkey dummy6 dummy6m
	bmatch dummy6m feal.man

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy1 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -e -kkey feal.man dummy1 
time :      1.158 [sec]

FEAL復号化 (Ver.1.1)     ( dummy1 --> dummy1m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -d -kkey dummy1 dummy1m 
time :      1.117 [sec]
file1(dummy1m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy2 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m2 -finitial -e -kkey feal.man dummy2 
time :      1.034 [sec]

FEAL復号化 (Ver.1.1)     ( dummy2 --> dummy2m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m2 -finitial -d -kkey dummy2 dummy2m 
time :      1.249 [sec]
file1(dummy2m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy3 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m3 -finitial -b6 -e -kkey feal.man dummy3 
time :      1.102 [sec]

FEAL復号化 (Ver.1.1)     ( dummy3 --> dummy3m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m3 -finitial -b6 -d -kkey dummy3 dummy3m 
time :      1.257 [sec]
file1(dummy3m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy4 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m4 -finitial -b6 -l50 -e -kkey feal.man dummy4 
time :      1.143 [sec]

FEAL復号化 (Ver.1.1)     ( dummy4 --> dummy4m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -m4 -finitial -b6 -l50 -d -kkey dummy4 dummy4m 
time :      1.268 [sec]
file1(dummy4m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy5 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -x -n8 -e -kkey feal.man dummy5 
time :      1.185 [sec]

FEAL復号化 (Ver.1.1)     ( dummy5 --> dummy5m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -x -n8 -d -kkey dummy5 dummy5m 
time :      1.204 [sec]
file1(dummy5m) & file2(feal.man) matched in 6838 byte.

FEAL暗号化 (Ver.1.1)     ( feal.man --> dummy6 )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -x -n64 -e -kkey feal.man dummy6 
time :      1.402 [sec]

FEAL復号化 (Ver.1.1)     ( dummy6 --> dummy6m )
  Copyright(C) 1995/03/20 by Tomy(NIFTY:SGV01401) all rights reserved.
         ----+----!----+----!----+----!----+----!----+----!
処理進行 ..................................................
command : feal -x -n64 -d -kkey dummy6 dummy6m 
time :      1.362 [sec]
file1(dummy6m) & file2(feal.man) matched in 6838 byte.

マニュアル           top (トップに戻る)

高速FEAL暗号処理プログラム(FEAL−NX対応)
  (FEAL : Fast Data Encipherment Algorithm)

  1. 使用法

     FEAL [-X] [-Nn] [-Mn] [-Kkey|-K=xxx|-K:txt] [-Finit] [-Bn] [-Ln] <-E|-D> file1 file2
    < > は必須オプション、[ ] は任意オプションを意味する。
    < >,[ ] 内の | は、どれか一つを指定することを意味する。
    各オプションの指定順は、任意である。
    同一オプションを指定した場合、後に指定した方が優先する。
    但し、-E 及び -D オプションは当然同時には指定できない。
    各オプションの先頭文字は、大文字でも小文字でも構わない。

    最も簡単な使用法は、 FEAL -E file1 file2 である。(file1 を file2 に暗号化する。)
    但し、暗号キーを指定していないので、 FEAL -D file2 file3 で誰にでも復号化できる。
    従って、基本的な使用法は、下記となる。
    暗号化 : FEAL -Kkeyfile -E file1 file2
    復号化 : FEAL -Kkeyfile -D file2 file3
    暗号キーを指定する keyfile の内容が同じであれば、file3 の内容は、file1 と一致する。

  2. オプション説明
     
    • -X は拡張FEAL暗号モード(FEAL−NX)を選択するオプションである。
      本オプション指定時には、暗号化キーを16バイト(128ビット)指定できる。
      (ノーマル・モードでは暗号化キーは8バイト(64ビット)である。)

    • -N は暗号アルゴリズムの内部回転数を指定するオプションで、
      4以上の偶数で128以下の数を指定する。
      2のべき乗数が推奨値。回転数が多いほど暗号強度が高いが、
      その分処理時間がかかる。(内部回転数のデフォルトは8である。)

    • -M はFEALの利用モードを指定する場合に使用するオプションで,
      下記番号で指定する。デフォルトは1である。(3項参照)
        
      1. : ECB(Electric CodeBook)
      2. : CBC(Cipher Block Chaining)
      3. : OFB(Output FeedBack)
      4. : CFB(Cipher FeedBack)

    • -K は暗合化および復合化を行うキーの定義ファイル名 key を指定する。
      復号時には,暗合化時と同じキーを定義したファイル名を指定せねばならない。
      キーは,16進コード(0-9,A-F)で設定する。
      (2桁で1バイトである。従って、ノーマル・モード時は16桁以内、
       FEAL−NX時は32桁以内となる。)

      -K オプションは省略可能であるが,省略時は all'0'のキーを設定する。
      なお、SUMIKA氏のFESにならって、暗号キーを直接指定するオプションとして、
      下記2オプションをサポートした。

      -K=xxx.... で16進コード入力
      -K:txt で任意テキスト(txt)入力(漢字も可)。

    • 利用モード 1 以外の利用オプションを指定する場合には,初期値を指示する必要があり,
      -F に続き初期値を定義したファイル名を指定する。
      初期値は,8バイトの16進コード(0-9,A-F:16桁)で設定する。
      初期値は省略可能であるが,省略時は all'0'が指定されたものとみなす。

    • -K 及び -F オプションでは、任意のファイル指定可(バイナリファイルも可)。
      先頭の16バイトまたは32バイトをデータと見なす。
      16進テキストコード以外の場合は、0x0f とのANDをとって4ビットのデータに変換している。

    • 利用モード 3,4 は,FEAL を乱数キーとして使用する逐次暗合であり,
      1回で処理するブロック長を -B オプションにて指定する。(1〜8 バイト,デフォルトは8)

    • 利用モード 4 では,さらに暗合文フィードバックのビット数を指定する。
      これは,-L オプションを用い 8〜64 で指定するが,
      -B オプション指定のブロック長以上でなければならない。(デフォルトはブロック長と同じ。)

    • -E(暗合化)または -D(復号化)のどちらかのオプションを必ず指定する。
      オプション指定により,file1 を暗合化または復号化し,file2 を生成する。
      なお、file2 と同名のファイルが既に存在する場合には、処理を中止する。
       

  3. 利用モード説明

     JIS X5052−90 「64ビットのブロック暗号アルゴリズムの利用モード」での
     利用モード4種にほぼ対応した。

    (1) ECB(Electric CodeBook)モード
    FEALをそのまま用いた8バイトのブロック暗合方式。
    この方法では,下記のような問題がある。
          
    • (最終)ブロックが8バイトに充たない場合,0その他の固定ダミービットを挿入する為,
      平文の内容に偏りが生じ,暗合解読の手掛かりを与える。
      特にデータベース等の暗合化に際し,フィールド長が8バイト未満の場合,問題となる。

    • 同一の暗合キーの下では平文8バイトと暗合文8バイトが1対1に対応するため
      既知平文攻撃に対して弱い。

    • ブロック単位で暗合文を改ざんされてもそれが判らない。
    (2) CBC(Cipher Block Chaining)モード

    暗合文ブロック連鎖方式。ブロック連鎖の初期値を指定する。
    暗合文8バイトと次の平文8バイトの排他的論理和を次の暗合化の入力とする。
    この方法では,ビット誤りが2つのブロックに伝播する欠点がある。
    (3) OFB(Output FeedBack)モード

    出力フィードバックによる同期式逐次暗合方式。
    乱数キー生成用初期値,逐次暗合ブロック長を指定する。
    任意バイト長(1〜8)のブロック毎に異なる(乱数)キーで
    暗合化(平文との排他的論理和)を行う。
    この乱数キーの生成にFEALを利用する。
    乱数キーを次のブロックの暗合化を行うための乱数キー生成の入力とする。
    この方式は暗合文のビット消滅が発生した場合,
    その後のすべての暗合文に対する同期が外れる。
    (4) CFB(Cipher FeedBack)モード

    暗合文フィードバックによる自己同期式逐次暗合方式。
    乱数キー生成用初期値,逐次暗合ブロック長,暗合文フィードバックビット長を指定する。
    乱数キー生成のフィードバックにおいて暗合文の一部をフィードバックする。
    この方式は暗合文のビット消滅が発生した場合,後続のLビットの暗合文に影響を与える。

  4. 参考文献
    1)FEAL暗号の拡張 宮口庄司 他 NTT R&D Vol.39 No.10 1990
    2)JIS X5052-90 「64ビットのブロック暗号アルゴリズムの利用モード」
    3)現代暗号理論  池野伸一,小山謙二 共著  電子通信学会編
    4)ネットワーク・セキュリティ  D.W.Davies,W.L.Price 共著 上園忠弘 監訳 日経マグロウヒル社

  5. 開発環境
      
    • コンパイラ  Turbo C++ Ver1.0
    • 動作確認機種 PC9801NA

  6. その他
    FEALの実行プログラムに関しては、既にSUMIKA氏(NIFTY-Serve JCG02171)が
    FES(Version 0.93)を発表されている。(NIFTY-Serve,FGALST,LIB6,#1244)

    このプログラムは、基本FEAL暗号である FEAL−8 の上位互換である FEAL−N に対応している。
    (内部回転数を8固定から任意指定としたもの)
    本プログラムは、さらに FEAL−N の上位互換である FEAL−NX
    (暗号キーの長さを64→128ビットとした)に対応し、
    ブロック暗号の利用モード他、細かいオプションに対応した。