The ISAAC cipher: Difference between revisions

m
(Added Kotlin)
m (→‎{{header|Wren}}: Minor tidy)
 
(36 intermediate revisions by 16 users not shown)
Line 1:
{{draft task|Encryption}}
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-word arrays for its state.
Line 59:
But building a strong and simple ISAAC-based stream cipher - replacing the irreparably broken RC4 - is our goal here: ISAAC's intended purpose.
<br><br>
 
=={{header|BASIC}}==
==={{header|FreeBASIC}}===
{{trans|C}}
<syntaxhighlight lang="freebasic">' version 03-11-2016
' compile with: fbc -s console
 
Dim Shared As UInteger<32> randrsl(256), randcnt
Static Shared As UInteger<32> mm(256)
Static Shared As UInteger<32> aa, bb ,cc
 
Sub ISAAC()
Dim As UInteger<32> i, x, y
cc = cc + 1
bb = bb + cc
For i = 0 To 256 -1
x = mm(i)
Select Case (i Mod 4)
Case 0 : aa = aa Xor (aa Shl 13)
Case 1 : aa = aa Xor (aa Shr 6)
Case 2 : aa = aa Xor (aa Shl 2)
Case 3 : aa = aa Xor (aa Shr 16)
End Select
aa = mm((i+128) Mod 256) + aa
y = mm((x Shr 2) Mod 256) + aa + bb : mm(i) = y
bb = mm((y Shr 10) Mod 256) + x : randrsl(i) = bb
Next
randcnt = 0
End Sub
 
#Macro mix(a, b, c, d, e, f, g, h)
a Xor= b Shl 11 : d += a : b += c
b Xor= c Shr 2 : e += b : c += d
c Xor= d Shl 8 : f += c : d += e
d Xor= e Shr 16 : g += d : e += f
e Xor= f Shl 10 : h += e : f += g
f Xor= g Shr 4 : a += f : g += h
g Xor= h Shl 8 : b += g : h += a
h Xor= a Shr 9 : c += h : a += b
#EndMacro
 
Sub randinit(flag As Long)
Dim As Long i
Dim As UInteger<32> a = &H9e3779b9 '/* the golden ratio *
Dim As UInteger<32> b = &H9e3779b9
Dim As UInteger<32> c = &H9e3779b9
Dim As UInteger<32> d = &H9e3779b9
Dim As UInteger<32> e = &H9e3779b9
Dim As UInteger<32> f = &H9e3779b9
Dim As UInteger<32> g = &H9e3779b9
Dim As UInteger<32> h = &H9e3779b9
aa = 0 : bb = 0 : cc = 0
For i = 0 To 3
mix(a, b, c, d, e, f, g, h)
Next
For i = 0 To 255 Step 8
If flag = 1 Then
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
End If
Next
If flag = 1 Then
For i = 0 To 255 Step 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
Next
End If
ISAAC()
randcnt = 0
End Sub
 
' // Get a random 32-bit value 0..MAXINT
Function iRandom() As UInteger<32>
Dim As UInteger<32> r = randrsl(randcnt)
randcnt += 1
If randcnt > 255 Then
ISAAC()
randcnt = 0
End If
Return r
End Function
 
' // Get a random character in printable ASCII range
Function iRandA() As UByte
Return iRandom() Mod 95 +32
End Function
 
' // Seed ISAAC with a string
Sub iSeed(seed As String, flag As Long)
Dim As ULong i, m = Len(seed) -1
For i = 0 To 255
mm(i) = 0
Next
For i = 0 To 255
If i > m Then
randrsl(i) = 0
Else
randrsl(i) = seed[i]
End If
Next
randinit(flag)
End Sub
 
' // maximum length of message
'#define MAXMSG 4096
#Define _MOD_ 95 ' mod is FreeBASIC keyword
#Define _START_ 32 ' start is used as variable name
 
' // cipher modes for Caesar
Enum ciphermode
mEncipher
mDecipher
mNone
End Enum
 
' // XOR cipher on random stream. Output: ASCII string
' no maximum lenght for input and output string
Function Vernam(msg As String) As String
Dim As ULong i
Dim As String v
For i = 0 To Len(msg) -1
v += Chr(iRandA() Xor msg[i])
Next
Return v
End Function
 
' // Caesar-shift a printable character
Function Ceasar(m As ciphermode, ch As UByte, shift As UByte, modulo As UByte, _
start As UByte) As UByte
' FreeBASIC Mod does not handle negative numbers correctly
' also there is litte problem with shift (declared UByte)
' the IIF() statement helps with shift
' to avoid a negative n a 8 times modulo is added
' modulo * 8 get translateted by FreeBASIC to modulo shl 3
Dim As Long n = (ch - start) + IIf(m = mDecipher, -shift, shift) + modulo * 8
n = n Mod modulo
Return start + n
End Function
 
' // Caesar-shift a string on a pseudo-random stream
Function CeasarStr(m As ciphermode, msg As String, modulo As UByte, _
start As UByte) As String
Dim As Long i
Dim As String v
For i = 0 To Len(msg) -1
v += Chr(Ceasar(m, msg[i], iRandA(), modulo, start))
Next
Return v
End Function
 
' ------=< MAIN >=------
 
Dim As Long n, l
Dim As String msg = "a Top Secret secret"
Dim As String key = "this is my secret key"
 
Dim As String vctx, vptx
Dim As String cctx, cptx
 
l = Len(msg)
' // Encrypt: Vernam XOR
iSeed(key, 1)
vctx = Vernam(msg)
' // Encrypt: Caesar
cctx = CeasarStr(mEncipher, msg, _mod_, _start_)
' // Decrypt: Vernam XOR
iSeed(key, 1)
vptx = Vernam(vctx)
' // Decrypt: Caesar
cptx = CeasarStr(mDecipher, cctx, _mod_, _start_)
Print "message: "; msg
Print " key: "; key
Print " XOR: ";
' // Output Vernam ciphertext as a string of hex digits
For n = 0 To l -1
Print Hex(vctx[n], 2);
Next
Print
' // Output Vernam decrypted plaintext
Print "XOR dcr: "; vptx
' // Caesar
Print " MOD: ";
' // Output Caesar ciphertext as a string of hex digits
For n= 0 To l -1
Print Hex(cctx[n], 2);
Next
Print
' // Output Caesar decrypted plaintext
Print "MOD dcr: " ; cptx
 
' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End</syntaxhighlight>
{{out}}
<pre>message: a Top Secret secret
key: this is my secret key
XOR: 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr: a Top Secret secret
MOD: 734270227D36772A783B4F2A5F206266236978
MOD dcr: a Top Secret secret</pre>
 
