The ISAAC cipher: Difference between revisions

From Rosetta Code
Content added Content deleted
(First task - Creating "the ISAAC Cipher": initial save - further edits and C reference example to follow...)
 
(C reference code added.)
Line 33: Line 33:


ISAAC can of course also be initialized with a single 32-bit unsigned integer in the manner of traditional RNGs, and indeed used as such for research and gaming purposes. But building a strong and simple ISAAC-based stream cipher - putting the irreparably broken RC4 to shame - is our goal here: ISAAC's intended purpose.
ISAAC can of course also be initialized with a single 32-bit unsigned integer in the manner of traditional RNGs, and indeed used as such for research and gaming purposes. But building a strong and simple ISAAC-based stream cipher - putting the irreparably broken RC4 to shame - is our goal here: ISAAC's intended purpose.


=={{header|C}}==
This is Bob Jenkins' reference code for ISAAC. Please insert initialization and encryption routines for the task in hand.
<lang C>
/*
------------------------------------------------------------------------------
readable.c: My random number generator, ISAAC.
(c) Bob Jenkins, March 1996, Public Domain
You may use this code in any way you wish, and it is free. No warrantee.
------------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stddef.h>

/* a ub4 is an unsigned 4-byte quantity */
typedef unsigned long int ub4;

/* external results */
ub4 randrsl[256], randcnt;

/* internal state */
static ub4 mm[256];
static ub4 aa=0, bb=0, cc=0;

void isaac()
{
register ub4 i,x,y;

cc = cc + 1; /* cc just gets incremented once per 256 results */
bb = bb + cc; /* then combined with bb */

for (i=0; i<256; ++i)
{
x = mm[i];
switch (i%4)
{
case 0: aa = aa^(aa<<13); break;
case 1: aa = aa^(aa>>6); break;
case 2: aa = aa^(aa<<2); break;
case 3: aa = aa^(aa>>16); break;
}
aa = mm[(i+128)%256] + aa;
mm[i] = y = mm[(x>>2)%256] + aa + bb;
randrsl[i] = bb = mm[(y>>10)%256] + x;
}
}

/* if (flag!=0), then use the contents of randrsl[] to initialize mm[]. */
#define mix(a,b,c,d,e,f,g,h) \
{ \
a^=b<<11; d+=a; b+=c; \
b^=c>>2; e+=b; c+=d; \
c^=d<<8; f+=c; d+=e; \
d^=e>>16; g+=d; e+=f; \
e^=f<<10; h+=e; f+=g; \
f^=g>>4; a+=f; g+=h; \
g^=h<<8; b+=g; h+=a; \
h^=a>>9; c+=h; a+=b; \
}

void randinit(flag)
int flag;
{
int i;
ub4 a,b,c,d,e,f,g,h;
aa=bb=cc=0;
a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */

for (i=0; i<4; ++i) /* scramble it */
{
mix(a,b,c,d,e,f,g,h);
}

for (i=0; i<256; i+=8) /* fill in mm[] with messy stuff */
{
if (flag) /* use all the information in the seed */
{
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
}
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}

if (flag)
{ /* do a second pass to make all of the seed affect all of mm */
for (i=0; i<256; i+=8)
{
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}
}

isaac(); /* fill in the first set of results */
randcnt=256; /* prepare to use the first set of results */
}

int main()
{
// C programmers: insert main variables and seed routine here

// insert XOR or mod 26 encryption routine here

// insert output routine here
}
</lang>

Revision as of 06:42, 22 July 2014

Task
The ISAAC cipher
You are encouraged to solve this task according to the task description, using any language you may know.

ISAAC is a cryptographically secure pseudo-random number generator (CSPRNG) and stream cipher. It was developed by Bob Jenkins from 1993 (http://burtleburtle.net/bob/rand/isaac.html) and placed in the Public Domain. ISAAC is fast - especially when optimised - and portable to most architectures in nearly all programming and scripting languages. It is also simple and succinct, using as it does just two 256-byte arrays for its state.

ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are the principal bitwise operations employed. To date - and that's after more than 20 years of existence - ISAAC has not been broken (unless GCHQ or NSA did it, but they wouldn't be telling). ISAAC thus deserves a lot more attention than it has hitherto received and it would be salutary to see it more universally implemented.

Your task, should you choose to accept it, is to translate ISAAC's reference C code into your language of choice. The RNG should then be seeded with the string "this is my secret key" and finally the message "a Top Secret secret" should be encrypted on that key. Your program's output ciphertext will be a string of hexadecimal digits.

