The ISAAC cipher: Difference between revisions

→‎{{header|Pascal}}: Spaces and indenting according to coding guidelines. The logic remained unchanged.
(→‎{{header|Pascal}}: [0 .. 255] instead of [0..256]; unnecessary variables removed)
(→‎{{header|Pascal}}: Spaces and indenting according to coding guidelines. The logic remained unchanged.)
Line 3,024:
<lang Pascal>
PROGRAM RosettaIsaac;
USES StrUtils;
StrUtils;
 
TYPE
iMode = (iEncrypt, iDecrypt);
 
TYPE iMode = (iEncrypt,iDecrypt);
// TASK globals
VAR
VAR msg : STRING = 'a Top Secret secret';
key msg : STRINGString = 'thisa isTop mySecret secret key';
xctx key : STRINGString = '';this //is XORmy ciphertextsecret key';
mctx xctx: STRINGString = ''; // MODXOR ciphertext
xptx mctx: STRINGString = ''; // XOR decryptionMOD (plaintext)ciphertext
mptx xptx: STRINGString = ''; // MODXOR decryption (plaintext)
mptx: String = ''; // MOD decryption (plaintext)
 
// ISAAC globals
VAR
// external results
// external results
VAR randrsl: ARRAY[0 .. 255] OF CARDINAL;
randrsl: ARRAY[0 .. 255] OF Cardinal;
randcnt: CARDINAL;
randcnt: Cardinal;
// internal state
VAR mm: ARRAY[0 .. 255] OF CARDINAL;
aa: CARDINAL = 0; bb: CARDINAL = 0; cc: CARDINAL = 0;
 
// internal state
mm: ARRAY[0 .. 255] OF Cardinal;
aa: Cardinal = 0;
bb: Cardinal = 0;
cc: Cardinal = 0;
 
PROCEDURE Isaac;
VAR
VAR i,x,y: CARDINAL;
i, x, y: Cardinal;
BEGIN
cc := cc + 1; // cc just gets incremented once per 256 results
bb := bb + cc; // then combined with bb
 
FOR i := 0 TO 255 DO BEGIN
BEGIN
x := mm[i];
x CASE:= (mm[i mod 4) OF];
0: aa := aa xorCASE (aai shlMOD 134); OF
1 0: aa := aa xorXOR (aa shrSHL 613);
2 1: aa := aa xorXOR (aa shlSHR 26);
3 2: aa := aa xorXOR (aa shrSHL 162);
3: aa := aa XOR (aa SHR 16);
END;
END;
aa := mm[(i+128) mod 256] + aa;
y aa := mm[(xi shr+ 2128) modMOD 256] + aa + bb;
y := mm[i(x SHR 2) MOD 256] :=+ yaa + bb;
bbmm[i] := mm[(y shr 10) mod 256] + x;
bb := mm[(y SHR 10) MOD 256] + x;
randrsl[i]:= bb;
randrsl[i] := bb;
END;
END;
// this reset was not in the original readable.c
randcnt := 0; // prepare to use the first set of results
END; {// Isaac}
 
PROCEDURE Mix(VAR a, b, c, d, e, f, g, h: Cardinal);
 
// if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
PROCEDURE mix(VAR a,b,c,d,e,f,g,h: CARDINAL);
BEGIN
a := a xorXOR b shlSHL 11; d := d + a; b := b + c;
b := b xorXOR c shrSHR 2; e := e + b; c := c + d;
c := c xorXOR d shlSHL 8; f := f + c; d := d + e;
d := d xorXOR e shrSHR 16; g := g + d; e := e + f;
e := e xorXOR f shlSHL 10; h := h + e; f := f + g;
f := f xorXOR g shrSHR 4; a := a + f; g := g + h;
g := g xorXOR h shlSHL 8; b := b + g; h := h + a;
h := h xorXOR a shrSHR 9; c := c + h; a := a + b;
END; {mix}// Mix
 
 
PROCEDURE iRandInit(flag: BOOLEANBoolean);
VAR
VAR i,a,b,c,d,e,f,g,h: CARDINAL;
i, a, b, c, d, e, f, g, h: Cardinal;
BEGIN
aa := 0; bb := 0; cc := 0;
a := $9e3779b9; // the golden ratio
b := a; c := a; d := a; e := a; f := a; g := a; h := a;
b:=a; c:=a; d:=a; e:=a; f:=a; g:=a; h:=a;
 
FOR i := 0 TO 3 DO // scramble it
mixMix(a, b, c, d, e, f, g, h);
 
i := 0;
REPEAT // fill in mm[] with messy stuff
IF flag THEN
IF flag THEN BEGIN // use all the information in the seed
BEGIN // use all the information in the seed
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
a e+= randrsl[i+4 ]; fb += randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+71];
c += randrsl[i + 2]; d += randrsl[i + 3];
e += randrsl[i + 4]; f += randrsl[i + 5];
g += randrsl[i + 6]; h += randrsl[i + 7];
END;
 