=={{header|C}}==
At the top is Bob Jenkins' reference code for ISAAC.
Below and in main() is the task's complete solution for XOR and MOD.
<syntaxhighlight lang="c">
<lang C>
/* Known to compile and work with tcc in win32 & gcc on Linux (with warnings)
------------------------------------------------------------------------------
Line 295 ⟶ 507:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 308 ⟶ 520:
=={{header|C sharp}}==
XOR with decryption check.
<langsyntaxhighlight Clang="c sharp">
using System;
 
Line 468 ⟶ 680:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 475 ⟶ 687:
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr: a Top Secret secret
</pre>
 
=={{header|C++}}==
{{trans|Modula-2}}
<syntaxhighlight lang="cpp">
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
 
enum CipherMode {ENCRYPT, DECRYPT};
 
// External results
uint32_t randRsl[256];
uint32_t randCnt;
 
// Internal state
uint32_t mm[256];
uint32_t aa = 0, bb = 0, cc = 0;
 
void isaac()
{
++cc; // cc just gets incremented once per 256 results
bb += cc; // then combined with bb
for (uint32_t i = 0; i < 256; ++i)
{
uint32_t x, y;
 
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;
y = mm[(x >> 2) % 256] + aa + bb;
mm[i] = y;
bb = mm[(y >> 10) % 256] + x;
randRsl[i] = bb;
}
randCnt = 0; // Prepare to use the first set of results.
}
 
void mix(uint32_t a[])
{
a[0] = a[0] ^ a[1] << 11; a[3] += a[0]; a[1] += a[2];
a[1] = a[1] ^ a[2] >> 2; a[4] += a[1]; a[2] += a[3];
a[2] = a[2] ^ a[3] << 8; a[5] += a[2]; a[3] += a[4];
a[3] = a[3] ^ a[4] >> 16; a[6] += a[3]; a[4] += a[5];
a[4] = a[4] ^ a[5] << 10; a[7] += a[4]; a[5] += a[6];
a[5] = a[5] ^ a[6] >> 4; a[0] += a[5]; a[6] += a[7];
a[6] = a[6] ^ a[7] << 8; a[1] += a[6]; a[7] += a[0];
a[7] = a[7] ^ a[0] >> 9; a[2] += a[7]; a[0] += a[1];
}
 
void randInit(bool flag)
{
uint32_t a[8];
aa = bb = cc = 0;
a[0] = 2654435769UL; // 0x9e3779b9: the golden ratio
for (uint32_t j = 1; j < 8; ++j)
a[j] = a[0];
for (uint32_t i = 0; i < 4; ++i) // Scramble it.
mix(a);
for (uint32_t i = 0; i < 256; i += 8) // Fill in mm[] with messy stuff.
{
if (flag) // Use all the information in the seed.
for (uint32_t j = 0; j < 8; ++j)
a[j] += randRsl[i + j];
mix(a);
for (uint32_t j = 0; j < 8; ++j)
mm[i + j] = a[j];
}
if (flag)
{ // Do a second pass to make all of the seed affect all of mm.
for (uint32_t i = 0; i < 256; i += 8)
{
for (uint32_t j = 0; j < 8; ++j)
a[j] += mm[i + j];
mix(a);
for (uint32_t j = 0; j < 8; ++j)
mm[i + j] = a[j];
}
}
isaac(); // Fill in the first set of results.
randCnt = 0; // Prepare to use the first set of results.
}
 
// Seed ISAAC with a given string.
// The string can be any size. The first 256 values will be used.
void seedIsaac(string seed, bool flag)
{
uint32_t seedLength = seed.length();
for (uint32_t i = 0; i < 256; i++)
mm[i] = 0;
for (uint32_t i = 0; i < 256; i++)
// In case seed has less than 256 elements
randRsl[i] = i > seedLength ? 0 : seed[i];
// Initialize ISAAC with seed
randInit(flag);
}
 
// Get a random 32-bit value 0..MAXINT
uint32_t getRandom32Bit()
{
uint32_t result = randRsl[randCnt];
++randCnt;
if (randCnt > 255)
{
isaac();
randCnt = 0;
}
return result;
}
 
// Get a random character in printable ASCII range
char getRandomChar()
{
return getRandom32Bit() % 95 + 32;
}
 
// Convert an ASCII string to a hexadecimal string.
string ascii2hex(string source)
{
uint32_t sourceLength = source.length();
stringstream ss;
for (uint32_t i = 0; i < sourceLength; i++)
ss << setfill ('0') << setw(2) << hex << (int) source[i];
return ss.str();
}
 
// XOR encrypt on random stream.
string vernam(string msg)
{
uint32_t msgLength = msg.length();
string destination = msg;
for (uint32_t i = 0; i < msgLength; i++)
destination[i] = getRandomChar() ^ msg[i];
return destination;
}
// Caesar-shift a character <shift> places: Generalized Vigenere
char caesar(CipherMode m, char ch, char shift, char modulo, char start)
{
int n;
if (m == DECRYPT)
shift = -shift;
n = (ch - start) + shift;
n %= modulo;
if (n < 0)
n += modulo;
return start + n;
}
// Vigenere mod 95 encryption & decryption.
string vigenere(string msg, CipherMode m)
{
uint32_t msgLength = msg.length();
string destination = msg;
// Caesar-shift message
for (uint32_t i = 0; i < msgLength; ++i)
destination[i] = caesar(m, msg[i], getRandomChar(), 95, ' ');
return destination;
}
int main()
{
// TASK globals
string msg = "a Top Secret secret";
string key = "this is my secret key";
string xorCipherText, modCipherText, xorPlainText, modPlainText;
// (1) Seed ISAAC with the key
seedIsaac(key, true);
// (2) Encryption
// (a) XOR (Vernam)
xorCipherText = vernam(msg);
// (b) MOD (Vigenere)
modCipherText = vigenere(msg, ENCRYPT);
// (3) Decryption
seedIsaac(key, true);
// (a) XOR (Vernam)
xorPlainText = vernam(xorCipherText);
// (b) MOD (Vigenere)
modPlainText = vigenere(modCipherText, DECRYPT);
// Program output
cout << "Message: " << msg << endl;
cout << "Key : " << key << endl;
cout << "XOR : " << ascii2hex(xorCipherText) << endl;
cout << "MOD : " << ascii2hex(modCipherText) << endl;
cout << "XOR dcr: " << xorPlainText << endl;
cout << "MOD dcr: " << modPlainText << endl;
}
</syntaxhighlight>
{{out}}
<pre>
Message: a Top Secret secret
Key : this is my secret key
XOR : 1c0636190b1260233b35125f1e1d0e2f4c5422
MOD : 734270227d36772a783b4f2a5f206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret
</pre>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defpackage isaac
(:use cl))
 
Line 720 ⟶ 1,148:
(terpri)
(format t "MOD dcr: ~a~%" cptx))))
(values))</langsyntaxhighlight>
{{out}}
<pre>ISAAC> (main-test)
Line 732 ⟶ 1,160:
=={{header|D}}==
Improved from the C# version. XOR with decryption check.
<langsyntaxhighlight lang="d">import std.algorithm: min;
import std.algorithm: copy;
import std.typetuple: TypeTuple;
Line 896 ⟶ 1,324:
 
writeln("Decrypted: ", decrypted.assumeUTF);
}</langsyntaxhighlight>
{{out}}
<pre>Message : a Top Secret secret
Line 905 ⟶ 1,333:
=={{header|Delphi}}==
Translation of Pascal.
<syntaxhighlight lang="delphi">
<lang Delphi>
{$apptype console}
PROGRAM RosettaIsaac;
Line 1,104 ⟶ 1,532:
Writeln('MOD : ',mctx);
END.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,116 ⟶ 1,544:
{{works with|node.js|0.10.32}}
{{trans|C#}}
<langsyntaxhighlight lang="ecmascript">randrsl = new Uint32Array(256);
randcnt = 0;
mm = new Uint32Array(256);
Line 1,231 ⟶ 1,659:
xptx = z[1];
console.log('xor: '+printable_hex(xctx))
console.log('decrypted: '+xptx)</langsyntaxhighlight>
{{out}}
<pre>
Line 1,239 ⟶ 1,667:
decrypted: a Top Secret secret
</pre>
=={{header|FreeBASICForth}}==
<syntaxhighlight lang="forth">
{{trans|C}}
Tested for VFX Forth and GForth 64bit in Linux
<lang freebasic>' version 03-11-2016
The code was based on and debugged v python
' compile with: fbc -s console
 
\ ******* Words for 32 bit fetching and storing *******
Dim Shared As UInteger<32> randrsl(256), randcnt
\ * Implement words for 32 bit fields (assuming 64 bit Forth) *
Static Shared As UInteger<32> mm(256)
\ *************************************************************
Static Shared As UInteger<32> aa, bb ,cc
 
: halves 4 * ; \ half a cell.
Sub ISAAC()
 
\ VFX Forth
Dim As UInteger<32> i, x, y
\ : h@ L@ ; : h! L! ; : h+! L+! ;
\ GFORTH
: h@ UL@ ; : h! L! ; : h+! DUP h@ ROT + SWAP h! ;
\ a 32 bit Forth
\ : h@ @ ; : h! ! ; : h+! +! ;
 
: half-array \ n <'name'> -- ; DOES> n -- a ;
cc = cc + 1
\ Use: 8 half-array test - creates an array of 8 32 bit elements.
bb = bb + cc
\ Does> 4 test - returns the address of the 4th element of test.
CREATE HERE SWAP halves DUP ALLOT ERASE
DOES> SWAP halves + ;
 
\ ***** Words to implement an isaac rng *****
For i = 0 To 256 -1
8 half-array ]init-state
x = mm(i)
Select Case (i Mod 4)
Case 0 : aa = aa Xor (aa Shl 13)
Case 1 : aa = aa Xor (aa Shr 6)
Case 2 : aa = aa Xor (aa Shl 2)
Case 3 : aa = aa Xor (aa Shr 16)
End Select
aa = mm((i+128) Mod 256) + aa
y = mm((x Shr 2) Mod 256) + aa + bb : mm(i) = y
bb = mm((y Shr 10) Mod 256) + x : randrsl(i) = bb
Next
 
: init+! \ ix-tgt ix-src -- ;
randcnt = 0
]init-state h@ SWAP ]init-state h+! ;
 
: init-right-xor! \ ix-tgt ix-src shift-bits -- ;
End Sub
SWAP ]init-state h@ SWAP RSHIFT SWAP ]init-state TUCK h@ XOR SWAP h! ;
 
: init-left-xor! \ ix-tgt ix-src shift-bits -- ;
SWAP ]init-state h@ SWAP LSHIFT SWAP ]init-state TUCK h@ XOR SWAP h! ;
 
: mix
#Macro mix(a, b, c, d, e, f, g, h)
0 1 11 init-left-xor! 3 0 init+! 1 2 init+!
1 2 2 init-right-xor! 4 1 init+! 2 3 init+!
2 3 8 init-left-xor! 5 2 init+! 3 4 init+!
3 4 16 init-right-xor! 6 3 init+! 4 5 init+!
4 5 10 init-left-xor! 7 4 init+! 5 6 init+!
5 6 4 init-right-xor! 0 5 init+! 6 7 init+!
6 7 8 init-left-xor! 1 6 init+! 7 0 init+!
7 0 9 init-right-xor! 2 7 init+! 0 1 init+! ;
 
\ State variables and arrays
a Xor= b Shl 11 : d += a : b += c
VARIABLE aa b Xor= cVARIABLE Shrbb 2 :VARIABLE ecc += b :VARIABLE c += drand-count
256 half-array ]mm
c Xor= d Shl 8 : f += c : d += e
256 half-array ]result
d Xor= e Shr 16 : g += d : e += f
e Xor= f Shl 10 : h += e : f += g
f Xor= g Shr 4 : a += f : g += h
g Xor= h Shl 8 : b += g : h += a
h Xor= a Shr 9 : c += h : a += b
 
\ Jump table of xts used in isaac-iteration
#EndMacro
: shift-xor0 aa DUP h@ DUP 13 LSHIFT XOR SWAP h! ; \ -- ;
: shift-xor1 aa DUP h@ DUP 6 RSHIFT XOR SWAP h! ; \ -- ;
: shift-xor2 aa DUP h@ DUP 2 LSHIFT XOR SWAP h! ; \ -- ;
: shift-xor3 aa DUP h@ DUP 16 RSHIFT XOR SWAP h! ; \ -- ;
 
HERE
Sub randinit(flag As Long)
' shift-xor0 , ' shift-xor1 , ' shift-xor2 , ' shift-xor3 ,
CONSTANT shift-xor-xts
 
: ]execute-shift-xorn \ ix -- ; Executes the xt in shift-xor-xts
Dim As Long i
CELLS shift-xor-xts + @ EXECUTE ;
Dim As UInteger<32> a = &H9e3779b9 '/* the golden ratio *
Dim As UInteger<32> b = &H9e3779b9
Dim As UInteger<32> c = &H9e3779b9
Dim As UInteger<32> d = &H9e3779b9
Dim As UInteger<32> e = &H9e3779b9
Dim As UInteger<32> f = &H9e3779b9
Dim As UInteger<32> g = &H9e3779b9
Dim As UInteger<32> h = &H9e3779b9
aa = 0 : bb = 0 : cc = 0
 
: isaac-iteration \ -- ;
For i = 0 To 3
1 cc h+! cc h@ mix(a, b, c, d, e, f, g,bb h)+!
256 0 DO \ Python code
Next
I ]mm h@ \ x = mm[i] Store mm[i] on the stack
 
ForI i3 =AND ]execute-shift-xorn 0 To 255 Step 8
\ Executes shift-xor0 .. 3 from shift-xor-xts above.
If flag = 1 Then
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)
 
aa DUP h@ I 128 XOR ]mm mix(a,h@ b,+ c,SWAP d,h! e, f,\ g,aa h= (mm[i^128] + aa)
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
End If
Next
 
DUP 2 RSHIFT 0xFF AND ]mm h@ aa h@ + bb h@ + \ mm[(x>>2) & 0xFF] + aa + bb)
If flag = 1 Then
DUP I ]mm h! For \ y = mm[i] = 0; Store in ]mm leave Toy 255on Stepthe 8stack
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)
 
10 RSHIFT 0xFF AND ]mm h@ + mix\ mm[(a,y>>10) b,& c,0xFF] d,+ e, f, g, hx)
DUP bb h! I ]result h! \ mm(result[i] )= a : mm(i +1)self.bb = b; :store mm(iin +2)bb =and c : mm(result[i +3) = d]
mm(i +4)= e : mm(i +5) = f : mm(i +6) = g : mm(i +7) = h
Next
End If
 
LOOP
ISAAC()
0 rand-count ! ;
randcnt = 0
 
256 half-array ]seed
End Sub
: zero-fill \ a ct -- ;
halves ERASE ;
 
: seed-mt 0 ]seed 256 zero-fill ;
' // Get a random 32-bit value 0..MAXINT
Function iRandom() As UInteger<32>
 
: string>seed \ a ct -- ;
Dim As UInteger<32> r = randrsl(randcnt)
seed-mt 256 MIN ]seed 0 ]seed ?DO COUNT I h! 4 +LOOP DROP ;
randcnt += 1
If randcnt > 255 Then
ISAAC()
randcnt = 0
End If
 
: mm-mt 0 ]mm 256 zero-fill ;
Return r
: init-vars 0 aa ! 0 bb ! 0 cc ! 256 rand-count ! ;
: res-mt 0 ]result 256 zero-fill ;
 
: base-init-state
End Function
8 ]init-state 0 ]init-state DO 0x9e3779b9 i h! 4 +LOOP
mix mix mix mix ;
 
: init>mm-ix \ ix -- ;
' // Get a random character in printable ASCII range
0 ]init-state SWAP ]mm 8 halves MOVE ;
Function iRandA() As UByte
 
: init>mm \ -- ;
Return iRandom() Mod 95 +32
256 0 DO mix I init>mm-ix 8 +LOOP
0 aa h! 0 bb h! 0 cc h! ;
 
: default-seed \ -- ;
End Function
base-init-state init>mm ;
 
: seed>init-state>mm
' // Seed ISAAC with a string
256 0 DO
Sub iSeed(seed As String, flag As Long)
8 0 DO I J + ]seed h@ I ]init-state h+! LOOP
mix
0 ]init-state I ]mm 8 halves MOVE
8 +LOOP ;
 
: init-mm-mix
Dim As ULong i, m = Len(seed) -1
256 0 DO
8 0 DO I J + ]mm h@ I ]init-state h+! LOOP
mix
I init>mm-ix
8 +LOOP ;
 
: string-seed \ str ct -- ;
For i = 0 To 255
string>seed base-init-state seed>init-state>mm
mm(i) = 0
init-mm-mix init-vars res-mt ;
Next
 
: random-next \ -- h ; 32 bit result
For i = 0 To 255
rand-count @ 255 > IF isaac-iteration 0 rand-count ! THEN
rand-count @ DUP ]result h@ SWAP 1+ rand-count ! ;
 
: rand-char If\ i-- >ch m Then;
random-next 95 MOD 32 + ;
randrsl(i) = 0
Else
randrsl(i) = seed[i]
End If
 
\ Encode, Decode and display.
Next
 
\ Working buffers
randinit(flag)
1024 CONSTANT buff-size
CREATE buff-in buff-size ALLOT
CREATE xor-out buff-size ALLOT
CREATE caesar-out buff-size ALLOT
 
: buff-count \ adr -- addr+cell count ; \ Prepares buff for TYPE
End Sub
DUP CELL + SWAP @ ;
 
: buff. buff-count TYPE ; \ addr -- ;
' // maximum length of message
'#define MAXMSG 4096
#Define _MOD_ 95 ' mod is FreeBASIC keyword
#Define _START_ 32 ' start is used as variable name
 
: byte>hexstr \ b -- str ct ; \ Generates a 2 character hex string.
' // cipher modes for Caesar
BASE @ SWAP HEX 0 <# # # #> ROT BASE ! ;
Enum ciphermode
mEncipher
mDecipher
mNone
End Enum
 
: buff-hex. \ addr --- ;
' // XOR cipher on random stream. Output: ASCII string
buff-count BOUNDS ?DO I C@ byte>hexstr TYPE LOOP ;
' no maximum lenght for input and output string
Function Vernam(msg As String) As String
 
: buff-empty 0 SWAP ! ; \ addr -- ; \ Empty the buffer. Sets length to zero.
Dim As ULong i
Dim As String v
 
: char-append \ ch adr -- ; \ Append ch to the buffer
For i = 0 To Len(msg) -1
tuck buff-count + C! 1 SWAP +! ;
v += Chr(iRandA() Xor msg[i])
Next
 
: buff-copy \ src dest -- ; \ Copy buffer to buffer
Return v
OVER @ CELL + MOVE ;
 
: buff-fill \ str ct buff -- ; \ Fill buffer with the contents of str ct
End Function
2DUP ! CELL + SWAP MOVE ;
 
\ ***** XOR encode/decode *****
' // Caesar-shift a printable character
: xor-byte \ b -- b' ;
Function Ceasar(m As ciphermode, ch As UByte, shift As UByte, modulo As UByte, _
rand-char XOR ;
start As UByte) As UByte
 
: xor-code \ str ct -- ;
' FreeBASIC Mod does not handle negative numbers correctly
xor-out buff-empty
' also there is litte problem with shift (declared UByte)
BOUNDS ?DO I C@ xor-byte xor-out char-append LOOP ;
' the IIF() statement helps with shift
' to avoid a negative n a 8 times modulo is added
' modulo * 8 get translateted by FreeBASIC to modulo shl 3
Dim As Long n = (ch - start) + IIf(m = mDecipher, -shift, shift) + modulo * 8
n = n Mod modulo
Return start + n
 
: init-rng" [CHAR] " WORD COUNT string-seed ;
End Function
 
: xor-code-with" \ str ct <key"> -- ; str ct points to the text to encode
' // Caesar-shift a string on a pseudo-random stream
\ Use: s" Message" encode-xor-key" This is the key."
Function CeasarStr(m As ciphermode, msg As String, modulo As UByte, _
\ Prints the encoded bytes in hex to the terminal.
start As UByte) As String
init-rng" xor-code ;
 
\ ***** Caesar encode/decode *****
Dim As Long i
DEFER op \ ' + for encode, ' - for decode in caesar-code-ch
Dim As String v
 
: encode ['] + IS op ; \ Add the offset while encoding.
For i = 0 To Len(msg) -1
: decode ['] - IS op ; \ Substract it to decode
v += Chr(Ceasar(m, msg[i], iRandA(), modulo, start))
Next
 
: caesar-code-ch \ c -- c' ;
Return v
rand-char op 32 - 95 MOD
BEGIN DUP 0< WHILE 95 + REPEAT 32 + ;
 
: caesar \ str ct -- ;
End Function
\ The direction of caesar-code is modified by the encode / decode words
\ eg. encode s" Message" caesar
\ decode s" DntP8hg" caesar
caesar-out buff-empty
BOUNDS ?DO I C@ caesar-code-ch caesar-out char-append LOOP ;
 
: caesar-with" \ str ct <key" -- ;
' ------=< MAIN >=------
\ The direction of caesar-code is modified by the encode / decode words
\ eg. encode s" Message" caesar-with" Key"
\ decode s" DntP8hg" caesar-with" Key"
init-rng" caesar ;
 
\ ***** Demonstrate the encode/decode working *****
Dim As Long n, l
Dim: Asmessage String msg = s" a Top Secret secret" ;
Dim As String key = "this is my secret key"
 
: out>in \ buff-out -- buff-in' count ;
Dim As String vctx, vptx
buff-in buff-copy buff-in buff-count ;
Dim As String cctx, cptx
 
: xor>in xor-out out>in ; \ -- buff-in' ct ;
l = Len(msg)
: caesar>in caesar-out out>in ; \ -- buff-in' ct ;
' // Encrypt: Vernam XOR
iSeed(key, 1)
vctx = Vernam(msg)
' // Encrypt: Caesar
cctx = CeasarStr(mEncipher, msg, _mod_, _start_)
' // Decrypt: Vernam XOR
iSeed(key, 1)
vptx = Vernam(vctx)
' // Decrypt: Caesar
cptx = CeasarStr(mDecipher, cctx, _mod_, _start_)
Print "message: "; msg
Print " key: "; key
Print " XOR: ";
' // Output Vernam ciphertext as a string of hex digits
For n = 0 To l -1
Print Hex(vctx[n], 2);
Next
Print
' // Output Vernam decrypted plaintext
Print "XOR dcr: "; vptx
' // Caesar
Print " MOD: ";
' // Output Caesar ciphertext as a string of hex digits
For n= 0 To l -1
Print Hex(cctx[n], 2);
Next
Print
' // Output Caesar decrypted plaintext
Print "MOD dcr: " ; cptx
 
: examples
' empty keyboard buffer
CR ." Raw message : " message TYPE
While InKey <> "" : Wend
CR ." First encode."
Print : Print "hit any key to end program"
s" this is my secret key" string-seed \ Set key
Sleep
message xor-code
End</lang>
CR ." XOR encoded as hex : " xor-out buff-hex.
message encode caesar
CR ." Caesar encoded as hex: " caesar-out buff-hex.
CR ." Now decode "
s" this is my secret key" string-seed \ Set key
xor>in xor-code
CR ." XOR decoded : " xor-out buff.
caesar>in decode caesar
CR ." Caesar decoded : " caesar-out buff. ;
</syntaxhighlight>
{{out}}
<pre>
<pre>message: a Top Secret secret
message key:xor-code-with" this is my secret key" ok
CR ." XOR encoded as hex : " xor-out buff-hex.
XOR: 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR encoded as hex : 1C0636190B1260233B35125F1E1D0E2F4C5422 ok
XOR dcr: a Top Secret secret
ok
MOD: 734270227D36772A783B4F2A5F206266236978
message encode caesar ok
MOD dcr: a Top Secret secret</pre>
CR ." Caesar encoded as hex: " caesar-out buff-hex.
Caesar encoded as hex: 734270227D36772A783B4F2A5F206266236978 ok
ok
ok
xor>in xor-code-with" this is my secret key" ok
CR ." XOR decoded : " xor-out buff.
XOR decoded : a Top Secret secret ok
ok
caesar>in decode caesar ok
CR ." Caesar decoded : " caesar-out buff.
Caesar decoded : a Top Secret secret ok
ok
examples
Raw message : a Top Secret secret
First encode.
XOR encoded as hex : 1C0636190B1260233B35125F1E1D0E2F4C5422
Caesar encoded as hex: 734270227D36772A783B4F2A5F206266236978
Now decode
XOR decoded : a Top Secret secret
Caesar decoded : a Top Secret secret ok
</pre>
 
=={{header|Go}}==
XOR version
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,608 ⟶ 2,043:
}
return fmt.Sprintf("%X", b)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,617 ⟶ 2,052:
 
=={{header|Haskell}}==
<langsyntaxhighlight Haskelllang="haskell">import Data.Array (Array, (!), (//), array, elems)
import Data.BitsWord (Word, Word32)
import Data.CharBits (shift, xor)
import Data.WordChar (toUpper)
import Data.List (unfoldr)
import Numeric (showHex)
 
type IArray = Array Word32 Word32
Line 1,629 ⟶ 2,064:
{ randrsl :: IArray
, randcnt :: Word32
, mm :: IArray
, aa :: Word32
, bb :: Word32
, cc :: Word32
}
 
instance Show IsaacState where
show (IState _ cnt _ a b c) = show cnt ++ " " ++ show a ++ " " ++ show b ++ " " ++ show c
show cnt ++ " " ++ show a ++ " " ++ show b ++ " " ++ show c
 
toHex :: Char -> String
Line 1,657 ⟶ 2,093:
mix set = foldl aux set [11, -2, 8, -16, 10, -4, 8, -9]
where
aux [a, b, c, d, e, f, g, h] x = [b + c, c, d + a'a_, e, f, g, h, a'a_]
where a' = a `xor` (b `shift` x)
a_ = a `xor` (b `shift` x)
 
-- Generate the next 256 words.
isaac :: IsaacState -> IsaacState
isaac (IState rsl _ m a b c) = IState rsl'rsl_ 0 m'm_ a'a_ b'b_ c'c_
where
c'c_ = c + 1
(rsl_, m_, a_, b_) =
(rsl', m', a', b') = foldl aux (rsl, m, a, b) $ zip [0..255] $ cycle [13, -6, 2, -16]
foldl aux (rsl, m, a, b) (i,$ s)zip =[0 (rsl'.. 255] $ cycle [13, m'-6, a'2, b')-16]
aux (rsl, wherem, xa, b) (i, s) = m(rsl_, !m_, ia_, b_)
where
a' = (a `xor` (a `shift` s)) + m ! ((i + 128) `mod` 256)
y x = a' + b + m ! ((x `shift` (-2)) `mod` 256)i
a_ = (a `xor` m'(a `shift` s)) =+ m //! [((i,y + 128) `mod` 256)]
y = a_ + b' = x + m' ! ((yx `shift` (-102)) `mod` 256)
rsl'm_ = rslm // [(i,b' y)]
b_ = x + m_ ! ((y `shift` (-10)) `mod` 256)
rsl_ = rsl // [(i, b_)]
 
-- Given a seed value in randrsl, initialize/mixup the state.
randinit :: IsaacState -> Bool -> IsaacState
randinit state flag = isaac (IState randrsl'randrsl_ 0 m 0 0 0)
where
firstSet = (iterate mix $ (replicate 8 golden) !! 4
iter _ _ [] = []
iter flag set rsl =
let (rslH, rslT) = splitAt 8 rsl
set' set_ = mix $ if flag
mix then zipWith (+) set rslH$
if else setflag
in set' ++ iter flag then zipWith (+) set' rslTrslH
else set
randrsl' = randrsl state
in set_ ++ iter flag set_ rslT
firstPass = iter flag firstSet $ elems randrsl'
randrsl_ = randrsl state
set' = drop (256 - 8) firstPass
secondPassfirstPass = ifiter flag firstSet $ elems randrsl_
set_ = drop (256 - then iter True set'8) firstPass
secondPass =
else firstPass
if flag
m = array (0, 255) $ zip [0..] secondPass
then iter True set_ firstPass
else firstPass
m = array (0, 255) $ zip [0 ..] secondPass
 
-- Given a string seed, optionaly use it to generate a new state.
seed :: String -> Bool -> IsaacState
seed key flag =
let m = array (0, 255) $ zip [0 .. 255] $ repeat 0
rsl = m // zip [0 ..] (map toNum key)
state = IState rsl 0 m 0 0 0
in randinit state flag
Line 1,705 ⟶ 2,147:
random :: IsaacState -> (Word32, IsaacState)
random state@(IState rsl cnt m a b c) =
let r = rsl ! cnt
state'state_ = if cnt + 1 > 255
if cnt + 1 > then isaac $ IState rsl 0 m a b c255
then isaac else$ IState rsl (cnt + 1)0 m a b c
else IState rsl (cnt + 1) m a b c
in (r, state')
in (r, state_)
 
-- Produce a stream of random words from the given state.
Line 1,719 ⟶ 2,162:
randA :: IsaacState -> (Char, IsaacState)
randA state =
let (r, state'state_) = random state
in (toEnum $ fromIntegral $ (r `mod` 95) + 32, state'state_)
 
-- Produce a stream of printable characters from the given state.
Line 1,728 ⟶ 2,171:
-- Vernam encode/decode a string with the given state.
vernam :: IsaacState -> String -> String
vernam state msg = map toChar $ zipWith xor msg'msg_ randAs'randAs_
where
msg'msg_ = map toNum msg
randAs'randAs_ = map toNum $ randAs state
 
main :: IO ()
main = do
let msg = "a Top Secret secret"
key = "this is my secret key"
st = seed key True
ver = vernam st msg
unver = vernam st ver
putStrLn $ "Message: " ++ msg
putStrLn $ "Key : " ++ key
putStrLn $ "XOR : " ++ hexify ver
putStrLn $ "XOR dcr: " ++ unver</langsyntaxhighlight>
{{out}}
<pre>Message: a Top Secret secret
Line 1,757 ⟶ 2,200:
It is possible in Haxe to create your own 32bit unsigned type,
but that is outside this exercise.
<syntaxhighlight lang="haxe">
<lang Haxe>
package src ;
import haxe.Int32;
Line 1,919 ⟶ 2,362:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,929 ⟶ 2,372:
MOD dcr: a Top Secret secret
</pre>
 
=={{header|J}}==
{{trans|C}}
In this draft, only the XOR implementation (vernam) is implemented:
<syntaxhighlight lang="j">NB. bitwise logic on 32 bit unsigned values
ub4=: (#.33{.1)&|
xor=: ub4@(2b10110 b.)
shl=: ub4@(33 b.~)
add=: ub4@+
 
isaac=: {{
cc=: cc add 1
bb=: bb add cc
for_i.i.256 do.
aa=. aa xor aa shl 13 _6 2 _16{~4|i
X=. i{mm
aa=. aa add mm{~ 256| i+128
y=. aa add bb add mm{~ 256| X shl _2
randrsl=: randrsl i}~ bb=. X add mm{~ 256| y shl _10
end.
randcnt=: 0
}}
mix=: {{
b=: b add c [ d=: d add a=: a xor b shl 11
c=: c add d [ e=: e add b=: b xor c shl _2
d=: d add e [ f=: f add c=: c xor d shl 8
e=: e add f [ g=: g add d=: d xor e shl _16
f=: f add g [ h=: h add e=: e xor f shl 10
g=: g add h [ a=: a add f=: f xor g shl _4
h=: h add a [ b=: b add g=: g xor h shl 8
a=: a add b [ c=: c add h=: h xor a shl _9
}}
 
randinit=: {{
aa=: bb=: cc=: 0
a=: b=: c=: d=: e=: f=: g=: h=: 16b9e3779b9
mix^:4''
if. y do.
for_i. _8]\i.256 do.
mix 'a b c d e f g h'=: (a,b,c,d,e,f,g,h) add i{randrsl
mm=: mm i}~ a,b,c,d,e,f,g,h
end.
for_i. _8]\i.256 do.
mix 'a b c d e f g h'=: (a,b,c,d,e,f,g,h) add i{mm
mm=: mm i}~ a,b,c,d,e,f,g,h
end.
else.
for_i. _8]\i.256 do.
mix ''
mm=: mm i}~ a,b,c,d,e,f,g,h
end.
end.
isaac''
}}
 
iRandom=: {{
r=. randcnt { randrsl
if. 255 < randcnt=: randcnt+1 do. isaac'' end.
r
}}
 
iRandA=: {{ 7 u: 32+95|iRandom^:(1+i.y)'' }}
 
iSeed=: {{ NB. y: seed, x: flag
0 iSeed y
:
mm=: 256#0
randrsl=: 256{.3 u: y
randinit x
}}
 
vernam=: {{ y xor&.(3&u:) iRandA #y }}</syntaxhighlight>
 
Task example:<syntaxhighlight lang="j"> ,hfd 3 u:E=: vernam 'a Top Secret secret' [ 1 iSeed 'this is my secret key'
1c0636190b1260233b35125f1e1d0e2f4c5422
vernam E [ 1 iSeed 'this is my secret key'
a Top Secret secret</syntaxhighlight>
 
=={{header|Java}}==
Line 1,938 ⟶ 2,459:
This implementation extends the java.util.Random class, so it inherits methods that generate booleans, floats, doubles and longs, and can also generate numbers with Gaussian and uniform distribution. It can also be plugged in to standard library methods that receive a Random instance as a source of randomness. The toHexString() and main() methods are for demo purposes only and can be removed without changing main functionality.
 
<langsyntaxhighlight Javalang="java">import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Random;
Line 2,162 ⟶ 2,683:
System.out.printf("MOD dcr: %s\n", caesarDecrypted);
}
}</langsyntaxhighlight>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">
"""
Julia translation of code from the following:
------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------
"""
# maximum length of message here is set to 4096
const MAXMSG = 4096
 
# cipher modes for encryption versus decryption modes
@enum CipherMode mEncipher mDecipher mNone
 
# external results
mutable struct IState
randrsl::Array{UInt32, 1}
randcnt::UInt32
mm::Array{UInt32, 1}
aa::UInt32
bb::UInt32
cc::UInt32
function IState()
this = new()
this.randrsl = zeros(UInt32, 256)
this.randcnt = UInt32(0)
this.mm = zeros(UInt32, 256)
this.aa = this.bb = this.cc = UInt32(0)
this
end
end
 
"""
isaac
Randomize the pool
"""
function isaac(istate)
istate.cc += 1 # cc gets incremented once per 256 results
istate.bb += istate.cc # then combined with bb
 
for (j, c) in enumerate(istate.mm) # Julia NB: indexing ahead so use i for c indexing
i = j - 1
xmod4 = i % 4
if(xmod4 == 0)
istate.aa ⊻= istate.aa << 13
elseif(xmod4 == 1)
istate.aa ⊻= istate.aa >> 6
elseif(xmod4 == 2)
istate.aa ⊻= istate.aa << 2
else
istate.aa ⊻= istate.aa >> 16
end
istate.aa += istate.mm[(i + 128) % 256 + 1]
y = istate.mm[(c >> 2) % 256 + 1] + istate.aa + istate.bb
istate.mm[j] = y
istate.bb = istate.mm[(y >> 10) % 256 + 1] + c
istate.randrsl[j] = istate.bb
end
# not in original readable.c
istate.randcnt = 0
end
 
 
"""
mix
Mix the bytes in a reversible way.
"""
function mix(arr) # Julia NB: use E for e in c code here
(a,b,c,d,E,f,g,h) = arr
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;
(a,b,c,d,E,f,g,h)
end
 
 
"""
randinit
Make a random UInt32 array.
If flag is true, use the contents of randrsl[] to initialize mm[].
"""
function randinit(istate, flag::Bool)
istate.aa = istate.bb = istate.cc = 0
mixer = Array{UInt32,1}(8)
fill!(mixer, 0x9e3779b9) # the golden ratio
for i in 1:4 # scramble it
mixer = mix(mixer)
end
for i in 0:8:255 # fill in mm[] with messy stuff
if(flag) # use all the information in the seed
mixer = [mixer[j] + istate.randrsl[i+j] for j in 1:8]
end
mixer = mix(mixer)
istate.mm[i+1:i+8] .= mixer
end
if(flag) # do a second pass to seed all of mm
for i in 0:8:255
mixer = [mixer[j] + istate.mm[i+j] for j in 1:8]
mixer = mix(mixer)
istate.mm[i+1:i+8] .= mixer
end
end
isaac(istate) # fill in the first set of results
istate.randcnt = 0
end
 
 
"""
Get a random 32-bit value 0..MAXINT
"""
function irandom(istate)
retval::UInt32 = istate.randrsl[istate.randcnt+1]
istate.randcnt += 1
if(istate.randcnt > 255)
isaac(istate)
istate.randcnt = 0
end
retval
end
 
 
"""
Get a random character in printable ASCII range
"""
iranda(istate) = UInt8(irandom(istate) % 95 + 32)
 
 
"""
Do XOR cipher on random stream.
Output: UInt8 array
"""
vernam(istate, msg) = [UInt8(iranda(istate) ⊻ c) for c in msg]
 
 
"""
Seed ISAAC with a string
"""
function iseed(istate, seed, flag)
fill!(istate.mm, 0)
fill!(istate.randrsl, 0)
len = min(length(seed), length(istate.randrsl))
istate.randrsl[1:len] .= seed[1:len]
randinit(istate, flag) # initialize ISAAC with seed
end
 
 
tohexstring(arr::Array{UInt8,1}) = join([hex(i, 2) for i in arr])
 
 
function test(istate, msg, key)
# Vernam ciphertext & plaintext
vctx = zeros(UInt8, MAXMSG)
vptx = zeros(UInt8, MAXMSG)
# Encrypt: Vernam XOR
iseed(istate, Vector{UInt8}(key), true)
vctx = vernam(istate, Vector{UInt8}(msg))
# Decrypt: Vernam XOR
iseed(istate, Vector{UInt8}(key), true)
vptx = vernam(istate, vctx)
# Program output
println("Message: $msg")
println("Key : $key")
println("XOR : $(tohexstring(vctx))")
# Output Vernam decrypted plaintext
println("XOR dcr: $(join(map(c -> Char(c), vptx)))")
0
end
 
 
"""
Test the above.
"""
const msg = "a Top Secret secret"
const key = "this is my secret key"
test(IState(), msg, key)
</syntaxhighlight>
{{output}}<pre>
Message: a Top Secret secret
Key : this is my secret key
XOR : 1c0636190b1260233b35125f1e1d0e2f4c5422
XOR dcr: a Top Secret secret
</pre>
 
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
/* external results */
Line 2,328 ⟶ 3,039:
println("MOD : ${cctx.toHexByteString()}")
println("MOD dcr : $cptx")
}</langsyntaxhighlight>
 