Two encryption schemes are possible: (1) XOR (Vernam) or (2) Caesar-shift mod 26 (Vigenère). XOR is the simplest; C-shifting offers greater security. You may choose either scheme, but please specify which you used. Here are the alternative sample outputs for checking purposes:

Message: a Top Secret secret
Key    : this is my secret key
XOR    : 
Mod 26 : 

No official seeding method for ISAAC has been published, but for this task we may as well just inject the bytes of our key into the randrsl array, padding with zeroes before mixing, like so:

// zeroise mm array
FOR i:= 0 TO 255 DO mm[i]:=0;
// check seed's highest array element
m := High(seed);
// inject the seed
FOR i:= 0 TO 255 DO BEGIN
	// in case seed[] has less than 256 elements.
	IF i>m THEN randrsl[i]:=0  
		ELSE randrsl[i]:=seed[i];
END;
// initialize ISAAC with seed
RandInit(true);

ISAAC can of course also be initialized with a single 32-bit unsigned integer in the manner of traditional RNGs, and indeed used as such for research and gaming purposes. But building a strong and simple ISAAC-based stream cipher - putting the irreparably broken RC4 to shame - is our goal here: ISAAC's intended purpose.


C

This is Bob Jenkins' reference code for ISAAC. Please insert initialization and encryption routines for the task in hand. <lang C> /*


readable.c: My random number generator, ISAAC. (c) Bob Jenkins, March 1996, Public Domain You may use this code in any way you wish, and it is free. No warrantee.


  • /
  1. include <stdio.h>
  2. include <stddef.h>

/* a ub4 is an unsigned 4-byte quantity */ typedef unsigned long int ub4;

/* external results */ ub4 randrsl[256], randcnt;

/* internal state */ static ub4 mm[256]; static ub4 aa=0, bb=0, cc=0;

void isaac() {

  register ub4 i,x,y;
  cc = cc + 1;    /* cc just gets incremented once per 256 results */
  bb = bb + cc;   /* then combined with bb */
  for (i=0; i<256; ++i)
  {
    x = mm[i];
    switch (i%4)
    {
    case 0: aa = aa^(aa<<13); break;
    case 1: aa = aa^(aa>>6); break;
    case 2: aa = aa^(aa<<2); break;
    case 3: aa = aa^(aa>>16); break;
    }
    aa              = mm[(i+128)%256] + aa;
    mm[i]      = y  = mm[(x>>2)%256] + aa + bb;
    randrsl[i] = bb = mm[(y>>10)%256] + x;
  }

}

/* if (flag!=0), then use the contents of randrsl[] to initialize mm[]. */

  1. define mix(a,b,c,d,e,f,g,h) \

{ \

  a^=b<<11; d+=a; b+=c; \
  b^=c>>2;  e+=b; c+=d; \
  c^=d<<8;  f+=c; d+=e; \
  d^=e>>16; g+=d; e+=f; \
  e^=f<<10; h+=e; f+=g; \
  f^=g>>4;  a+=f; g+=h; \
  g^=h<<8;  b+=g; h+=a; \
  h^=a>>9;  c+=h; a+=b; \

}

void randinit(flag) int flag; {

  int i;
  ub4 a,b,c,d,e,f,g,h;
  aa=bb=cc=0;
  a=b=c=d=e=f=g=h=0x9e3779b9;  /* the golden ratio */
  for (i=0; i<4; ++i)          /* scramble it */
  {
    mix(a,b,c,d,e,f,g,h);
  }
  for (i=0; i<256; i+=8)   /* fill in mm[] with messy stuff */
  {
    if (flag)                  /* use all the information in the seed */
    {
      a+=randrsl[i  ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
      e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
    }
    mix(a,b,c,d,e,f,g,h);
    mm[i  ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
    mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
  }
  if (flag)
  {        /* do a second pass to make all of the seed affect all of mm */
    for (i=0; i<256; i+=8)
    {
      a+=mm[i  ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
      e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
      mix(a,b,c,d,e,f,g,h);
      mm[i  ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
      mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
    }
  }
  isaac();            /* fill in the first set of results */
  randcnt=256;        /* prepare to use the first set of results */

}

int main() {

 // C programmers: insert main variables and seed routine here
 // insert XOR or mod 26 encryption routine here
 // insert output routine here

} </lang>