mixMix(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;
i += 8;
UNTIL i > 255;
 
IF (flag) THEN BEGIN
BEGIN
// do a second pass to make all of the seed affect all of mm
// do a second pass to make all of the seed affect all of mm
i:=0;
i REPEAT:= 0;
REPEAT
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
ea += mm[i+4 ]; fb += mm[i +5 1]; gc += mm[i +6 2]; hd += mm[i +7 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 ]:=Mix(a;, mm[i+1]:=b;, mm[i+2]:=c;, mm[i+3]:=d, e, f, g, h);
mm[i+4 ] :=e a; mm[i +5 1] :=f b; mm[i +6 2] :=g c; mm[i +7 3] :=h d;
mm[i + 4] := e; mm[i + 5] := f; mm[i + 6] := g; mm[i + 7] := h;
i+=8;
UNTIL i>255 += 8;
END UNTIL i > 255;
END;
isaac(); // fill in the first set of results
randcnt:=0Isaac(); // prepare tofill usein the first set of results
randcnt := 0; // prepare to use the first set of results
END; {randinit}
END; // iRandInit
 
// Seed ISAAC with a given string.
 
// The string can be any size. The first 256 values will be used.
{ Seed ISAAC with a given string.
PROCEDURE iSeed(seed: String; flag: Boolean);
The string can be any size. The first 256 values will be used.}
VAR
PROCEDURE iSeed(seed: STRING; flag: BOOLEAN);
VAR i, m: CARDINALCardinal;
BEGIN
FOR i := 0 TO 255 DO mm[i]:=0;
mm[i] := 0;
m := Length(seed)-1;
m := Length(seed) - 1;
FOR i:= 0 TO 255 DO BEGIN
FOR i := 0 TO 255 DO
// in case seed has less than 256 elements
BEGIN
IF i>m THEN randrsl[i]:=0
// in case seed has less than 256 elements
// Pascal strings are 1-based
IF i > m THEN
ELSE randrsl[i]:=ord(seed[i+1]);
randrsl[i] := 0
END;
// Pascal strings are 1-based
// initialize ISAAC with seed
ELSE
iRandInit(flag);
randrsl[i] := Ord(seed[i + 1]);
END; {iSeed}
END;
 
// initialize ISAAC with seed
iRandInit(flag);
END; // iSeed
 
{// Get a random 32-bit value 0..MAXINT }
FUNCTION iRandom : CARDINALCardinal;
BEGIN
iRandom := randrsl[randcnt];
inc(randcnt);
IF (randcnt > 255) THEN BEGIN
BEGIN
Isaac();
Isaac;
randcnt := 0;
randcnt := 0;
END;
END; {iRandom}
END; // iRandom
 
// Get a random character in printable ASCII range
 
FUNCTION iRandA: Byte;
{ Get a random character in printable ASCII range }
FUNCTION iRandA: BYTE;
BEGIN
iRandA := iRandom modMOD 95 + 32;
END;
 
// Convert an ASCII string to a hexadecimal string
FUNCTION Ascii2Hex(s: String): String;
VAR
i: Cardinal;
BEGIN
Ascii2Hex := '';
FOR i := 1 TO Length(s) DO
Ascii2Hex += Dec2Numb(Ord(s[i]), 2, 16);
END; // Ascii2Hex
 
{// convertXOR anencrypt ASCIIon stringrandom tostream. aOutput: hexadecimalASCII string }
FUNCTION ascii2hexVernam(smsg: STRINGString): STRINGString;
VAR
VAR i: CARDINAL;
i: Cardinal;
BEGIN
BEGIN
ascii2hex := '';
Vernam := '';
FOR i := 1 TO Length(s) DO
FOR i := 1 to Length(msg) DO
ascii2hex += Dec2Numb(ord(s[i]),2,16);
Vernam += Chr(iRandA XOR Ord(msg[i]));
END;
END; // Vernam
 
// Get position of the letter in chosen alphabet
FUNCTION LetterNum(letter, start: Char): Byte;
BEGIN
LetterNum := (Ord(letter) - Ord(start));
END; // LetterNum
 
// Caesar-shift a character <shift> places: Generalized Vigenere
{ XOR encrypt on random stream. Output: ASCII string }
FUNCTION Caesar(m: iMode; ch: Char; shift, modulo: Integer; start: Char): Char;
FUNCTION Vernam(msg: STRING): STRING;
VAR
VAR i: CARDINAL;
n: Integer;
BEGIN
BEGIN
Vernam := '';
IF m = iDecrypt THEN
FOR i := 1 to length(msg) DO
shift := -shift;
Vernam += chr(iRandA xor ord(msg[i]));
n := LetterNum(ch, start) + shift;
END;
n := n MOD modulo;
 
IF n < 0 THEN
 
n += modulo;
{ Get position of the letter in chosen alphabet }
Caesar := Chr(Ord(start) + n);
FUNCTION letternum(letter, start: CHAR): byte;
END; // Caesar
BEGIN
letternum := (ord(letter)-ord(start));
END;
 
 
{ Caesar-shift a character <shift> places: Generalized Vigenere }
FUNCTION Caesar(m: iMode; ch: CHAR; shift, modulo: INTEGER; start: CHAR): CHAR;
VAR n: INTEGER;
BEGIN
IF m = iDecrypt THEN shift := -shift;
n := letternum(ch,start) + shift;
n := n MOD modulo;
IF n<0 THEN n += modulo;
Caesar := chr(ord(start)+n);
END;
 
 
{ Vigenere mod 95 encryption & decryption. Output: ASCII string }
FUNCTION Vigenere(msg: STRING; m: iMode): STRING;
VAR i: CARDINAL;
BEGIN
Vigenere := '';
FOR i := 1 to length(msg) DO
Vigenere += Caesar(m,msg[i],iRandA,95,' ');
END;
 
// Vigenere MOD 95 encryption & decryption. Output: ASCII string
FUNCTION Vigenere(msg: String; m: iMode): String;
VAR
i: Cardinal;
BEGIN
Vigenere := '';
FOR i := 1 to Length(msg) DO
Vigenere += Caesar(m, msg[i], iRandA, 95, ' ');
END; // Vigenere
 
BEGIN
// 1) seed ISAAC with the key
iSeed(key, true);
// 2) Encryption
// a) XOR (Vernam)
xctx := Vernam(msg);
// b) MOD (Vigenere)
mctx := Vigenere(msg, iEncrypt);
// 3) Decryption
iSeed(key, true);
// a) XOR (Vernam)
xptx := Vernam(xctx);
// b) MOD (Vigenere)
mptx := Vigenere(mctx, iDecrypt);
// program output
Writeln('Message: ', msg);
Writeln('Key : ', key);
Writeln('XOR : ',ascii2hex Ascii2Hex(xctx));
Writeln('MOD : ',ascii2hex Ascii2Hex(mctx));
Writeln('XOR dcr: ', xptx);
Writeln('MOD dcr: ', mptx);
END.
</lang>
Anonymous user