{{out}}
Line 2,340 ⟶ 3,051:
</pre>
 
=={{header|PascalLua}}==
<syntaxhighlight lang="lua">#!/usr/bin/env lua
Free Pascal. A fully functional and complete reference solution of the task.
-- ISAAC - Lua 5.3
<lang Pascal>
PROGRAM RosettaIsaac;
USES StrUtils;
 
-- External Results
TYPE iMode = (iEncrypt,iDecrypt);
local randRsl = {};
// TASK globals
local randCnt = 0;
VAR msg : STRING = 'a Top Secret secret';
key : STRING = 'this is my secret key';
xctx: STRING = ''; // XOR ciphertext
mctx: STRING = ''; // MOD ciphertext
xptx: STRING = ''; // XOR decryption (plaintext)
mptx: STRING = ''; // MOD decryption (plaintext)
mode: iMode = iEncrypt;
// ISAAC globals
// external results
VAR randrsl: ARRAY[0..256] OF CARDINAL;
randcnt: cardinal;
// internal state
VAR mm: ARRAY[0..256] OF CARDINAL;
aa: CARDINAL=0; bb: CARDINAL=0; cc: CARDINAL=0;
 
-- Internal State
local mm = {};
local aa,bb,cc = 0,0,0;
 
-- Cap to maintain 32 bit maths
local cap = 0x100000000;
 
