ctl ^= ((r1 >> 9) & 0x1);
if (ctl)
{
feedback = (r1 >> 18) ^ (r1 >> 17) ^ (r1 >> 16) ^ (r1 >> 13);
r1 = (r1 << 1) & 0x7ffff;
if (feedback & 0x01)
r1 ^= 0x01;
}
return (r1);
}
unsigned long clock_r2(ctl, r2)
int ctl;
unsigned long r2;
{
unsigned long feedback;
ctl ^= ((r2 >> 11) & 0x1);
if (ctl)
{
feedback = (r2 >> 21) ^ (r2 >> 20) ^ (r2 >> 16) ^ (r2 >> 12);
r2 = (r2 << 1) & 0x3fffff;
if (feedback & 0x01)
r2 ^= 0x01;
}
return (r2);
}
unsigned long clock_r3(ctl, r3)
int ctl;
unsigned long r3;
{
unsigned long feedback;
ctl ^= ((r3 >> 11) & 0x1);
if (ctl)
{
feedback = (r3 >> 22) ^ (r3 >> 21) ^ (r3 >> 18) ^ (r3 >> 17);
r3 = (r3 << 1) & 0x7fffff;
if (feedback & 0x01)
r3 ^= 0x01;
}
return (r3);
}
int keystream(key, frame, alice, bob)
unsigned char *key; /* 64 bit session key */
unsigned long frame; /* 22 bit frame sequence number */
unsigned char *alice; /* 114 bit Alice to Bob key stream */
unsigned char *bob; /* 114 bit Bob to Alice key stream */
{
unsigned long r1; /* 19 bit shift register */
unsigned long r2; /* 22 bit shift register */
unsigned long r3; /* 23 bit shift register */
int i; /* counter for loops */
int clock_ctl; /* xored with clock enable on each shift register */
unsigned char *ptr; /* current position in keystream */
unsigned char byte; /* byte of keystream being assembled */
unsigned int bits; /* number of bits of keystream in byte */
unsigned int bit; /* bit output from keystream generator */
/* Initialise shift registers from session key */
r1 = (key[0] | (key[1] << 8) | (key[2] << 16) ) & 0x7ffff;
r2 = ((key[2] >> 3) | (key[3] << 5) | (key[4] << 13) | (key[5] << 21)) &
0x3fffff;
r3 = ((key[5] >> 1) | (key[6] << 7) | (key[7] << 15) ) & 0x7fffff;
/* Merge frame sequence number into shift register state, by xor'ing it
* into the feedback path
*/
for (i=0;i<22;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
if (frame & 1)
{
r1 ^= 1;
r2 ^= 1;
r3 ^= 1;
}
frame = frame >> 1;
}
/* Run shift registers for 100 clock ticks to allow frame number to
* be diffused into all the bits of the shift registers
*/
for (i=0;i<100;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
}
/* Produce 114 bits of Alice->Bob key stream */
ptr = alice;
bits = 0;
byte = 0;
for (i=0;i<114;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
byte = (byte << 1) | bit;
bits++;
if (bits == 8)
{
*ptr = byte;
ptr++;
bits = 0;
byte = 0;
}
}
if (bits)
*ptr = byte;
/* Run shift registers for another 100 bits to hide relationship between
* Alice->Bob key stream and Bob->Alice key stream.
*/
for (i=0;i<100;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
}
/* Produce 114 bits of Bob->Alice key stream */
ptr = bob;
bits = 0;
byte = 0;
for (i=0;i<114;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
byte = (byte << 1) | bit;
bits++;
if (bits == 8)
{
*ptr = byte;
ptr++;
bits = 0;
byte = 0;
}
}
if (bits)
*ptr = byte;
return (0);
}
void a5_key(a5_ctx *c, char *k){
c->r1 = k[0]<<11|k[1]<<3 | k[2]>>5 ; /* 19 */
c->r2 = k[2]<<17|k[3]<<9 | k[4]<<1 | k[5]>>7; /* 22 */
c->r3 = k[5]<<15|k[6]<<8 | k[7] ; /* 23 */
}
/* Step one bit in A5, return 0 or 1 as output bit. */
int a5_step(a5_ctx *c){
int control;
control = threshold(c->r1,c->r2,c->r3);
c->r1 = clock_r1(control,c->r1);
c->r2 = clock_r2(control,c->r2);
c->r3 = clock_r3(control,c->r3);
return( (c->r1^c->r2^c->r3)&1);
}
/* Encrypts a buffer of len bytes. */
void a5_encrypt(a5_ctx *c, char *data, int len){
int i,j;
char t;
for(i=0;i for(j=0;j<8;j++) t = t<<1 | a5_step(c);
data[i]^=t;
}
}
void a5_decrypt(a5_ctx *c, char *data, int len){
a5_encrypt(c,data,len);
}
void main(void){
a5_ctx c;
char data[100];
char key[] = {1,2,3,4,5,6,7,8};
int i,flag;
for(i=0;i<100;i++) data[i] = i;
a5_key(&c,key);
a5_encrypt(&c,data,100);
a5_key(&c,key);
a5_decrypt(&c,data,1);
a5_decrypt(&c,data+1,99);
flag = 0;
for(i=0;i<100;i++) if(data[i]!=i)flag = 1;
if(flag)printf("Decrypt failed\n"); else printf("Decrypt succeeded\n");
}
SEAL
#undef SEAL_DEBUG
#define ALG_OK 0
#define ALG_NOTOK 1
#define WORDS_PER_SEAL_CALL 1024
typedef struct {
unsigned long t[520]; /* 512 rounded up to a multiple of 5 + 5*/
unsigned long s[265]; /* 256 rounded up to a multiple of 5 + 5*/
unsigned long r[20]; /* 16 rounded up to multiple of 5 */
unsigned long counter; /* 32-bit synch value. */
unsigned long ks_buf[WORDS_PER_SEAL_CALL];
int ks_pos;
} seal_ctx;
#define ROT2(x) (((x) >> 2) | ((x) << 30))
#define ROT9(x) (((x) >> 9) | ((x) << 23))
#define ROT8(x) (((x) >> 8) | ((x) << 24))
#define ROT16(x) (((x) >> 16) | ((x) << 16))
#define ROT24(x) (((x) >> 24) | ((x) << 8))
#define ROT27(x) (((x) >> 27) | ((x) << 5))
#define WORD(cp) ((cp[0] << 24)|(cp[1] << 16)|(cp[2] << 8)|(cp[3]))
#define F1(x, y, z) (((x) & (y)) | (((x)) & (z)))
#define F2(x, y, z) ((x)^(y)^(z))
#define F3(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define F4(x, y, z) ((x)^(y)^(z))
int g(in, i, h)
unsigned char *in;
int i;
unsigned long *h;
{
unsigned long h0;
unsigned long h1;
unsigned long h2;
unsigned long h3;
unsigned long h4;
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
unsigned long e;
unsigned char *kp;
unsigned long w[80];
unsigned long temp;
kp = in;
h0 = WORD(kp); kp += 4;
h1 = WORD(kp); kp += 4;
h2 = WORD(kp); kp += 4;
h3 = WORD(kp); kp += 4;
h4 = WORD(kp); kp += 4;
w[0] = i;
for (i=1;i<16;i++)
w[i] = 0;
for (i=16;i<80;i++)
w[i] = w[i-3]^w[i-8]^w[i-14]^w[i-16];
a = h0;
b = h1;
c = h2;
d = h3;
e = h4;
for (i=0;i<20;i++)
{
temp = ROT27(a) + F1(b, c, d) + e + w[i] + 0x5a827999;
e = d;
d = c;
c = ROT2(b);
b = a;
a = temp;
}
for (i=20;i<40;i++)
{
temp = ROT27(a) + F2(b, c, d) + e + w[i] + 0x6ed9eba1;
e = d;
d = c;
c = ROT2(b);
b = a;
a = temp;
}
for (i=40;i<60;i++)
{
temp = ROT27(a) + F3(b, c, d) + e + w[i] + 0x8f1bbcdc;
e = d;
d = c;
c = ROT2(b);
b = a;
a = temp;
}
for (i=60;i<80;i++)
{
temp = ROT27(a) + F4(b, c, d) + e + w[i] + 0xca62c1d6;
e = d;
d = c;
c = ROT2(b);
b = a;
a = temp;
}
h[0] = h0+a;
h[1] = h1+b;
h[2] = h2+c;
h[3] = h3+d;
h[4] = h4+e;
return (ALG_OK);
}
unsigned long gamma(a, i)
unsigned char *a;
int i;
{
unsigned long h[5];
(void) g(a, i/5, h);
return h[i % 5];
}
int seal_init(seal_ctx *result, unsigned char *key)
{
int i;
unsigned long h[5];
for (i=0;i<510;i+=5)
g(key, i/5, &(result->t[i]));
/* horrible special case for the end */
g(key, 510/5, h);
for (i=510;i<512;i++)
result->t[i] = h[i-510];
/* 0x1000 mod 5 is +1, so have horrible special case for the start */
g(key, (-1+0x1000)/5, h);
for (i=0;i<4;i++)
result->s[i] = h[i+1];
for (i=4;i<254;i+=5)
g(key, (i+0x1000)/5, &(result->s[i]));
/* horrible special case for the end */
g(key, (254+0x1000)/5, h);
for (i=254;i<256;i++)
result->s[i] = h[i-254];
/* 0x2000 mod 5 is +2, so have horrible special case at the start */
g(key, (-2+0x2000)/5, h);
for (i=0;i<3;i++)
result->r[i] = h[i+2];
for (i=3;i<13;i+=5)
g(key, (i+0x2000)/5, &(result->r[i]));
/* horrible special case for the end */
g(key, (13+0x2000)/5, h);
for (i=13;i<16;i++)
result->r[i] = h[i-13];
return (ALG_OK);
}
int seal(seal_ctx *key, unsigned long in, unsigned long *out)
{
int i;
int j;
int l;
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
unsigned short p;
unsigned short q;
unsigned long n1;
unsigned long n2;
unsigned long n3;
unsigned long n4;
unsigned long *wp;
wp = out;
for (l=0;l<4;l++)
{
a = in ^ key->r[4*l];
b = ROT8(in) ^ key->r[4*l+1];
c = ROT16(in) ^ key->r[4*l+2];
d = ROT24(in) ^ key->r[4*l+3];
for (j=0;j<2;j++)
{
p = a & 0x7fc;
b += key->t[p/4];
a = ROT9(a);
p = b & 0x7fc;
c += key->t[p/4];
b = ROT9(b);
p = c & 0x7fc;
d += key->t[p/4];
c = ROT9(c);
p = d & 0x7fc;
a += key->t[p/4];
d = ROT9(d);
}
n1 = d;
n2 = b;
n3 = a;
n4 = c;
p = a & 0x7fc;
b += key->t[p/4];
a = ROT9(a);
p = b & 0x7fc;
c += key->t[p/4];
b = ROT9(b);
p = c & 0x7fc;
d += key->t[p/4];
c = ROT9(c);
p = d & 0x7fc;
a += key->t[p/4];
d = ROT9(d);
/* This generates 64 32-bit words, or 256 bytes of keystream. */
for (i=0;i<64;i++)
{
p = a & 0x7fc;
b += key->t[p/4];
a = ROT9(a);
b ^= a;
q = b & 0x7fc;
c ^= key->t[q/4];
b = ROT9(b);
c += b;
p = (p+c) & 0x7fc;
d += key->t[p/4];
c = ROT9(c);
d ^= c;
q = (q+d) & 0x7fc;
a ^= key->t[q/4];
d = ROT9(d);
a += d;
p = (p+a) & 0x7fc;
b ^= key->t[p/4];
a = ROT9(a);
q = (q+b) & 0x7fc;
c += key->t[q/4];
b = ROT9(b);
p = (p+c) & 0x7fc;
d ^= key->t[p/4];
c = ROT9(c);
q = (q+d) & 0x7fc;
a += key->t[q/4];
d = ROT9(d);
*wp = b + key->s[4*i];
wp++;
*wp = c ^ key->s[4*i+1];
wp++;
*wp = d + key->s[4*i+2];
wp++;
*wp = a ^ key->s[4*i+3];
wp++;
if (i & 1)
{
a += n3;
c += n4;
}
else
{
a += n1;
c += n2;
}
}
}
return (ALG_OK);
}
/* Added call to refill ks_buf and reset counter and ks_pos. */
void seal_refill_buffer(seal_ctx *c){
seal(c,c->counter,c->ks_buf);
c->counter++;
c->ks_pos = 0;
}
void seal_key(seal_ctx *c, unsigned char *key){
seal_init(c,key);
c->counter = 0; /* By default, init to zero. */
c->ks_pos = WORDS_PER_SEAL_CALL;
/* Refill keystream buffer on next call. */
}
/* This encrypts the next w words with SEAL. */
void seal_encrypt(seal_ctx *c, unsigned long *data_ptr, int w){
int i;
for(i=0;i if(c->ks_pos>=WORDS_PER_SEAL_CALL) seal_refill_buffer(c);
data_ptr[i]^=c->ks_buf[c->ks_pos];
c->ks_pos++;
}
}
void seal_decrypt(seal_ctx *c, unsigned long *data_ptr, int w) {
seal_encrypt(c,data_ptr,w);
}
void seal_resynch(seal_ctx *c, unsigned long synch_word){
c->counter = synch_word;
c->ks_pos = WORDS_PER_SEAL_CALL;
}
void main(void){
seal_ctx sc;
unsigned long buf[1000],t;
int i,flag;
unsigned char key[] =
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
printf("1\n");
seal_key(&sc,key);
printf("2\n");
for(i=0;i<1000;i++) buf[i]=0;
printf("3\n");
seal_encrypt(&sc,buf,1000);
printf("4\n");
t = 0;
for(i=0;i<1000;i++) t = t ^ buf[i];
printf("XOR of buf is %08lx.\n",t);
seal_key(&sc,key);
seal_decrypt(&sc,buf,1);
seal_decrypt(&sc,buf+1,999);
flag = 0;
for(i=0;i<1000;i++) if(buf[i]!=0)flag=1;
if(flag) printf("Decrypt failed.\n");
else printf("Decrypt succeeded.\n");
}
References
1. ABA Bank Card Standard, "Management and Use of Personal Information Numbers, " Aids from ABA, Catalog no. 207213, American Bankers Association, 1979.
2. ABA Document 4.3, "Key Management Standard," American Bankers Association, 1980.
3. M. Abadi, J. Feigenbaum, and J. Kilian, "On Hiding Information from an Oracle," Proceedings of the 19th ACM Symposium on the Theory of Computing, 1987, pp. 195-203.
4. M. Abadi, J. Feigenbaum, and J. Kilian, "On Hiding Information from an Oracle," Journal of
Computer and System Sciences, v.39, n.1, Aug 1989, pp.21-50.
5. M. Abadi and R. Needham, "Prudent Engineering Practice for Cryptographic Protocols,"
Research Report 125, Digital Equipment Corp Systems Research Center, Jun 1994.
6. C.M. Adams, "On Immunity Against Biham and Shamir's Differential Cryptanalysis,' "
Information Processing Letters, v. 41, 14 Fob 1992, pp. 77-80.
7. C.M. Adams, "Simple and Effective Key Scheduling for Symmetric Ciphers, " Workshop on
Selected Areas in Cryptography Workshop Record, Kingston, Ontario, 5-6 May 1994,
pp.129-133.
8. C.M. Adams and H. Mailer, "Security Related Comments Regarding McEliece's Public-Key
Cryptosystem, " Advances in Cryptology CRYPTO '87 Proceedings, Springer-Verlag, 1988,
pp. 224-230.
9. C.M. Adams and S.E. Tavares, "The Structured Design of Cryptographically Good SBoxes,"
journal of Cryptology v. 3, n. 1, 1990, pp. 27-41.
10. C.M. Adams and S.E. Tavares, "Designing S-Boxes for Ciphers Resistant to Differential
Cryptanalysis," Proceedings of the 3rd Symposium on State and Progress of Research in
Cryptography Rome, Italy, 15-16 Feh 1993, pp. 181-190.
11. W. Adams and D. Shanks, "Strong Primality Tests That Are Not Sufficient, " Mathematics of
Computation, v. 39, 1982, pp. 255-300.
12. W.W Adams and L.J. Goldstein, Introduction to Number Theory, Englewood Cliffs, N.J.:
Prentice-Hall, 1976.
13. B.S. Adiga and P. Shankar, "Modified LuLee Cryptosystem," Electronics Letters, v 21, n. 18,
29 Aug 1985, pp. 794-795.
14. L.M. Adleman, "A Subexponential Algorithm for the Discrete Logarithm Problem with
Applications to Cryptography," Proceedings of the IEEE 20th Annual Symposium of
Foundations of Computer Science, 1979, pp.55-60.
15. L.M. Adleman, "On Breaking Generalized Knapsack Public Key Cryptosystems, " Proceedings of the 15th ACM Symposium on Theory of Computing, 1983, pp. 402412.
16. L.M. Adleman, "Factoring Numbers Using Singular Integers," Proceedings of the 23rd
Annual ACM Symposium on the Theory of Computing, 1991, pp. 64 71.
17. L.M. Adleman, "Molecular Computation of Solutions to Combinatorial Problems," Science, v.
266, n. 11, Nov 1994, p. 1021.
18. L.M. Adleman, D. Estes, and K. McCurley, "Solving Bivariate Quadratic Congruences in
Random Polynomial Time," Mathematics of Computation, v. 48, n. 177, Jan 1987, pp. 17-
28.
19. L.M. Adleman, C. Pomerance, and R.S. Rumeley, "On Distinguishing Prime Numbers from
Composite Numbers, " Annals of Mathematics, v. 117, n. 1, 1983, pp. 173-206.
20. L.M. Adleman and R.L. Rivest, "How to Break the Lu-Lee {COMSAT) Public-Key
Cryptosystem, " MIT Laboratory for Computer Science, Jul 1979.
21. G.B. Agnew, "Random Sources for Cryptographic Systems, " Advances in Cryptology
EUROCRYPT '8 7 Proceedings, Springer-Verlag, 1988, pp. 77-81.
22. G.B. Agnew, R.C. Mullin, I.M. Onyszchuk, and S.A. Vanstone, "An Implementation for a
Fast Public-Key Cryptosystem," Journal of Cryptology, v. 3, n. 2, 1991, pp. 63-79.
23. G.B. Agnew, R.C. Mullin, and S.A. Vanstone, "A Fast Elliptic Curve Cryptosystem,"
Advances in Cryptology EUROCRYPT '89 Proceedings, Spnnger-Verlag, 1990, pp. 706-
708.
24. G.B. Agnew, R.C. Mullin, and S.A. Vanstone, "Improved Digital Signature Scheme Based on
Discrete Exponentiation, " Electronics Letters, v. 26, n. 14, 5 Jul 1990, pp. 1024 1025.
25. G.B. Agnew, R.C. Mullin, and S.A. Vanstone, "On the Development of a Fast Elliptic Curve
Cryptosystem," Advances in Cryptology EUROCRYPT '92 Proceedings, Springer-Verlag,
1993, pp. 482 26. G.B. Agnew, R.C. Mullin, and S.A. Vanstone, "An Implementation of Elliptic Curve
Cryptosystems over F:155," IEEE Selected Areas of Communications, v. 11, n. 5, Jun 1993,
pp. 804-813.
27. A. Aho, J. Hopcroft, and J. Ullman. The 40. Design and Analysis of Computer Algorithms,
Addison-Wesley, 1974.
28. S.G. Akl, "Digital Signatures: A Tutorial Survey." Computer, v. 16, n. 2, Feb 1983, pp. 15-24.
29. S.G. Akl, "On the Security of Compressed Encodings," Advances in Cryptology: Proceedings of Crypto 83, Plenum Press, 1984, pp. 209-230.
30. S.G. Akl and H. Meijer, "A Fast Pseudo-Random Permutation Generator with Applications to
Cryptology," Advances in Cryptology: Proceedings of CRYPTO 84, Springer-Verlag, 1985,
pp. 269-275.
31. M. Alabbadi and S.B. Wicker, "Security of Xinmei Digital Signature Scheme," Electronics
Letters, v. 28, n. 9, 23 Apr 1992, pp. 890-89 1.
32. M. Alabbadi and S.B. Wicker, "Digital Signature Schemes Based on Error-Correcting
Codes," Proceedings of the 1993 IEEE-ISIT, IEEE Press, 1993, p. 199.
33. M. Alabbadi and S.B. Wicker, "Cryptanalysis of the Harn and Wang Modification of the
Xinmei Digital Signature Scheme, " Electronics Letters, v. 28, n. 18, 27 Aug 1992, pp.
1756-1758.
34. K. Alagappan and J. Tardo, "SPX Guide: Prototype Public Key Authentication Service, "
Digital Equipment Corp.. May 1991.
35. W. Alexi, B.-Z. Chor, O. Goldreich, and C.R Schnorr, "RSA and Rabin Functions: Certain
Parts Are as Hard as the Whole," Proceedings of the 25th IEEE Symposium on the
Foundations of Computer Science, 1984, pp. 449-457.
36. W. Alexi, B.-Z. Chor, O. Goldreich, and C.R Schnorr, "RSA and Rabin Functions: Certain
Parts are as Hard as the Whole," SIAM 1ournal on Computing, v. 17, n. 2, Apr 1988, pp.
194 209.
37. Ameritech Mobile Communications et al., "Cellular Digital Packet Data System Specifications:
1>8>1>9>3>