-- CipherMode
local ENCRYPT = 1;
local DECRYPT = 2;
 
function isaac()
 
cc = ( cc + 1 ) % cap; -- cc just gets incremented once per 256 results
bb = ( bb + cc ) % cap; -- then combined with bb
 
for i = 0,255 do
local x = mm[i];
local y;
local imod = i % 4;
if imod == 0 then aa = aa ~ (aa << 13);
elseif imod == 1 then aa = aa ~ (aa >> 6);
elseif imod == 2 then aa = aa ~ (aa << 2);
elseif imod == 3 then aa = aa ~ (aa >> 16);
end
aa = ( mm[(i+128)%256] + aa ) % cap;
y = ( mm[(x>>2) % 256] + aa + bb ) % cap;
mm[i] = y;
bb = ( mm[(y>>10)%256] + x ) % cap;
randRsl[i] = bb;
end
 
randCnt = 0; -- Prepare to use the first set of results.
 
end
 
function mix(a)
a[0] = ( a[0] ~ ( a[1] << 11 ) ) % cap; a[3] = ( a[3] + a[0] ) % cap; a[1] = ( a[1] + a[2] ) % cap;
a[1] = ( a[1] ~ ( a[2] >> 2 ) ) % cap; a[4] = ( a[4] + a[1] ) % cap; a[2] = ( a[2] + a[3] ) % cap;
a[2] = ( a[2] ~ ( a[3] << 8 ) ) % cap; a[5] = ( a[5] + a[2] ) % cap; a[3] = ( a[3] + a[4] ) % cap;
a[3] = ( a[3] ~ ( a[4] >> 16 ) ) % cap; a[6] = ( a[6] + a[3] ) % cap; a[4] = ( a[4] + a[5] ) % cap;
a[4] = ( a[4] ~ ( a[5] << 10 ) ) % cap; a[7] = ( a[7] + a[4] ) % cap; a[5] = ( a[5] + a[6] ) % cap;
a[5] = ( a[5] ~ ( a[6] >> 4 ) ) % cap; a[0] = ( a[0] + a[5] ) % cap; a[6] = ( a[6] + a[7] ) % cap;
a[6] = ( a[6] ~ ( a[7] << 8 ) ) % cap; a[1] = ( a[1] + a[6] ) % cap; a[7] = ( a[7] + a[0] ) % cap;
a[7] = ( a[7] ~ ( a[0] >> 9 ) ) % cap; a[2] = ( a[2] + a[7] ) % cap; a[0] = ( a[0] + a[1] ) % cap;
end
 
function randInit(flag)
 
-- The golden ratio in 32 bit
-- math.floor((((math.sqrt(5)+1)/2)%1)*2^32) == 2654435769 == 0x9e3779b9
local a = { [0] = 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, 0x9e3779b9, };
 
aa,bb,cc = 0,0,0;
 
for i = 1,4 do mix(a) end -- Scramble it.
 
for i = 0,255,8 do -- Fill in mm[] with messy stuff.
if flag then -- Use all the information in the seed.
for j = 0,7 do
a[j] = ( a[j] + randRsl[i+j] ) % cap;
end
end
mix(a);
for j = 0,7 do
mm[i+j] = a[j];
end
end
 
if flag then
-- Do a second pass to make all of the seed affect all of mm.
for i = 0,255,8 do
for j = 0,7 do
a[j] = ( a[j] + mm[i+j] ) % cap;
end
mix(a);
for j = 0,7 do
mm[i+j] = a[j];
end
end
end
 
isaac(); -- Fill in the first set of results.
randCnt = 0; -- Prepare to use the first set of results.
 
end
 
-- Seed ISAAC with a given string.
-- The string can be any size. The first 256 values will be used.
function seedIsaac(seed,flag)
local seedLength = #seed;
for i = 0,255 do mm[i] = 0; end
for i = 0,255 do randRsl[i] = seed:byte(i+1,i+1) or 0; end
randInit(flag);
end
 
-- Get a random 32-bit value 0..MAXINT
function getRandom32Bit()
local result = randRsl[randCnt];
randCnt = randCnt + 1;
if randCnt > 255 then
isaac();
randCnt = 0;
end
return result;
end
 
-- Get a random character in printable ASCII range
function getRandomChar()
return getRandom32Bit() % 95 + 32;
end
 
-- Convert an ASCII string to a hexadecimal string.
function ascii2hex(source)
local ss = "";
for i = 1,#source do
ss = ss..string.format("%02X",source:byte(i,i));
end
return ss
end
 
-- XOR encrypt on random stream.
function vernam(msg)
local msgLength = #msg;
local destination = {};
for i = 1, msgLength do
destination[i] = string.char(getRandomChar() ~ msg:byte(i,i));
end
return table.concat(destination);
end
 
-- Caesar-shift a character <shift> places: Generalized Vigenere
function caesar(m, ch, shift, modulo, start)
local n
local si = 1
if m == DECRYPT then shift = shift*-1 ; end
n = (ch - start) + shift;
if n < 0 then si,n = -1,n*-1 ; end
n = ( n % modulo ) * si;
if n < 0 then n = n + modulo ; end
return start + n;
end
 
-- Vigenere mod 95 encryption & decryption.
function vigenere(msg,m)
local msgLength = #msg;
local destination = {};
for i = 1,msgLength do
destination[i] = string.char( caesar(m, msg:byte(i,i), getRandomChar(), 95, 32) );
end
return table.concat(destination);
end
 
function main()
local msg = "a Top Secret secret";
local key = "this is my secret key";
local xorCipherText, modCipherText, xorPlainText, modPlainText;
 
-- (1) Seed ISAAC with the key
seedIsaac(key, true);
-- (2) Encryption
-- (a) XOR (Vernam)
xorCipherText = vernam(msg);
-- (b) MOD (Vigenere)
modCipherText = vigenere(msg, ENCRYPT);
-- (3) Decryption
seedIsaac(key, true);
-- (a) XOR (Vernam)
xorPlainText = vernam(xorCipherText);
-- (b) MOD (Vigenere)
modPlainText = vigenere(modCipherText, DECRYPT);
-- Program output
print("Message: " .. msg);
print("Key : " .. key);
print("XOR : " .. ascii2hex(xorCipherText));
print("XOR dcr: " .. xorPlainText);
print("MOD : " .. ascii2hex(modCipherText));
print("MOD dcr: " .. modPlainText);
 
end
 
main()
</syntaxhighlight>
{{out}}
<pre>
Message: a Top Secret secret
Key : this is my secret key
XOR : 1c0636190b1260233b35125f1e1d0e2f4c5422
MOD : 734270227d36772a783b4f2a5f206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret
</pre>
 
=={{header|Modula-2}}==
{{trans|Pascal}}
{{works with|ADW Modula-2|any (Compile with the linker option ''Console Application'').}}
I changed the identifiers to clearer ones and I changed the variables <code>a</code>, <code>b</code>, ..., <code>h</code> to an array, because they made my blood boil.
<syntaxhighlight lang="modula2">
MODULE RosettaIsaac;
 
FROM Strings IMPORT
Length, Assign, Append;
FROM STextIO IMPORT
WriteString, WriteLn;
FROM Conversions IMPORT
CardBaseToStr;
 
CONST
MaxStrLength = 256;
 
TYPE
TMode = (iEncrypt, iDecrypt);
TString = ARRAY [0 .. MaxStrLength - 1] OF CHAR;
THexString = ARRAY [0 .. 2 * MaxStrLength - 1] OF CHAR;
TCardIndexedFrom0To7 = ARRAY [0 .. 7] OF CARDINAL;
 
VAR
(* TASK globals *)
Msg: TString = 'a Top Secret secret';
Key: TString = 'this is my secret key';
XorCipherText: TString = '';
ModCipherText: TString = '';
XorPlainText: TString = '';
ModPlainText: TString = '';
HexText: THexString;
 
(* ISAAC globals *)
(* external results *)
RandRsl: ARRAY [0 .. 255] OF CARDINAL;
RandCnt: CARDINAL;
 
(* 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
ccCC := ccCC + 1; //(* ccCC just gets incremented once per 256 results *)
bbBB := bbBB + ccCC; //(* then combined with bbBB *)
FOR I := 0 TO 255 DO
 
FOR i X := 0 TO 255 DO BEGINMM[I];
xCASE :=(I mm[i];MOD 4) OF
CASE 0: AA := AA BXOR (iAA modSHL 413); OF|
0 1: aaAA := aaAA xorBXOR (aaAA shlSHR 136); |
1 2: aaAA := aaAA xorBXOR (aaAA shrSHL 62); |
2 3: aaAA := aaAA xorBXOR (aaAA shlSHR 216);
ELSE
3: aa := aa xor (aa shr 16);
END;
aaAA := mmMM[(iI + 128) modMOD 256] + aaAA;
y Y := mmMM[(xX shrSHR 2) modMOD 256] + aaAA + bbBB;
mmMM[iI] := yY;
bbBB := mmMM[(yY shrSHR 10) modMOD 256] + xX;
randrslRandRsl[iI] := bbBB;
END; (* FOR *)
RandCnt := 0; (* Prepare to use the first set of results. *)
// this reset was not in the original readable.c
END Isaac;
randcnt:=0; // prepare to use the first set of results
END; {Isaac}
 
PROCEDURE Mix(VAR A: TCardIndexedFrom0To7);
BEGIN
A[0] := A[0] BXOR A[1] SHL 11; A[3] := A[3] + A[0]; A[1] := A[1] + A[2];
A[1] := A[1] BXOR A[2] SHR 2; A[4] := A[4] + A[1]; A[2] := A[2] + A[3];
A[2] := A[2] BXOR A[3] SHL 8; A[5] := A[5] + A[2]; A[3] := A[3] + A[4];
A[3] := A[3] BXOR A[4] SHR 16; A[6] := A[6] + A[3]; A[4] := A[4] + A[5];
A[4] := A[4] BXOR A[5] SHL 10; A[7] := A[7] + A[4]; A[5] := A[5] + A[6];
A[5] := A[5] BXOR A[6] SHR 4; A[0] := A[0] + A[5]; A[6] := A[6] + A[7];
A[6] := A[6] BXOR A[7] SHL 8; A[1] := A[1] + A[6]; A[7] := A[7] + A[0];
A[7] := A[7] BXOR A[0] SHR 9; A[2] := A[2] + A[7]; A[0] := A[0] + A[1];
END Mix;
 
PROCEDURE RandInit(Flag: BOOLEAN);
// if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
VAR
PROCEDURE mix(VAR a,b,c,d,e,f,g,h: CARDINAL);
I, J: CARDINAL;
A: TCardIndexedFrom0To7;
BEGIN
a AA := a xor b shl 110; dBB :=d+a 0; bCC :=b+c 0;
A[0] := 2654435769; (* $9e3779b9: the golden ratio *)
b := b xor c shr 2; e:=e+b; c:=c+d;
FOR J := 1 TO 7 DO
c := c xor d shl 8; f:=f+c; d:=d+e;
d := d xor eA[J] shr 16; g:=g+d; e:=e+fA[0];
END;
e := e xor f shl 10; h:=h+e; f:=f+g;
f := f xor g shr 4; a:=a+f; g:=g+h;
g := g xor h shl 8; b:=b+g; h:=h+a;
h := h xor a shr 9; c:=c+h; a:=a+b;
END; {mix}
 
FOR I := 0 TO 3 DO (* Scramble it *)
Mix(A);
END;
FOR I := 0 TO 255 BY 8 DO (* Fill in MM[] with messy stuff. *)
IF Flag THEN (* Use all the information in the seed. *)
FOR J := 0 TO 7 DO
A[J] := A[J] + RandRsl[I + J];
END;
END;
Mix(A);
FOR J := 0 TO 7 DO
MM[I + J] := A[J];
END;
END; (* FOR I*)
 
IF Flag THEN
PROCEDURE iRandInit(flag: BOOLEAN);
(* Do a second pass to make all of the Seed affect all of MM *)
VAR i,a,b,c,d,e,f,g,h: CARDINAL;
FOR I := 0 TO 255 BY 8 DO
FOR J := 0 TO 7 DO
A[J] := A[J] + MM[I + J];
END;
Mix(A);
FOR J := 0 TO 7 DO
MM[I + J] := A[J];
END;
END; (* FOR I *)
END;
Isaac(); (* Fill in the first set of results *)
RandCnt := 0; (* Prepare to use the first set of results *)
END RandInit;
 
(* Seed ISAAC with a given string.
The string can be any size. The first 256 values will be used. *)
PROCEDURE SeedIsaac(Seed: ARRAY OF CHAR; Flag: BOOLEAN);
VAR
I, SeedLength: CARDINAL;
BEGIN
FOR I aa:=0; bb:=0; cc:=0;TO 255 DO
MM[I] := 0;
a:=$9e3779b9; // the golden ratio
END;
SeedLength := Length(Seed);
b:=a; c:=a; d:=a; e:=a; f:=a; g:=a; h:=a;
FOR I := 0 TO 255 DO
(* In case seed has less than 256 elements *)
IF I > SeedLength THEN
RandRsl[I] := 0
ELSE
(* Modula-2 strings are 0-based (at least, in this case). *)
RandRsl[I] := ORD(Seed[I]);
END;
END;
(* Initialize ISAAC with seed. *)
RandInit(Flag);
END SeedIsaac;
 
(* Get a random 32-bit value 0..MAXINT *)
FOR i := 0 TO 3 DO // scramble it
PROCEDURE GetRandom32Bit(): CARDINAL;
mix(a,b,c,d,e,f,g,h);
VAR
iResult:=0 CARDINAL;
BEGIN
REPEAT // fill in mm[] with messy stuff
Result := RandRsl[RandCnt];
IF flag THEN BEGIN // use all the information in the seed
INC(RandCnt);
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
IF RandCnt > 255 THEN
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
Isaac();
RandCnt := 0;
END;
RETURN Result;
END GetRandom32Bit;
 
(* Get a random character in printable ASCII range. *)
PROCEDURE GetRandomChar(): SHORTCARD;
BEGIN
RETURN GetRandom32Bit() MOD 95 + 32;
END GetRandomChar;
 
(* Convert an ASCII string to a hexadecimal string. *)
PROCEDURE ASCII2Hex(Source: ARRAY OF CHAR; VAR OUT Destination: ARRAY OF CHAR);
VAR
I: CARDINAL;
NumbHex: ARRAY [0 .. 1] OF CHAR;
BEGIN
Assign('', Destination);
FOR I := 0 TO Length(Source) - 1 DO
CardBaseToStr(ORD(Source[I]), 16, NumbHex);
IF Length(NumbHex) <= 1 THEN
Append('0', Destination);
END;
Append(NumbHex, Destination);
END;
mix(a,b,c,d,e,f,g,h);
END ASCII2Hex;
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;
 
(* XOR encrypt on random stream. *)
IF (flag) THEN BEGIN
PROCEDURE Vernam(Msg: ARRAY OF CHAR; VAR OUT Destination: ARRAY OF CHAR);
// do a second pass to make all of the seed affect all of mm
VAR
i:=0;
I: REPEATCARDINAL;
OrdMsgI: SHORTCARD;
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
BEGIN
e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
mixAssign(aMsg,b,c,d,e,f,g,h Destination);
FOR I := 0 TO Length(Msg) - 1 DO
mm[i ]:=a; mm[i+1]:=b; mm[i+2]:=c; mm[i+3]:=d;
OrdMsgI := ORD(Msg[I]);
mm[i+4]:=e; mm[i+5]:=f; mm[i+6]:=g; mm[i+7]:=h;
Destination[I] := CHR(GetRandomChar() BXOR OrdMsgI);
i+=8;
END;
UNTIL i>255;
END Vernam;
END;
isaac(); // fill in the first set of results
randcnt:=0; // prepare to use the first set of results
END; {randinit}
 
(* Get position of the letter in chosen alphabet *)
PROCEDURE LetterNum(Letter, Start: CHAR): SHORTCARD;
BEGIN
RETURN ORD(Letter) - ORD(Start);
END LetterNum;
 
(* Caesar-shift a character <Shift> places: Generalized Vigenere *)
{ Seed ISAAC with a given string.
PROCEDURE Caesar(M: TMode; Ch: CHAR; Shift, Modulo: INTEGER; Start: CHAR): CHAR;
The string can be any size. The first 256 values will be used.}
VAR
PROCEDURE iSeed(seed: STRING; flag: BOOLEAN);
N, IntOrdStart: INTEGER;
VAR i,m: CARDINAL;
BEGIN
IF M = iDecrypt THEN
FOR i:= 0 TO 255 DO mm[i]:=0;
Shift := -Shift;
m := Length(seed)-1;
END;
FOR i:= 0 TO 255 DO BEGIN
N := LetterNum(Ch, Start);
// in case seed has less than 256 elements
N := N + Shift;
IF i>m THEN randrsl[i]:=0
N := N MOD Modulo;
// Pascal strings are 1-based
IF N < 0 THEN
ELSE randrsl[i]:=ord(seed[i+1]);
N := N + Modulo;
END;
END;
// initialize ISAAC with seed
IntOrdStart := ORD(Start);
iRandInit(flag);
RETURN CHR(IntOrdStart + N);
END; {iSeed}
END Caesar;
 
(* Vigenere mod 95 encryption & decryption. *)
PROCEDURE Vigenere(Msg: ARRAY OF CHAR; M: TMode; VAR OUT Destination: ARRAY OF CHAR);
VAR
I: CARDINAL;
BEGIN
Assign(Msg, Destination);
FOR I := 0 TO Length(Msg) - 1 DO
Destination[I] := Caesar(M, Msg[I], GetRandomChar(), 95, ' ');
END;
END Vigenere;
 
{ Get a random 32-bit value 0..MAXINT }
FUNCTION iRandom : Cardinal;
BEGIN
(* (1) Seed ISAAC with the key *)
iRandom := randrsl[randcnt];
SeedIsaac(Key, TRUE);
inc(randcnt);
(* (2) Encryption *)
IF (randcnt >255) THEN BEGIN
(* (a) XOR (Vernam) *)
Isaac();
Vernam(Msg, XorCipherText);
randcnt := 0;
(* (b) MOD (Vigenere) *)
END;
Vigenere(Msg, iEncrypt, ModCipherText);
END; {iRandom}
(* (3) Decryption *)
SeedIsaac(Key, TRUE);
(* (a) XOR (Vernam) *)
Vernam(XorCipherText, XorPlainText);
(* (b) MOD (Vigenere) *)
Vigenere(ModCipherText, iDecrypt, ModPlainText);
(* program output *)
WriteString('Message: '); WriteString(Msg); WriteLn;
WriteString('Key : '); WriteString(Key); WriteLn;
ASCII2Hex(XorCipherText, HexText);
WriteString('XOR : '); WriteString(HexText); WriteLn;
ASCII2Hex(ModCipherText, HexText);
WriteString('MOD : '); WriteString(HexText); WriteLn;
WriteString('XOR dcr: '); WriteString(XorPlainText); WriteLn;
WriteString('MOD dcr: '); WriteString(ModPlainText); WriteLn;
END RosettaIsaac.
</syntaxhighlight>
{{out}}
<pre>
Message: a Top Secret secret
Key : this is my secret key
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
MOD : 734270227D36772A783B4F2A5F206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret
</pre>
 
=={{header|Nim}}==
{{trans|Pascal}}
We choose the translate the Pascal version as the it’s easier to translate to Nim from Pascal rather than from C.
This is not an exact translation: the more important difference is the use of a global state record rather than a list of global variables. This global state is transmitted to each procedure. This way, it is possible to run several PRNG concurrently.
 
We also replaced the eight variables "a" to "h" with an array. This allows to simplify the code at several places by using a loop. And we changed the "mod" to "and", even if the compiler will likely optimize the modulo when the second operand is a power of two.
{ Get a random character in printable ASCII range }
FUNCTION iRandA: BYTE;
BEGIN
iRandA := iRandom mod 95 + 32;
END;
 
Note that the "mix" procedure could possibly be transformed in a template or be marked as "inline" (in the C version, it is a "define"). But as we are not in a procedure whose performance is critical, expanding the code rather than calling a procedure is not very useful.
 
<syntaxhighlight lang="nim">import strutils
{ convert an ASCII string to a hexadecimal string }
FUNCTION ascii2hex(s: STRING): STRING;
VAR i,l: CARDINAL;
BEGIN
ascii2hex := '';
l := Length(s);
FOR i := 1 TO l DO
ascii2hex += Dec2Numb(ord(s[i]),2,16);
END;
 
type
 
IMode = enum iEncrypt, iDecrypt
{ XOR encrypt on random stream. Output: ASCII string }
FUNCTION Vernam(msg: STRING): STRING;
VAR i: CARDINAL;
BEGIN
Vernam := '';
FOR i := 1 to length(msg) DO
Vernam += chr(iRandA xor ord(msg[i]));
END;
 
State = object
# Internal.
{ Get position of the letter in chosen alphabet }
mm: array[256, uint32]
FUNCTION letternum(letter, start: CHAR): byte;
aa, bb, cc: uint32
BEGIN
# External.
letternum := (ord(letter)-ord(start));
randrsl: array[256, uint32]
END;
randcnt: uint32
 
 
proc isaac(s: var State) =
{ 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;
 
inc s.cc # "cc" just gets incremented once per 256 results
s.bb += s.cc # then combined with "bb".
 
for i in 0u32..255:
{ Vigenere mod 95 encryption & decryption. Output: ASCII string }
let x = s.mm[i]
FUNCTION Vigenere(msg: STRING; m: iMode): STRING;
case range[0..3](i and 3)
VAR i: CARDINAL;
of 0: s.aa = s.aa xor s.aa shl 13
BEGIN
of 1: s.aa = s.aa xor s.aa shr 6
Vigenere := '';
of 2: s.aa = s.aa xor s.aa shl 2
FOR i := 1 to length(msg) DO
of 3: s.aa = s.aa xor s.aa shr 16
Vigenere += Caesar(m,msg[i],iRandA,95,' ');
s.aa += s.mm[(i + 128) and 255]
END;
let y = s.mm[(x shr 2) and 255] + s.aa + s.bb
s.mm[i] = y
s.bb = s.mm[(y shr 10) and 255] + x
s.randrsl[i] = s.bb
 
s.randcnt = 0
 
 
proc mix(a: var array[8, uint32]) =
a[0] = a[0] xor a[1] shl 11; a[3] += a[0]; a[1] += a[2]
a[1] = a[1] xor a[2] shr 2; a[4] += a[1]; a[2] += a[3]
a[2] = a[2] xor a[3] shl 8; a[5] += a[2]; a[3] += a[4]
a[3] = a[3] xor a[4] shr 16; a[6] += a[3]; a[4] += a[5]
a[4] = a[4] xor a[5] shl 10; a[7] += a[4]; a[5] += a[6]
a[5] = a[5] xor a[6] shr 4; a[0] += a[5]; a[6] += a[7]
a[6] = a[6] xor a[7] shl 8; a[1] += a[6]; a[7] += a[0]
a[7] = a[7] xor a[0] shr 9; a[2] += a[7]; a[0] += a[1]
 
 
proc iRandInit(s: var State; flag: bool) =
 
s.aa = 0; s.bb = 0; s.cc = 0
var a: array[8, uint32]
for item in a.mitems: item = 0x9e3779b9u32 # The golden ratio.
 
for i in 0..3: # Scramble it.
a.mix()
 
var i = 0u32
while true: # Fill in "mm" with messy stuff.
if flag:
# Use all the information in the seed.
for n in 0u32..7: a[n] += s.randrsl[n + i]
a.mix()
for n in 0u32..7: s.mm[n + i] = a[n]
inc i, 8
if i > 255: break
 
if flag:
# Do a second pass to make all of the seed affect all of "mm".
i = 0
while true:
for n in 0u32..7: a[n] += s.mm[n + i]
a.mix()
for n in 0u32..7: s.mm[n + i] = a[n]
inc i, 8
if i > 255: break
 
s.isaac() # Fill in the first set of results.
s.randcnt = 0 # Prepare to use the first set of results.
 
 
proc iSeed(s: var State; seed: string; flag: bool) =
## Seed ISAAC with a given string.
## The string can be any size. The first 256 values will be used.
s.mm.reset()
let m = seed.high
for i in 0..255:
s.randrsl[i] = if i > m: 0 else: ord(seed[i])
# Initialize ISAAC with seed.
s.iRandInit(flag)
 
 
proc iRandom(s: var State): uint32 =
## Get a random 32-bit value 0..int32.high.
result = s.randrsl[s.randcnt]
inc s.randcnt
if s.randcnt > 255:
s.isaac()
s.randcnt = 0
 
 
proc iRandA(s: var State): byte =
## Get a random character in printable ASCII range.
result = byte(s.iRandom() mod 95 + 32)
 
 
proc vernam(s: var State; msg: string): string =
## XOR encrypt on random stream. Output: ASCII string.
result.setLen(msg.len)
for i, c in msg:
result[i] = chr(s.irandA() xor byte(c))
 
 
template letterNum(letter, start: char): int =
ord(letter) - ord(start)
 
 
proc caesar(m: IMode; ch: char; shift, modulo: int; start: char): char =
let shift = if m == iEncrypt: shift else: -shift
var n = letterNum(ch, start) + shift
n = n mod modulo
if n < 0: inc n, modulo
result = chr(ord(start) + n)
 
 
proc vigenere(s: var State; msg: string; m: IMode): string =
## Vigenere MOD 95 encryption & decryption. Output: ASCII string.
result.setLen(msg.len)
for i, c in msg:
result[i] = caesar(m, c, s.iRanda().int, 95, ' ')
 
 
let
msg = "a Top Secret secret"
key = "this is my secret key"
 
var state: State
 
# 1) seed ISAAC with the key
state.iSeed(key, true)
# 2) Encryption
# a) XOR (Vernam)
let xctx = state.vernam(msg) # XOR ciphertext.
# b) MOD (Vigenere)
let mctx = state.vigenere(msg, iEncrypt) # MOD ciphertext.
# 3) Decryption
state.iSeed(key, true)
# a) XOR (Vernam)
let xptx = state.vernam(xctx) # XOR decryption (plaintext).
# b) MOD (Vigenere)
let mptx = state.vigenere(mctx, iDecrypt) # MOD decryption (plaintext).
# Program output
echo "Message: ", msg
echo " Key: ", key
echo " XOR: ", xctx.tohex
echo " MOD: ", mctx.toHex
echo "XOR dcr: ", xptx
echo "MOD dcr: ", mptx</syntaxhighlight>
 
{{out}}
<pre>Message: a Top Secret secret
Key: this is my secret key
XOR: 1C0636190B1260233B35125F1E1D0E2F4C5422
MOD: 734270227D36772A783B4F2A5F206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret</pre>
 
=={{header|Pascal}}==
Free Pascal. A fully functional and complete reference solution of the task.
<syntaxhighlight lang="pascal">
PROGRAM RosettaIsaac;
USES
StrUtils;
 
TYPE
iMode = (iEncrypt, iDecrypt);
 
// TASK globals
VAR
msg : String = 'a Top Secret secret';
key : String = 'this is my secret key';
xctx: String = ''; // XOR ciphertext
mctx: String = ''; // MOD ciphertext
xptx: String = ''; // XOR decryption (plaintext)
mptx: String = ''; // MOD decryption (plaintext)
 
// ISAAC globals
VAR
// external results
randrsl: ARRAY[0 .. 255] OF Cardinal;
randcnt: Cardinal;
 
// internal state
mm: ARRAY[0 .. 255] OF Cardinal;
aa: Cardinal = 0;
bb: Cardinal = 0;
cc: Cardinal = 0;
 
PROCEDURE Isaac;
VAR
i, x, y: Cardinal;
BEGIN
cc := cc + 1; // cc just gets incremented once per 256 results
// 1) seed ISAAC with the key
bb := bb + cc; // then combined with bb
iSeed(key,true);
// 2) Encryption
mode := iEncrypt;
// a) XOR (Vernam)
xctx := Vernam(msg);
// b) MOD (Vigenere)
mctx := Vigenere(msg,mode);
// 3) Decryption
mode := iDecrypt;
iSeed(key,true);
// a) XOR (Vernam)
xptx:= Vernam(xctx);
// b) MOD (Vigenere)
mptx:=Vigenere(mctx,mode);
// program output
Writeln('Message: ',msg);
Writeln('Key : ',key);
Writeln('XOR : ',ascii2hex(xctx));
Writeln('MOD : ',ascii2hex(mctx));
Writeln('XOR dcr: ',xptx);
Writeln('MOD dcr: ',mptx);
END.
 
FOR i := 0 TO 255 DO
</lang>
BEGIN
x := mm[i];
CASE (i MOD 4) OF
0: aa := aa XOR (aa SHL 13);
1: aa := aa XOR (aa SHR 6);
2: aa := aa XOR (aa SHL 2);
3: aa := aa XOR (aa SHR 16);
END;
aa := mm[(i + 128) MOD 256] + aa;
y := mm[(x SHR 2) MOD 256] + aa + bb;
mm[i] := y;
bb := mm[(y SHR 10) MOD 256] + x;
randrsl[i] := bb;
END;
randcnt := 0; // prepare to use the first set of results
END; // Isaac
 
PROCEDURE Mix(VAR a, b, c, d, e, f, g, h: Cardinal);
BEGIN
a := a XOR b SHL 11; d := d + a; b := b + c;
b := b XOR c SHR 2; e := e + b; c := c + d;
c := c XOR d SHL 8; f := f + c; d := d + e;
d := d XOR e SHR 16; g := g + d; e := e + f;
e := e XOR f SHL 10; h := h + e; f := f + g;
f := f XOR g SHR 4; a := a + f; g := g + h;
g := g XOR h SHL 8; b := b + g; h := h + a;
h := h XOR a SHR 9; c := c + h; a := a + b;
END; // Mix
 
PROCEDURE iRandInit(flag: Boolean);
VAR
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;
 
FOR i := 0 TO 3 DO // scramble it
Mix(a, b, c, d, e, f, g, h);
 
i := 0;
REPEAT // fill in mm[] with messy stuff
IF flag THEN
BEGIN // 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];
END;
 
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;
i += 8;
UNTIL i > 255;
 
IF flag THEN
BEGIN
// do a second pass to make all of the seed affect all of mm
i := 0;
REPEAT
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;
i += 8;
UNTIL i > 255;
END;
Isaac(); // fill in the first set of results
randcnt := 0; // prepare to use the first set of results
END; // iRandInit
 
// Seed ISAAC with a given string.
// The string can be any size. The first 256 values will be used.
PROCEDURE iSeed(seed: String; flag: Boolean);
VAR
i, m: Cardinal;
BEGIN
FOR i := 0 TO 255 DO
mm[i] := 0;
m := Length(seed) - 1;
FOR i := 0 TO 255 DO
BEGIN
// in case seed has less than 256 elements
IF i > m THEN
randrsl[i] := 0
// Pascal strings are 1-based
ELSE
randrsl[i] := Ord(seed[i + 1]);
END;
// initialize ISAAC with seed
iRandInit(flag);
END; // iSeed
 
// Get a random 32-bit value 0..MAXINT
FUNCTION iRandom: Cardinal;
BEGIN
iRandom := randrsl[randcnt];
inc(randcnt);
IF (randcnt > 255) THEN
BEGIN
Isaac;
randcnt := 0;
END;
END; // iRandom
 
// Get a random character in printable ASCII range
FUNCTION iRandA: Byte;
BEGIN
iRandA := iRandom MOD 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
 
// XOR encrypt on random stream. Output: ASCII string
FUNCTION Vernam(msg: String): String;
VAR
i: Cardinal;
BEGIN
Vernam := '';
FOR i := 1 to Length(msg) DO
Vernam += Chr(iRandA XOR Ord(msg[i]));
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
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; // Caesar
 
// 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(xctx));
Writeln('MOD : ', Ascii2Hex(mctx));
Writeln('XOR dcr: ', xptx);
Writeln('MOD dcr: ', mptx);
END.
</syntaxhighlight>
{{out}}
<pre>
Line 2,575 ⟶ 3,933:
as well as additional convenience functions.
 
<langsyntaxhighlight lang="perl">use warnings;
use strict;
use Math::Random::ISAAC;
Line 2,605 ⟶ 3,963:
map { ord($_) ^ shift(@iranda) } # xor it with rand char
split "", $msg; # Take each character
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,612 ⟶ 3,970:
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr: a Top Secret secret
</pre>
 
=={{header|Phix}}==
{{trans|Pascal}}
We need the r32() function to convert our common sense maths into the needed unsigned_and_throw_away_any_high_bits maths.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\ISAAC_Cipher.exw
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">randrsl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">randcnt</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">mm</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cc</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">+=</span><span style="color: #000000;">#100000000</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#100000000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">bits</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">bits</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Isaac</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">cc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000080;font-style:italic;">-- cc just gets incremented once per 256 results </span>
<span style="color: #000000;">bb</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">cc</span><span style="color: #0000FF;">;</span> <span style="color: #000080;font-style:italic;">-- then combined with bb </span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">256</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">switch</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">aa</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">aa</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">aa</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">aa</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #000000;">aa</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#80</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">+</span><span style="color: #000000;">bb</span>
<span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">;</span>
<span style="color: #000000;">bb</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">randrsl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]:=</span> <span style="color: #000000;">bb</span><span style="color: #0000FF;">;</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">randcnt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">mix</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a8</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a8</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">d</span><span style="color: #0000FF;">+</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">e</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">f</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">+</span><span style="color: #000000;">e</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">g</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">+</span><span style="color: #000000;">f</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">+</span><span style="color: #000000;">g</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">g</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">a</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">));</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">({</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">});</span>
<span style="color: #000000;">a8</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a8</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">iRandInit</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">aa</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cc</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a8</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">#9e3779b9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- the golden ratio</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- scramble it </span>
<span style="color: #000000;">a8</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mix</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a8</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">255</span> <span style="color: #008080;">by</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a8</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mix</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">randrsl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]))</span>
<span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a8</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">255</span> <span style="color: #008080;">by</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a8</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mix</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span><span style="color: #0000FF;">])))</span>
<span style="color: #000000;">mm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a8</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">Isaac</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- fill in the first set of results </span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">iSeed</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">seed</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mm</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">randrsl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">randrsl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seed</span><span style="color: #0000FF;">),</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">seed</span>
<span style="color: #000000;">iRandInit</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">randch</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">randrsl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">randcnt</span><span style="color: #0000FF;">],</span><span style="color: #000000;">95</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">32</span>
<span style="color: #000000;">randcnt</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">randcnt</span><span style="color: #0000FF;">></span><span style="color: #000000;">256</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">Isaac</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Vernam</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">randch</span><span style="color: #0000FF;">())</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Caesar</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">shift</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">' '</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">+</span><span style="color: #000000;">shift</span><span style="color: #0000FF;">,</span><span style="color: #000000;">95</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">ENCRYPT</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">DECRYPT</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Vigenere</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">Caesar</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">randch</span><span style="color: #0000FF;">()*</span><span style="color: #000000;">mode</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"a Top Secret secret"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"this is my secret key"</span>
<span style="color: #000000;">iSeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">xctx</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">Vernam</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mctx</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">Vigenere</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ENCRYPT</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">iSeed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">xptx</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">Vernam</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xctx</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mptx</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">Vigenere</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mctx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">DECRYPT</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">ascii2hex</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%02x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Message: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Key : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">key</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"XOR : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ascii2hex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xctx</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"MOD : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ascii2hex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mctx</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"XOR dcr: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">xptx</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"MOD dcr: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">mptx</span><span style="color: #0000FF;">})</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Message: a Top Secret secret
Key : this is my secret key
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
MOD : 734270227D36772A783B4F2A5F206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de add32 @
(mod32 (pass +)) )
 
Line 2,719 ⟶ 4,239:
95 ) ) ) ) ) ) ) ) ) )
 
(bye)</langsyntaxhighlight>
 
=={{header|Python}}==
Line 2,729 ⟶ 4,249:
This implementation extends the Random class of the built-in random module, so it automatically inherits methods for generating several distributions, as well as support for shuffling and sampling collections.
 
<langsyntaxhighlight Pythonlang="python">import random
import collections
 
Line 2,925 ⟶ 4,445:
print('MOD :', hexify(caesar_encoded))
print('MOD dcr:', caesar_decoded)
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 2,937 ⟶ 4,457:
left from after the XOR, and one with a cleanly reseeded state engine.
 
<langsyntaxhighlight lang="racket">#lang racket
;; Imperative version: Translation of C
;; Vigenère: Translation of Pascal
Line 3,191 ⟶ 4,711:
(randctx-b C) => #x902c0691
(randctx-c C) => 10))
}</langsyntaxhighlight>
 
{{out}}
Line 3,209 ⟶ 4,729:
< context reseeded
Vigenère (-MOD): [6120546f702053656372657420736563726574 "a Top Secret secret"]</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>my uint32 (@mm, @randrsl, $randcnt, $aa, $bb, $cc);
my \ϕ := 2654435769; constant MOD = 95; constant START = 32;
 
constant MAXINT = uint.Range.max;
enum CipherMode < ENCIPHER DECIPHER NONE >;
 
sub mix (\n) {
sub mix1 (\i, \v) {
n[i] +^= v;
n[(i+3)%8] += n[i];
n[(i+1)%8] += n[(i+2)%8];
}
mix1 0, n[1]+<11; mix1 1, n[2]+>2; mix1 2, n[3]+<8; mix1 3, n[4]+>16;
mix1 4, n[5]+<10; mix1 5, n[6]+>4; mix1 6, n[7]+<8; mix1 7, n[0]+>9 ;
}
 
sub randinit(\flag) {
$aa = $bb = $cc = 0;
my uint32 @n = [^8].map({ ϕ });
for ^4 { mix @n };
for 0,8 … 255 -> $i {
{ for (0..7) { @n[$^j] += @randrsl[$i + $^j] } } if flag;
mix @n;
for (0..7) { @mm[$i + $^j] = @n[$^j] }
}
if flag {
for 0,8 … 255 -> $i {
for ^8 { @n[$^j] += @mm[$i + $^j] };
mix @n;
for ^8 { @mm[$i + $^j] = @n[$^j] };
}
}
isaac;
$randcnt = 0;
}
 
sub isaac() {
$cc++;
$bb += $cc;
for ^256 -> $i {
my $x = @mm[$i];
given ($i % 4) {
when 0 { $aa +^= ($aa +< 13) }
when 1 { $aa +^= (($aa +& MAXINT) +> 6) }
when 2 { $aa +^= ($aa +< 2) }
when 3 { $aa +^= (($aa +& MAXINT) +> 16) }
}
$aa += @mm[($i + 128) % 256];
my $y = @mm[(($x +& MAXINT) +> 2) % 256] + $aa + $bb;
@mm[$i] = $y;
$bb = @mm[(($y +& MAXINT) +> 10) % 256] + $x;
@randrsl[$i] = $bb;
}
$randcnt = 0;
}
 
sub iRandom {
my $result = @randrsl[$randcnt++];
if ($randcnt > 255) {
isaac;
$randcnt = 0;
}
return $result;
}
 
sub iSeed(\seed, \flag) {
@mm = [^256].race.map({0});
my \m = seed.chars;
@randrsl = [^256].hyper.map({ $^i ≥ m ?? 0 !! seed.substr($^i,1).ord });
randinit(flag);
}
 
sub iRandA { return iRandom() % MOD + START };
 
sub vernam(\M) { ( map { (iRandA() +^ .ord ).chr }, M.comb ).join };
sub caesar(CipherMode \m, \ch, $shift is copy, \Modulo, \Start) {
$shift = -$shift if m == DECIPHER;
my $n = (ch.ord - Start) + $shift;
$n %= Modulo;
$n += Modulo if $n < 0;
return (Start + $n).chr;
}
 
sub caesarStr(CipherMode \m, \msg, \Modulo, \Start) {
my $sb = '';
for msg.comb {
$sb ~= caesar m, $^c, iRandA(), Modulo, Start;
}
return $sb;
}
multi MAIN () {
my \msg = "a Top Secret secret";
my \key = "this is my secret key";
iSeed key, True ;
my $vctx = vernam msg;
my $cctx = caesarStr ENCIPHER, msg, MOD, START;
 
iSeed key, True ;
my $vptx = vernam $vctx;
my $cptx = caesarStr DECIPHER, $cctx, MOD, START;
 
my $vctx2hex = ( map { .ord.fmt('%02X') }, $vctx.comb ).join('');
my $cctx2hex = ( map { .ord.fmt('%02X') }, $cctx.comb ).join('');
 
say "Message : ", msg;
say "Key : ", key;
say "XOR : ", $vctx2hex;
say "XOR dcr : ", $vptx;
say "MOD : ", $cctx2hex;
say "MOD dcr : ", $cptx;
}</syntaxhighlight>
{{out}}
<pre>
Message : a Top Secret secret
Key : this is my secret key
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr : a Top Secret secret
MOD : 734270227D36772A783B4F2A5F206266236978
MOD dcr : a Top Secret secret
</pre>
 
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 24.07.2014 Walter Pachl translated from Pascal
* extend with decryption (following Pascal)
Line 3,419 ⟶ 5,065:
If arg(3)<>'' Then
res=res+arg(3)
return res//4294967296</langsyntaxhighlight>
{{out}}
<pre>Message: a Top Secret secret
Line 3,429 ⟶ 5,075:
 
===version 2===
This can be used to ecryptencrypt a file and thereafter decrypt it.
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 25.07.2014 Walter Pachl framing version 1 for processing a file
*--------------------------------------------------------------------*/
Line 3,668 ⟶ 5,314:
parse Arg fid
Parse Var fid fn '.' ft
Return fn</langsyntaxhighlight>
{{out}}
<pre>Please enter a key
Line 3,680 ⟶ 5,326:
This is a little test file
that shows my encryption</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">
//! includes the XOR version of the encryption scheme
 
use std::num::Wrapping as w;
 
const MSG: &str = "a Top Secret secret";
const KEY: &str = "this is my secret key";
 
fn main() {
let mut isaac = Isaac::new();
isaac.seed(KEY, true);
let encr = isaac.vernam(MSG.as_bytes());
 
println!("msg: {}", MSG);
println!("key: {}", KEY);
print!("XOR: ");
for a in &encr {
print!("{:02X}", *a);
}
 
let mut isaac = Isaac::new();
isaac.seed(KEY, true);
let decr = isaac.vernam(&encr[..]);
 
print!("\nXOR dcr: ");
println!("{}", String::from_utf8(decr).unwrap())
}
 
macro_rules! mix_v(
($a:expr) => (
{
$a[0] ^= $a[1] << 11; $a[3] += $a[0]; $a[1] += $a[2];
$a[1] ^= $a[2] >> 2; $a[4] += $a[1]; $a[2] += $a[3];
$a[2] ^= $a[3] << 8; $a[5] += $a[2]; $a[3] += $a[4];
$a[3] ^= $a[4] >> 16; $a[6] += $a[3]; $a[4] += $a[5];
$a[4] ^= $a[5] << 10; $a[7] += $a[4]; $a[5] += $a[6];
$a[5] ^= $a[6] >> 4; $a[0] += $a[5]; $a[6] += $a[7];
$a[6] ^= $a[7] << 8; $a[1] += $a[6]; $a[7] += $a[0];
$a[7] ^= $a[0] >> 9; $a[2] += $a[7]; $a[0] += $a[1];
} );
);
 
struct Isaac {
mm: [w<u32>; 256],
aa: w<u32>,
bb: w<u32>,
cc: w<u32>,
rand_rsl: [w<u32>; 256],
rand_cnt: u32,
}
 
impl Isaac {
fn new() -> Isaac {
Isaac {
mm: [w(0u32); 256],
aa: w(0),
bb: w(0),
cc: w(0),
rand_rsl: [w(0u32); 256],
rand_cnt: 0,
}
}
 
fn isaac(&mut self) {
self.cc += w(1);
self.bb += self.cc;
 
for i in 0..256 {
let w(x) = self.mm[i];
match i % 4 {
0 => self.aa ^= self.aa << 13,
1 => self.aa ^= self.aa >> 6,
2 => self.aa ^= self.aa << 2,
3 => self.aa ^= self.aa >> 16,
_ => unreachable!(),
}
 
self.aa += self.mm[((i + 128) % 256) as usize];
let w(y) = self.mm[((x >> 2) % 256) as usize] + self.aa + self.bb;
self.bb = self.mm[((y >> 10) % 256) as usize] + w(x);
self.rand_rsl[i] = self.bb;
}
 
self.rand_cnt = 0;
}
 
fn rand_init(&mut self, flag: bool) {
let mut a_v = [w(0x9e37_79b9u32); 8];
 
for _ in 0..4 {
// scramble it
mix_v!(a_v);
}
 
for i in (0..256).step_by(8) {
// fill in mm[] with messy stuff
if flag {
// use all the information in the seed
for (j, value) in a_v.iter_mut().enumerate().take(8) {
*value += self.rand_rsl[i + j];
}
}
mix_v!(a_v);
for (j, value) in a_v.iter().enumerate().take(8) {
self.mm[i + j] = *value;
}
}
 
if flag {
// do a second pass to make all of the seed affect all of mm
for i in (0..256).step_by(8) {
for (j, value) in a_v.iter_mut().enumerate().take(8) {
*value += self.mm[i + j];
}
mix_v!(a_v);
for (j, value) in a_v.iter().enumerate().take(8) {
self.mm[i + j] = *value;
}
}
}
 
self.isaac(); // fill in the first set of results
self.rand_cnt = 0; // prepare to use the first set of results
}
 
/// Get a random 32-bit value
fn i_random(&mut self) -> u32 {
let r = self.rand_rsl[self.rand_cnt as usize];
self.rand_cnt += 1;
if self.rand_cnt > 255 {
self.isaac();
self.rand_cnt = 0;
}
r.0
}
 
/// Seed ISAAC with a string
fn seed(&mut self, seed: &str, flag: bool) {
for i in 0..256 {
self.mm[i] = w(0);
}
for i in 0..256 {
self.rand_rsl[i] = w(0);
}
 
for i in 0..seed.len() {
self.rand_rsl[i] = w(u32::from(seed.as_bytes()[i]));
}
// initialize ISAAC with seed
self.rand_init(flag);
}
 
/// Get a random character in printable ASCII range
fn i_rand_ascii(&mut self) -> u8 {
(self.i_random() % 95 + 32) as u8
}
 
/// XOR message
fn vernam(&mut self, msg: &[u8]) -> Vec<u8> {
msg.iter()
.map(|&b| (self.i_rand_ascii() ^ b))
.collect::<Vec<u8>>()
}
}
 
impl Default for Isaac {
fn default() -> Self {
Isaac::new()
}
}
 
</syntaxhighlight>
{{out}}
<pre>
msg: a Top Secret secret
key: this is my secret key
XOR: 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr: a Top Secret secret
</pre>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">require('Math::Random::ISAAC')
 
func xor_isaac(key, msg) {
Line 3,702 ⟶ 5,529:
say "Key : #{key}"
say "XOR : #{enc}"
say "XOR dcr: #{pack('H*', dec)}"</langsyntaxhighlight>
{{out}}
<pre>
Line 3,714 ⟶ 5,541:
{{works with|Tcl|8.6}}
{{trans|Go}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
oo::class create ISAAC {
Line 3,823 ⟶ 5,650:
return [binary encode hex [binary format c* $b]]
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">set key "this is my secret key"
set msg "a Top Secret secret"
ISAAC create demo $key
puts "Message: $msg"
puts "Key : $key"
puts "XOR : [demo vernam $msg]"</langsyntaxhighlight>
{{out}}
<pre>
Line 3,836 ⟶ 5,663:
Key : this is my secret key
XOR : 1c0636190b1260233b35125f1e1d0e2f4c5422
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-iterate}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./iterate" for Stepped
import "./dynamic" for Enum
import "./fmt" for Fmt
 
/* external results */
var randrsl = List.filled(256, 0)
var randcnt = 0
 
/* internal state */
var mm = List.filled(256, 0)
var aa = 0
var bb = 0
var cc = 0
 
var GOLDEN_RATIO = 0x9e3779b9
 
var isaac = Fn.new {
cc = cc + 1 // cc just gets incremented once per 256 results
bb = bb + cc // then combined with bb
for (i in 0..255) {
var x = mm[i]
var j = i % 4
aa = (j == 0) ? aa ^ (aa << 13) :
(j == 1) ? aa ^ (aa >> 6) :
(j == 2) ? aa ^ (aa << 2) :
(j == 3) ? aa ^ (aa >> 16) : aa
aa = aa + mm[(i + 128) % 256]
var y = mm[(x >> 2) % 256] + aa + bb
mm[i] = y
bb = mm[(y >> 10) % 256] + x
randrsl[i] = bb
}
randcnt = 0
}
 
/* if (flag == true), then use the contents of randrsl to initialize mm. */
var mix = Fn.new { |n|
n[0] = n[0] ^ (n[1] << 11)
n[3] = n[3] + n[0]
n[1] = n[1] + n[2]
n[1] = n[1] ^ (n[2] >> 2)
n[4] = n[4] + n[1]
n[2] = n[2] + n[3]
n[2] = n[2] ^ (n[3] << 8)
n[5] = n[5] + n[2]
n[3] = n[3] + n[4]
n[3] = n[3] ^ (n[4] >> 16)
n[6] = n[6] + n[3]
n[4] = n[4] + n[5]
n[4] = n[4] ^ (n[5] << 10)
n[7] = n[7] + n[4]
n[5] = n[5] + n[6]
n[5] = n[5] ^ (n[6] >> 4)
n[0] = n[0] + n[5]
n[6] = n[6] + n[7]
n[6] = n[6] ^ (n[7] << 8)
n[1] = n[1] + n[6]
n[7] = n[7] + n[0]
n[7] = n[7] ^ (n[0] >> 9)
n[2] = n[2] + n[7]
n[0] = n[0] + n[1]
}
 
var randinit = Fn.new { |flag|
aa = 0
bb = 0
cc = 0
var n = List.filled(8, GOLDEN_RATIO)
for (i in 0..3) mix.call(n) // scramble the array
 
for (i in Stepped.new(0..255, 8)) { // fill in mm with messy stuff
if (flag) { // use all the information in the seed
for (j in 0..7) {
n[j] = n[j] + randrsl[i + j]
}
}
mix.call(n)
for (j in 0..7) mm[i + j] = n[j]
}
 
if (flag) {
/* do a second pass to make all of the seed affect all of mm */
for (i in Stepped.new(0..255, 8)) {
for (j in 0..7) n[j] = n[j] + mm[i + j]
mix.call(n)
for (j in 0..7) mm[i + j] = n[j]
}
}
 
isaac.call() // fill in the first set of results
randcnt = 0 // prepare to use the first set of results
}
 
var iRandom = Fn.new {
var r = randrsl[randcnt]
randcnt = randcnt + 1
if (randcnt > 255) {
isaac.call()
randcnt = 0
}
return r & 0xffffffff
}
 
/* Get a random character (as Num) in printable ASCII range */
var iRandA = Fn.new { (iRandom.call() % 95 + 32) }
 
/* Seed ISAAC with a string */
var iSeed = Fn.new { |seed, flag|
for (i in 0..255) mm[i] = 0
var m = seed.count
for (i in 0..255) {
/* in case seed has less than 256 elements */
randrsl[i] = (i >= m) ? 0 : seed[i].bytes[0]
}
/* initialize ISAAC with seed */
randinit.call(flag)
}
 
/* XOR cipher on random stream. Output: ASCII string */
var vernam = Fn.new { |msg|
var len = msg.count
var v = List.filled(len, 0)
var i = 0
for (b in msg.bytes) {
v[i] = (iRandA.call() ^ b) & 0xff
i = i + 1
}
return v.map { |b| String.fromByte(b) }.join()
}
 
/* constants for Caesar */
var MOD = 95
var START = 32
/* cipher modes for Caesar */
var CipherMode = Enum.create("CipherMode", ["ENCIPHER", "DECIPHER", "NONE"])
 
/* Caesar-shift a printable character */
var caesar = Fn.new { |m, ch, shift, modulo, start|
var sh = (m == CipherMode.DECIPHER) ? -shift : shift
var n = (ch - start) + sh
n = n % modulo
if (n < 0) n = n + modulo
return String.fromByte(start + n)
}
 
/* Caesar-shift a string on a pseudo-random stream */
var caesarStr = Fn.new { |m, msg, modulo, start|
var sb = ""
/* Caesar-shift message */
for (b in msg.bytes) {
sb = sb + caesar.call(m, b, iRandA.call(), modulo, start)
}
return sb
}
 
var toHexByteString = Fn.new { |s|
return s.bytes.map { |b| Fmt.swrite("$02X", b) }.join()
}
 
var msg = "a Top Secret secret"
var key = "this is my secret key"
 
// Vernam & Caesar ciphertext
iSeed.call(key, true)
var vctx = vernam.call(msg)
var cctx = caesarStr.call(CipherMode.ENCIPHER, msg, MOD, START)
 
// Vernam & Caesar plaintext
iSeed.call(key, true)
var vptx = vernam.call(vctx)
var cptx = caesarStr.call(CipherMode.DECIPHER, cctx, MOD, START)
 
// Program output
System.print("Message : %(msg)")
System.print("Key : %(key)")
System.print("XOR : %(toHexByteString.call(vctx))")
System.print("XOR dcr : %(vptx)")
System.print("MOD : %(toHexByteString.call(cctx))")
System.print("MOD dcr : %(cptx)")</syntaxhighlight>
 
{{out}}
<pre>
Message : a Top Secret secret
Key : this is my secret key
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr : a Top Secret secret
MOD : 734270227D36772A783B4F2A5F206266236978
MOD dcr : a Top Secret secret
</pre>
9,476

edits