Update all new Tasks
This commit is contained in:
parent
00a190b0a6
commit
91df62d461
5697 changed files with 93386 additions and 804 deletions
56
Task/The-ISAAC-Cipher/00DESCRIPTION
Normal file
56
Task/The-ISAAC-Cipher/00DESCRIPTION
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
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.
|
||||
|
||||
ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are the principal bitwise operations employed.
|
||||
To date - and that's after more than 20 years of existence - ISAAC has not been broken (unless GCHQ or NSA did it, but they wouldn't be telling).
|
||||
ISAAC thus deserves a lot more attention than it has hitherto received and it would be salutary to see it more universally implemented.
|
||||
|
||||
Your task, should you choose to accept it, is to translate ISAAC's reference
|
||||
C or Pascal code into your language of choice.
|
||||
The RNG should then be seeded with the string "this is my secret key" and
|
||||
finally the message "a Top Secret secret" should be encrypted on that key.
|
||||
Your program's output ciphertext will be a string of hexadecimal digits.
|
||||
|
||||
Optional: Include a decryption check by re-initializing ISAAC and performing
|
||||
the same encryption pass on the ciphertext.
|
||||
|
||||
Please use the C or Pascal as a reference guide to these operations.
|
||||
|
||||
Two encryption schemes are possible:
|
||||
(1) XOR (Vernam) or
|
||||
(2) Caesar-shift mod 95 (Vigenère).
|
||||
XOR is the simplest; C-shifting offers greater security.
|
||||
|
||||
You may choose either scheme, or both, but please specify which you used.
|
||||
Here are the alternative sample outputs for checking purposes:
|
||||
|
||||
<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>
|
||||
|
||||
No official seeding method for ISAAC has been published, but for this task
|
||||
we may as well just inject the bytes of our key into the randrsl array,
|
||||
padding with zeroes before mixing, like so:
|
||||
|
||||
<pre>
|
||||
// zeroise mm array
|
||||
FOR i:= 0 TO 255 DO mm[i]:=0;
|
||||
// check seed's highest array element
|
||||
m := High(seed);
|
||||
// inject the seed
|
||||
FOR i:= 0 TO 255 DO BEGIN
|
||||
// in case seed[] has less than 256 elements.
|
||||
IF i>m THEN randrsl[i]:=0
|
||||
ELSE randrsl[i]:=seed[i];
|
||||
END;
|
||||
// initialize ISAAC with seed
|
||||
RandInit(true);
|
||||
</pre>
|
||||
|
||||
ISAAC can of course also be initialized with a single 32-bit unsigned integer in the manner of traditional RNGs, and indeed used as such for research and gaming purposes.
|
||||
But building a strong and simple ISAAC-based stream cipher - replacing the irreparably broken RC4 - is our goal here: ISAAC's intended purpose.
|
||||
2
Task/The-ISAAC-Cipher/00META.yaml
Normal file
2
Task/The-ISAAC-Cipher/00META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Encryption
|
||||
159
Task/The-ISAAC-Cipher/C-sharp/the-isaac-cipher.cs
Normal file
159
Task/The-ISAAC-Cipher/C-sharp/the-isaac-cipher.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
|
||||
namespace cipher {
|
||||
|
||||
static class Cipher {
|
||||
|
||||
// external results
|
||||
static uint[] randrsl = new uint[256];
|
||||
static uint randcnt;
|
||||
// internal state
|
||||
static uint[] mm = new uint[256];
|
||||
static uint aa=0, bb=0, cc=0;
|
||||
|
||||
|
||||
static void isaac() {
|
||||
uint i,x,y;
|
||||
cc++; // cc just gets incremented once per 256 results
|
||||
bb+=cc; // then combined with bb
|
||||
|
||||
for (i=0; i<=255; i++) {
|
||||
x = mm[i];
|
||||
switch (i & 3) {
|
||||
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) & 255] + aa;
|
||||
y = mm[(x >> 2) & 255] + aa + bb;
|
||||
mm[i] = y;
|
||||
bb = mm[(y >> 10) & 255] + x;
|
||||
randrsl[i]= bb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
|
||||
static void mix(ref uint a, ref uint b, ref uint c, ref uint d, ref uint e, ref uint f, ref uint g, ref uint h) {
|
||||
a = a ^ b << 11; d+=a; b+=c;
|
||||
b = b ^ c >> 2; e+=b; c+=d;
|
||||
c = c ^ d << 8; f+=c; d+=e;
|
||||
d = d ^ e >> 16; g+=d; e+=f;
|
||||
e = e ^ f << 10; h+=e; f+=g;
|
||||
f = f ^ g >> 4; a+=f; g+=h;
|
||||
g = g ^ h << 8; b+=g; h+=a;
|
||||
h = h ^ a >> 9; c+=h; a+=b;
|
||||
}
|
||||
|
||||
|
||||
static void Init(bool flag) {
|
||||
short i; uint a,b,c,d,e,f,g,h;
|
||||
|
||||
aa=0; bb=0; cc=0;
|
||||
a=0x9e3779b9; b=a; c=a; d=a;
|
||||
e=a; f=a; g=a; h=a;
|
||||
|
||||
for (i=0; i<=3; i++) // scramble it
|
||||
mix(ref a,ref b,ref c,ref d,ref e,ref f,ref g,ref h);
|
||||
|
||||
i=0;
|
||||
do { // fill in mm[] with messy stuff
|
||||
if (flag) { // use all the information in the seed
|
||||
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
|
||||
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
|
||||
} // if flag
|
||||
|
||||
mix(ref a,ref b,ref c,ref d,ref e,ref f,ref g,ref 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;
|
||||
}
|
||||
while (i<255);
|
||||
|
||||
if (flag) {
|
||||
// do a second pass to make all of the seed affect all of mm
|
||||
i=0;
|
||||
do {
|
||||
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(ref a,ref b,ref c,ref d,ref e,ref f,ref g,ref 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;
|
||||
}
|
||||
while (i<255);
|
||||
}
|
||||
isaac(); // fill in the first set of results
|
||||
randcnt=0; // prepare to use the first set of results
|
||||
}
|
||||
|
||||
|
||||
// Seed ISAAC with a string
|
||||
static void Seed(string seed, bool flag) {
|
||||
for (int i=0; i<256; i++) mm[i]=0;
|
||||
for (int i=0; i<256; i++) randrsl[i]=0;
|
||||
int m = seed.Length;
|
||||
for (int i=0; i<m; i++) {
|
||||
randrsl[i] = seed[i];
|
||||
}
|
||||
// initialize ISAAC with seed
|
||||
Init(flag);
|
||||
}
|
||||
|
||||
|
||||
// Get a random 32-bit value
|
||||
static uint Random() {
|
||||
uint result = randrsl[randcnt];
|
||||
randcnt++;
|
||||
if (randcnt>255) {
|
||||
isaac(); randcnt=0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Get a random character in printable ASCII range
|
||||
static byte RandA() {
|
||||
return (byte)(Random() % 95 + 32);
|
||||
}
|
||||
|
||||
|
||||
// XOR encrypt on random stream. Output: ASCII byte array
|
||||
static byte[] Vernam(string msg)
|
||||
{
|
||||
int n,l;
|
||||
byte[] v = new byte[msg.Length];
|
||||
l = msg.Length;
|
||||
// XOR message
|
||||
for (n=0; n<l; n++) {
|
||||
v[n] = (byte) (RandA() ^ (byte)msg[n]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
public static void Main() {
|
||||
string msg = "a Top Secret secret";
|
||||
string key = "this is my secret key";
|
||||
byte[] xctx= new byte[msg.Length];
|
||||
byte[] xptx= new byte[msg.Length];
|
||||
string xtcx= "*******************";
|
||||
string xtpx= "*******************";
|
||||
Seed(key,true);
|
||||
// XOR encrypt
|
||||
xctx = Vernam(msg);
|
||||
xtcx = System.Text.Encoding.ASCII.GetString(xctx);
|
||||
// XOR decrypt
|
||||
Seed(key,true);
|
||||
xptx = Vernam(xtcx);
|
||||
xtpx = System.Text.Encoding.ASCII.GetString(xptx);
|
||||
Console.WriteLine("Message: "+msg);
|
||||
Console.WriteLine("Key : "+key);
|
||||
Console.Write ("XOR : ");
|
||||
// output ciphertext as a string of hexadecimal digits
|
||||
for (int n=0; n<xctx.Length; n++) Console.Write("{0:X2}", xctx[n]);
|
||||
Console.WriteLine("\nXOR dcr: "+xtpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
231
Task/The-ISAAC-Cipher/C/the-isaac-cipher.c
Normal file
231
Task/The-ISAAC-Cipher/C/the-isaac-cipher.c
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/* Known to compile and work with tcc in win32 & gcc on Linux (with warnings)
|
||||
------------------------------------------------------------------------------
|
||||
readable.c: My random number generator, ISAAC.
|
||||
(c) Bob Jenkins, March 1996, Public Domain
|
||||
You may use this code in any way you wish, and it is free. No warrantee.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* a ub4 is an unsigned 4-byte quantity */
|
||||
typedef uint32_t ub4;
|
||||
|
||||
/* external results */
|
||||
ub4 randrsl[256], randcnt;
|
||||
|
||||
/* internal state */
|
||||
static ub4 mm[256];
|
||||
static ub4 aa=0, bb=0, cc=0;
|
||||
|
||||
void isaac()
|
||||
{
|
||||
register ub4 i,x,y;
|
||||
|
||||
cc = cc + 1; /* cc just gets incremented once per 256 results */
|
||||
bb = bb + cc; /* then combined with bb */
|
||||
|
||||
for (i=0; i<256; ++i)
|
||||
{
|
||||
x = mm[i];
|
||||
switch (i%4)
|
||||
{
|
||||
case 0: aa = aa^(aa<<13); break;
|
||||
case 1: aa = aa^(aa>>6); break;
|
||||
case 2: aa = aa^(aa<<2); break;
|
||||
case 3: aa = aa^(aa>>16); break;
|
||||
}
|
||||
aa = mm[(i+128)%256] + aa;
|
||||
mm[i] = y = mm[(x>>2)%256] + aa + bb;
|
||||
randrsl[i] = bb = mm[(y>>10)%256] + x;
|
||||
}
|
||||
// not in original readable.c
|
||||
randcnt = 0;
|
||||
}
|
||||
|
||||
/* if (flag!=0), then use the contents of randrsl[] to initialize mm[]. */
|
||||
#define mix(a,b,c,d,e,f,g,h) \
|
||||
{ \
|
||||
a^=b<<11; d+=a; b+=c; \
|
||||
b^=c>>2; e+=b; c+=d; \
|
||||
c^=d<<8; f+=c; d+=e; \
|
||||
d^=e>>16; g+=d; e+=f; \
|
||||
e^=f<<10; h+=e; f+=g; \
|
||||
f^=g>>4; a+=f; g+=h; \
|
||||
g^=h<<8; b+=g; h+=a; \
|
||||
h^=a>>9; c+=h; a+=b; \
|
||||
}
|
||||
|
||||
void randinit(int flag)
|
||||
{
|
||||
register int i;
|
||||
ub4 a,b,c,d,e,f,g,h;
|
||||
aa=bb=cc=0;
|
||||
a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
|
||||
|
||||
for (i=0; i<4; ++i) /* scramble it */
|
||||
{
|
||||
mix(a,b,c,d,e,f,g,h);
|
||||
}
|
||||
|
||||
for (i=0; i<256; i+=8) /* fill in mm[] with messy stuff */
|
||||
{
|
||||
if (flag) /* use all the information in the seed */
|
||||
{
|
||||
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
|
||||
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
|
||||
}
|
||||
mix(a,b,c,d,e,f,g,h);
|
||||
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
|
||||
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{ /* do a second pass to make all of the seed affect all of mm */
|
||||
for (i=0; i<256; i+=8)
|
||||
{
|
||||
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
|
||||
e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
|
||||
mix(a,b,c,d,e,f,g,h);
|
||||
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
|
||||
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
|
||||
}
|
||||
}
|
||||
|
||||
isaac(); /* fill in the first set of results */
|
||||
randcnt=0; /* prepare to use the first set of results */
|
||||
}
|
||||
|
||||
|
||||
// Get a random 32-bit value 0..MAXINT
|
||||
ub4 iRandom()
|
||||
{
|
||||
ub4 r = randrsl[randcnt];
|
||||
++randcnt;
|
||||
if (randcnt >255) {
|
||||
isaac();
|
||||
randcnt = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// Get a random character in printable ASCII range
|
||||
char iRandA()
|
||||
{
|
||||
return iRandom() % 95 + 32;
|
||||
}
|
||||
|
||||
|
||||
// Seed ISAAC with a string
|
||||
void iSeed(char *seed, int flag)
|
||||
{
|
||||
register ub4 i,m;
|
||||
for (i=0; i<256; i++) mm[i]=0;
|
||||
m = strlen(seed);
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
// in case seed has less than 256 elements
|
||||
if (i>m) randrsl[i]=0; else randrsl[i] = seed[i];
|
||||
}
|
||||
// initialize ISAAC with seed
|
||||
randinit(flag);
|
||||
}
|
||||
|
||||
|
||||
// maximum length of message
|
||||
#define MAXMSG 4096
|
||||
#define MOD 95
|
||||
#define START 32
|
||||
// cipher modes for Caesar
|
||||
enum ciphermode {
|
||||
mEncipher, mDecipher, mNone
|
||||
};
|
||||
|
||||
|
||||
// XOR cipher on random stream. Output: ASCII string
|
||||
char v[MAXMSG];
|
||||
char* Vernam(char *msg)
|
||||
{
|
||||
register ub4 i,l;
|
||||
l = strlen(msg);
|
||||
// zeroise v
|
||||
memset(v,'\0',l+1);
|
||||
// XOR message
|
||||
for (i=0; i<l; i++)
|
||||
v[i] = iRandA() ^ msg[i];
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Caesar-shift a printable character
|
||||
char Caesar(enum ciphermode m, char ch, char shift, char modulo, char start)
|
||||
{
|
||||
register int n;
|
||||
if (m == mDecipher) shift = -shift;
|
||||
n = (ch-start) + shift;
|
||||
n = n % modulo;
|
||||
if (n<0) n += modulo;
|
||||
return start+n;
|
||||
}
|
||||
|
||||
// Caesar-shift a string on a pseudo-random stream
|
||||
char c[MAXMSG];
|
||||
char* CaesarStr(enum ciphermode m, char *msg, char modulo, char start)
|
||||
{
|
||||
register ub4 i,l;
|
||||
l = strlen(msg);
|
||||
// zeroise c
|
||||
memset(c,'\0',l+1);
|
||||
// Caesar-shift message
|
||||
for (i=0; i<l; i++)
|
||||
c[i] = Caesar(m, msg[i], iRandA(), modulo, start);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
register ub4 n,l;
|
||||
// input: message and key
|
||||
char *msg = "a Top Secret secret";
|
||||
char *key = "this is my secret key";
|
||||
// Vernam ciphertext & plaintext
|
||||
char vctx[MAXMSG], vptx[MAXMSG];
|
||||
// Caesar ciphertext & plaintext
|
||||
char cctx[MAXMSG], cptx[MAXMSG];
|
||||
l = strlen(msg);
|
||||
// Encrypt: Vernam XOR
|
||||
iSeed(key,1);
|
||||
strcpy(vctx, Vernam(msg));
|
||||
// Encrypt: Caesar
|
||||
strcpy(cctx, CaesarStr(mEncipher, msg, MOD, START));
|
||||
// Decrypt: Vernam XOR
|
||||
iSeed(key,1);
|
||||
strcpy(vptx, Vernam(vctx));
|
||||
// Decrypt: Caesar
|
||||
strcpy(cptx, CaesarStr(mDecipher,cctx, MOD, START));
|
||||
// Program output
|
||||
printf("Message: %s\n",msg);
|
||||
printf("Key : %s\n",key);
|
||||
printf("XOR : ");
|
||||
// Output Vernam ciphertext as a string of hex digits
|
||||
for (n=0; n<l; n++) printf("%02X",vctx[n]);
|
||||
printf("\n");
|
||||
// Output Vernam decrypted plaintext
|
||||
printf("XOR dcr: %s\n",vptx);
|
||||
// Caesar
|
||||
printf("MOD : ");
|
||||
// Output Caesar ciphertext as a string of hex digits
|
||||
for (n=0; n<l; n++) printf("%02X",cctx[n]);
|
||||
printf("\n");
|
||||
// Output Caesar decrypted plaintext
|
||||
printf("MOD dcr: %s\n",cptx);
|
||||
return 0;
|
||||
}
|
||||
165
Task/The-ISAAC-Cipher/D/the-isaac-cipher.d
Normal file
165
Task/The-ISAAC-Cipher/D/the-isaac-cipher.d
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
import std.algorithm: min;
|
||||
import std.algorithm: copy;
|
||||
import std.typetuple: TypeTuple;
|
||||
import std.typecons: staticIota;
|
||||
|
||||
struct ISAAC {
|
||||
// External results.
|
||||
private uint[mm.length] randResult;
|
||||
private uint randCount;
|
||||
|
||||
// Internal state.
|
||||
private uint[256] mm;
|
||||
private uint aa, bb, cc;
|
||||
|
||||
|
||||
private void isaac() pure nothrow @safe @nogc {
|
||||
cc++; // cc just gets incremented once per mm.length results.
|
||||
bb = bb + cc; // Then combined with bb.
|
||||
|
||||
foreach (immutable i, ref mmi; mm) {
|
||||
immutable x = mm[i];
|
||||
final switch (i % 4) { // Not enforced final switch.
|
||||
case 0: aa ^= (aa << 13); break;
|
||||
case 1: aa ^= (aa >> 6); break;
|
||||
case 2: aa ^= (aa << 2); break;
|
||||
case 3: aa ^= (aa >> 16); break;
|
||||
}
|
||||
|
||||
aa = mm[(i + 128) % $] + aa;
|
||||
immutable y = mm[(x >> 2) % $] + aa + bb;
|
||||
bb = mm[(y >> 10) % $] + x;
|
||||
randResult[i] = bb;
|
||||
}
|
||||
|
||||
randCount = 0;
|
||||
}
|
||||
|
||||
|
||||
// If flag is true then use the contents of randResult to initialize mm.
|
||||
private pure nothrow @safe @nogc static void mix(ref uint[8] a) {
|
||||
alias shifts = TypeTuple!(11, 2, 8, 16, 10, 4, 8, 9);
|
||||
/*static*/ foreach (immutable i, immutable sh; shifts) {
|
||||
static if (i % 2 == 0)
|
||||
a[i] ^= a[(i + 1) % $] << sh;
|
||||
else
|
||||
a[i] ^= a[(i + 1) % $] >> sh;
|
||||
a[(i + 3) % $] += a[i];
|
||||
a[(i + 1) % $] += a[(i + 2) % $];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void randInit(bool flag)() pure nothrow @safe @nogc {
|
||||
uint[8] a = 0x9E37_79B9; // The Golden Ratio.
|
||||
aa = bb = cc = 0;
|
||||
|
||||
// Scramble it.
|
||||
/*static*/ foreach (immutable i; staticIota!(0, 4))
|
||||
mix(a);
|
||||
|
||||
// Fill in mm with messy stuff. Use all the information in the seed.
|
||||
for (size_t i = 0; i < mm.length; i += 8) {
|
||||
static if (flag)
|
||||
a[] += randResult[i .. i + 8];
|
||||
mix(a);
|
||||
mm[i .. i + 8] = a[];
|
||||
}
|
||||
|
||||
// Do a second pass to make all of the seed affect all of mm.
|
||||
static if (flag) {
|
||||
for (size_t i = 0; i < mm.length; i += 8) {
|
||||
a[] += mm[i .. i + 8];
|
||||
mix(a);
|
||||
mm[i .. i + 8] = a[];
|
||||
}
|
||||
}
|
||||
|
||||
isaac(); // Fill in the first set of results.
|
||||
randCount = 0; // Prepare to use the first set of results.
|
||||
}
|
||||
|
||||
|
||||
/// Seed ISAAC with a string.
|
||||
/// Uses only the first randResult.length ubytes.
|
||||
public void iSeed(bool flag)(in ubyte[] seed) pure nothrow @safe @nogc {
|
||||
mm[] = 0;
|
||||
randResult[] = 0;
|
||||
|
||||
immutable n = min(randResult.length, seed.length);
|
||||
copy(seed[0 .. n], randResult[0 .. n]);
|
||||
|
||||
randInit!flag(); // Initialize ISAAC with seed.
|
||||
}
|
||||
|
||||
|
||||
/// Get a random uint.
|
||||
private uint iRandom() pure nothrow @safe @nogc {
|
||||
immutable result = randResult[randCount];
|
||||
|
||||
randCount++;
|
||||
if (randCount > (randResult.length - 1)) {
|
||||
isaac();
|
||||
randCount = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// Get a random character in printable ASCII range.
|
||||
private ubyte iRandA() pure nothrow @safe @nogc {
|
||||
return iRandom() % 95 + 32;
|
||||
}
|
||||
|
||||
|
||||
/// XOR encrypt on random stream.
|
||||
/// buffer must be as large as message or larger.
|
||||
public ubyte[] vernam(in ubyte[] message, ubyte[] buffer)
|
||||
pure nothrow @safe @nogc
|
||||
in {
|
||||
assert(buffer.length >= message.length);
|
||||
} out(result) {
|
||||
assert(result.length == message.length);
|
||||
} body {
|
||||
auto v = buffer[0 .. message.length];
|
||||
|
||||
// XOR message.
|
||||
foreach (immutable i, immutable msgi; message)
|
||||
v[i] = (iRandA() ^ msgi);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/// XOR encrypt on random stream.
|
||||
public ubyte[] vernam(in ubyte[] message) pure nothrow @safe {
|
||||
return vernam(message, new ubyte[message.length]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
import std.stdio, std.string;
|
||||
|
||||
immutable message = "a Top Secret secret";
|
||||
immutable key = "this is my secret key";
|
||||
|
||||
writeln("Message : ", message);
|
||||
writeln("Key : ", key);
|
||||
|
||||
ISAAC cipher;
|
||||
|
||||
// Encrypt.
|
||||
// iSeed uses only the first ISAAC.randResult.length ubytes.
|
||||
cipher.iSeed!true(key.representation);
|
||||
const encrypted = cipher.vernam(message.representation);
|
||||
|
||||
// Output ciphertext as a string of hexadecimal digits.
|
||||
writefln("Encrypted: %(%02X%)", encrypted);
|
||||
|
||||
// Decrypt.
|
||||
cipher.iSeed!true(key.representation);
|
||||
const decrypted = cipher.vernam(encrypted);
|
||||
|
||||
writeln("Decrypted: ", decrypted.assumeUTF);
|
||||
}
|
||||
198
Task/The-ISAAC-Cipher/Delphi/the-isaac-cipher.delphi
Normal file
198
Task/The-ISAAC-Cipher/Delphi/the-isaac-cipher.delphi
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
{$apptype console}
|
||||
PROGRAM RosettaIsaac;
|
||||
USES SysUtils;
|
||||
|
||||
// TASK globals
|
||||
VAR msg : STRING = 'a Top Secret secret';
|
||||
VAR key : STRING = 'this is my secret key';
|
||||
VAR xctx: STRING = ''; // XOR ciphertext
|
||||
VAR mctx: STRING = ''; // MOD ciphertext
|
||||
|
||||
// ISAAC globals
|
||||
// external results
|
||||
VAR randrsl: ARRAY[0..256] OF CARDINAL;
|
||||
VAR randcnt: cardinal;
|
||||
// internal state
|
||||
VAR mm: ARRAY[0..256] OF CARDINAL;
|
||||
VAR 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
|
||||
bb := bb + cc; // then combined with bb
|
||||
|
||||
FOR i := 0 TO 255 DO 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;
|
||||
// this reset was not in original readable.c!
|
||||
randcnt:=0; // prepare to use the first set of results
|
||||
END; {Isaac}
|
||||
|
||||
|
||||
// if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
|
||||
PROCEDURE mix(VAR a,b,c,d,e,f,g,h: CARDINAL);
|
||||
BEGIN
|
||||
a := a 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:=a+randrsl[i ]; b:=b+randrsl[i+1]; c:=c+randrsl[i+2]; d:=d+randrsl[i+3];
|
||||
e:=e+randrsl[i+4]; f:=f+randrsl[i+5]; g:=g+randrsl[i+6]; h:=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:=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:=a+mm[i ]; b:=b+mm[i+1]; c:=c+mm[i+2]; d:=d+mm[i+3];
|
||||
e:=e+mm[i+4]; f:=f+mm[i+5]; g:=g+mm[i+6]; h:=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:=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; {randinit}
|
||||
|
||||
|
||||
{ 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
|
||||
result := 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
|
||||
result := iRandom mod 95 + 32;
|
||||
END;
|
||||
|
||||
|
||||
{ convert an ASCII string to a hexadecimal string }
|
||||
FUNCTION ascii2hex(s: STRING): STRING;
|
||||
VAR i,l: CARDINAL;
|
||||
BEGIN
|
||||
result := '';
|
||||
l := Length(s);
|
||||
FOR i := 1 TO l DO
|
||||
result := result + IntToHex(ord(s[i]),2);
|
||||
END;
|
||||
|
||||
|
||||
{ XOR encrypt on random stream. Output: string of hex chars }
|
||||
FUNCTION Vernam(msg: STRING): STRING;
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
result := '';
|
||||
FOR i := 1 to length(msg) DO
|
||||
result := result + chr(iRandA xor ord(msg[i]));
|
||||
result := ascii2hex(result);
|
||||
END;
|
||||
|
||||
|
||||
{ Get position of the letter in chosen alphabet }
|
||||
FUNCTION letternum(letter, start: CHAR): byte;
|
||||
BEGIN
|
||||
result := (ord(letter)-ord(start));
|
||||
END;
|
||||
|
||||
|
||||
{ Caesar-shift a character <shift> places: Generalized Vigenere }
|
||||
FUNCTION Caesar(ch: CHAR; shift, modulo: INTEGER; start: CHAR): CHAR;
|
||||
VAR n: INTEGER;
|
||||
BEGIN
|
||||
n := letternum(ch,start) + shift;
|
||||
n := n MOD modulo;
|
||||
result := chr(ord(start)+n);
|
||||
END;
|
||||
|
||||
{ Vigenere mod 95 encryption. Output: string of hex chars }
|
||||
FUNCTION Vigenere(msg: STRING): STRING;
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
result := '';
|
||||
FOR i := 1 to length(msg) DO
|
||||
result := result + Caesar(msg[i],iRandA,95,' ');
|
||||
result := ascii2hex(result);
|
||||
END;
|
||||
|
||||
|
||||
BEGIN
|
||||
// 1) seed ISAAC with the key
|
||||
iSeed(key,true);
|
||||
// 2) Vernam XOR encryption
|
||||
xctx := Vernam(msg);
|
||||
// 3) MOD encryption
|
||||
mctx := Vigenere(msg);
|
||||
// program output
|
||||
Writeln('Message: ',msg);
|
||||
Writeln('Key : ',key);
|
||||
Writeln('XOR : ',xctx);
|
||||
Writeln('MOD : ',mctx);
|
||||
END.
|
||||
119
Task/The-ISAAC-Cipher/Go/the-isaac-cipher.go
Normal file
119
Task/The-ISAAC-Cipher/Go/the-isaac-cipher.go
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
msg = "a Top Secret secret"
|
||||
key = "this is my secret key"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var z state
|
||||
z.seed(key)
|
||||
fmt.Println("Message: ", msg)
|
||||
fmt.Println("Key : ", key)
|
||||
fmt.Println("XOR : ", z.vernam(msg))
|
||||
}
|
||||
|
||||
type state struct {
|
||||
aa, bb, cc uint32
|
||||
mm [256]uint32
|
||||
randrsl [256]uint32
|
||||
randcnt int
|
||||
}
|
||||
|
||||
func (z *state) isaac() {
|
||||
z.cc++
|
||||
z.bb += z.cc
|
||||
for i, x := range z.mm {
|
||||
switch i % 4 {
|
||||
case 0:
|
||||
z.aa = z.aa ^ z.aa<<13
|
||||
case 1:
|
||||
z.aa = z.aa ^ z.aa>>6
|
||||
case 2:
|
||||
z.aa = z.aa ^ z.aa<<2
|
||||
case 3:
|
||||
z.aa = z.aa ^ z.aa>>16
|
||||
}
|
||||
z.aa += z.mm[(i+128)%256]
|
||||
y := z.mm[x>>2%256] + z.aa + z.bb
|
||||
z.mm[i] = y
|
||||
z.bb = z.mm[y>>10%256] + x
|
||||
z.randrsl[i] = z.bb
|
||||
}
|
||||
}
|
||||
|
||||
func (z *state) randInit() {
|
||||
const gold = uint32(0x9e3779b9)
|
||||
a := [8]uint32{gold, gold, gold, gold, gold, gold, gold, gold}
|
||||
mix1 := func(i int, v uint32) {
|
||||
a[i] ^= v
|
||||
a[(i+3)%8] += a[i]
|
||||
a[(i+1)%8] += a[(i+2)%8]
|
||||
}
|
||||
mix := func() {
|
||||
mix1(0, a[1]<<11)
|
||||
mix1(1, a[2]>>2)
|
||||
mix1(2, a[3]<<8)
|
||||
mix1(3, a[4]>>16)
|
||||
mix1(4, a[5]<<10)
|
||||
mix1(5, a[6]>>4)
|
||||
mix1(6, a[7]<<8)
|
||||
mix1(7, a[0]>>9)
|
||||
}
|
||||
for i := 0; i < 4; i++ {
|
||||
mix()
|
||||
}
|
||||
for i := 0; i < 256; i += 8 {
|
||||
for j, rj := range z.randrsl[i : i+8] {
|
||||
a[j] += rj
|
||||
}
|
||||
mix()
|
||||
for j, aj := range a {
|
||||
z.mm[i+j] = aj
|
||||
}
|
||||
}
|
||||
for i := 0; i < 256; i += 8 {
|
||||
for j, mj := range z.mm[i : i+8] {
|
||||
a[j] += mj
|
||||
}
|
||||
mix()
|
||||
for j, aj := range a {
|
||||
z.mm[i+j] = aj
|
||||
}
|
||||
}
|
||||
z.isaac()
|
||||
}
|
||||
|
||||
func (z *state) seed(seed string) {
|
||||
for i, r := range seed {
|
||||
if i == 256 {
|
||||
break
|
||||
}
|
||||
z.randrsl[i] = uint32(r)
|
||||
}
|
||||
z.randInit()
|
||||
}
|
||||
|
||||
func (z *state) random() (r uint32) {
|
||||
r = z.randrsl[z.randcnt]
|
||||
z.randcnt++
|
||||
if z.randcnt == 256 {
|
||||
z.isaac()
|
||||
z.randcnt = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *state) randA() byte {
|
||||
return byte(z.random()%95 + 32)
|
||||
}
|
||||
|
||||
func (z *state) vernam(msg string) string {
|
||||
b := []byte(msg)
|
||||
for i := range b {
|
||||
b[i] ^= z.randA()
|
||||
}
|
||||
return fmt.Sprintf("%X", b)
|
||||
}
|
||||
127
Task/The-ISAAC-Cipher/Haskell/the-isaac-cipher.hs
Normal file
127
Task/The-ISAAC-Cipher/Haskell/the-isaac-cipher.hs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import Data.Array
|
||||
import Data.Bits
|
||||
import Data.Char
|
||||
import Data.Word
|
||||
import Data.List
|
||||
import Numeric
|
||||
|
||||
type IArray = Array Word32 Word32
|
||||
|
||||
data IsaacState = IState
|
||||
{ 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
|
||||
|
||||
toHex :: Char -> String
|
||||
toHex c = showHex (fromEnum c) ""
|
||||
|
||||
hexify :: String -> String
|
||||
hexify = map toUpper . concatMap toHex
|
||||
|
||||
toNum :: Char -> Word32
|
||||
toNum = fromIntegral . fromEnum
|
||||
|
||||
toChar :: Word32 -> Char
|
||||
toChar = toEnum . fromIntegral
|
||||
|
||||
golden :: Word32
|
||||
golden = 0x9e3779b9
|
||||
|
||||
-- Mix up an ordering of words.
|
||||
mix :: [Word32] -> [Word32]
|
||||
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', e, f, g, h, a']
|
||||
where a' = a `xor` (b `shift` x)
|
||||
|
||||
-- Generate the next 256 words.
|
||||
isaac :: IsaacState -> IsaacState
|
||||
isaac (IState rsl _ m a b c) = IState rsl' 0 m' a' b' c'
|
||||
where
|
||||
c' = c + 1
|
||||
(rsl', m', a', b') = foldl aux (rsl, m, a, b) $ zip [0..255] $ cycle [13, -6, 2, -16]
|
||||
aux (rsl, m, a, b) (i, s) = (rsl', m', a', b')
|
||||
where x = m ! i
|
||||
a' = (a `xor` (a `shift` s)) + m ! ((i + 128) `mod` 256)
|
||||
y = a' + b + m ! ((x `shift` (-2)) `mod` 256)
|
||||
m' = m // [(i,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' 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' = mix $ if flag
|
||||
then zipWith (+) set rslH
|
||||
else set
|
||||
in set' ++ iter flag set' rslT
|
||||
randrsl' = randrsl state
|
||||
firstPass = iter flag firstSet $ elems randrsl'
|
||||
set' = drop (256 - 8) firstPass
|
||||
secondPass = if flag
|
||||
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
|
||||
|
||||
-- Produce a random word and the next state from the given state.
|
||||
random :: IsaacState -> (Word32, IsaacState)
|
||||
random state@(IState rsl cnt m a b c) =
|
||||
let r = rsl ! cnt
|
||||
state' = if cnt + 1 > 255
|
||||
then isaac $ IState rsl 0 m a b c
|
||||
else IState rsl (cnt + 1) m a b c
|
||||
in (r, state')
|
||||
|
||||
-- Produce a stream of random words from the given state.
|
||||
randoms :: IsaacState -> [Word32]
|
||||
randoms = unfoldr $ Just . random
|
||||
|
||||
-- Produce a random printable/typable character in the ascii range
|
||||
-- and the next state from the given state.
|
||||
randA :: IsaacState -> (Char, IsaacState)
|
||||
randA state =
|
||||
let (r, state') = random state
|
||||
in (toEnum $ fromIntegral $ (r `mod` 95) + 32, state')
|
||||
|
||||
-- Produce a stream of printable characters from the given state.
|
||||
randAs :: IsaacState -> String
|
||||
randAs = unfoldr $ Just . randA
|
||||
|
||||
-- Vernam encode/decode a string with the given state.
|
||||
vernam :: IsaacState -> String -> String
|
||||
vernam state msg = map toChar $ zipWith xor msg' randAs'
|
||||
where
|
||||
msg' = map toNum msg
|
||||
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
|
||||
161
Task/The-ISAAC-Cipher/Haxe/the-isaac-cipher.haxe
Normal file
161
Task/The-ISAAC-Cipher/Haxe/the-isaac-cipher.haxe
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
package src ;
|
||||
import haxe.Int32;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.ds.Vector;
|
||||
|
||||
typedef Ub4 = Int32;
|
||||
|
||||
enum Ciphermode {
|
||||
mEncipher;
|
||||
mDecipher;
|
||||
mNone;
|
||||
}
|
||||
|
||||
class Isaac
|
||||
{
|
||||
public var randrsl = new Vector<Ub4>(256);
|
||||
public var randcnt:Ub4;
|
||||
|
||||
var mm = new Vector<Ub4>(256);
|
||||
var aa:Ub4 = 0;
|
||||
var bb:Ub4 = 0;
|
||||
var cc:Ub4 = 0;
|
||||
|
||||
public function isaac():Void {
|
||||
var x, y;
|
||||
cc++;
|
||||
bb += cc;
|
||||
for (i in 0...256) {
|
||||
x = mm[i];
|
||||
aa ^= switch (i % 4) {//Haxe unification
|
||||
case 0: aa << 13;
|
||||
case 1: aa >>> 6;
|
||||
case 2: aa << 2;
|
||||
case 3: aa >>> 16;
|
||||
default: 0;//never happens
|
||||
}
|
||||
aa = mm[(i + 128) % 256] + aa;
|
||||
mm[i] = y = mm[(x >>> 2) % 256] + aa + bb;
|
||||
randrsl[i] = bb = mm[(y >>> 10) % 256] + x;
|
||||
}
|
||||
}
|
||||
|
||||
macro static function mix(a:ExprOf<Ub4>, b:ExprOf<Ub4>, c:ExprOf<Ub4>, d:ExprOf<Ub4>,
|
||||
e:ExprOf<Ub4>, f:ExprOf<Ub4>, g:ExprOf<Ub4>, h:ExprOf<Ub4>) {
|
||||
return macro {
|
||||
$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;
|
||||
};
|
||||
}
|
||||
|
||||
public function randinit(flag:Bool):Void {
|
||||
var a, b, c, d, e, f, g, h, i;
|
||||
aa = bb = cc = (0:Ub4);
|
||||
a = b = c = d = e = f = g = h = (0x9e3779b9:Ub4); /* the golden ratio */
|
||||
for (i in 0...4) mix(a, b, c, d, e, f, g, h); /* scramble it */
|
||||
i = 0;
|
||||
while (i < 256) { /* fill in mm[] with messy stuff */
|
||||
if (flag) { /* use all the information in the seed */
|
||||
a += randrsl[i]; b += randrsl[i + 1];
|
||||
c += randrsl[i + 2]; d += randrsl[i + 3];
|
||||
e += randrsl[i + 4]; f += randrsl[i + 5];
|
||||
g += randrsl[i + 6]; h += randrsl[i + 7];
|
||||
}
|
||||
mix(a, b, c, d, e, f, g, h);
|
||||
mm[i] = a; mm[i + 1] = b; mm[i + 2] = c; mm[i + 3] = d;
|
||||
mm[i + 4] = e; mm[i + 5] = f; mm[i + 6] = g; mm[i + 7] = h;
|
||||
i += 8;
|
||||
}
|
||||
if (flag) { /* do a second pass to make all of the seed affect all of mm */
|
||||
i = 0;
|
||||
while (i<256) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
isaac();
|
||||
randcnt = 0;
|
||||
}
|
||||
|
||||
public function iRandom():Ub4 {
|
||||
var r = randrsl[randcnt];
|
||||
++randcnt;
|
||||
if (randcnt > 255) {
|
||||
isaac();
|
||||
randcnt = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public function iRandA():Int32 {
|
||||
return cast(cast(iRandom(),UInt) % 95 + 32,Int32);
|
||||
}
|
||||
|
||||
public function iSeed(seed:String, flag:Bool):Void {
|
||||
var m=seed.length-1;
|
||||
for (i in 0...256) mm[i] = 0;
|
||||
for (i in 0...256) if (i > m) randrsl[i] = 0; else randrsl[i] = seed.charCodeAt(i);
|
||||
randinit(flag);
|
||||
}
|
||||
|
||||
inline static var modC = 95;
|
||||
inline static var startC = 32;
|
||||
|
||||
public function vernam (msg:String):String {
|
||||
var v="";
|
||||
for (i in 0...msg.length) v += String.fromCharCode(iRandA() ^ msg.charCodeAt(i));
|
||||
return v;
|
||||
}
|
||||
|
||||
public function caesar(m:Ciphermode, ch:Int32, shift:Int32,
|
||||
modulo:Int32, start:Int32):String {
|
||||
var n:Int32;
|
||||
if (m == mDecipher) n = ch - start - cast(shift,Int32);
|
||||
else n = ch - start + cast(shift,Int32);
|
||||
n %= modulo;
|
||||
if (n < 0) n += modulo;
|
||||
return String.fromCharCode(start + cast(n,Ub4));
|
||||
}
|
||||
|
||||
public function caesarStr(m:Ciphermode, msg:String, modulo:Int32, start:Int32):String {
|
||||
var c = "";
|
||||
for (i in 0...msg.length)
|
||||
c += caesar(m,msg.charCodeAt(i),iRandA(),modulo,start);
|
||||
return c;
|
||||
}
|
||||
|
||||
static public function main():Void {
|
||||
var msg = "a Top Secret secret";
|
||||
var key = "this is my secret key";
|
||||
var cIsaac = new Isaac();
|
||||
var vctx, vptx, cctx, cptx;
|
||||
cIsaac.iSeed(key, true);
|
||||
vctx = cIsaac.vernam(msg);
|
||||
cctx = cIsaac.caesarStr(mEncipher, msg, modC, startC);
|
||||
|
||||
cIsaac.iSeed(key, true);
|
||||
vptx = cIsaac.vernam(vctx);
|
||||
cptx = cIsaac.caesarStr(mDecipher, cctx, modC, startC);
|
||||
|
||||
Sys.println("Message: " + msg);
|
||||
Sys.println("Key : " + key);
|
||||
var hex = "";
|
||||
for (i in 0...vctx.length) hex += StringTools.hex(vctx.charCodeAt(i), 2);
|
||||
Sys.println("XOR : " + hex);
|
||||
Sys.println("XOR dcr: " + vptx);
|
||||
hex = "";
|
||||
for (i in 0...cctx.length) hex += StringTools.hex(cctx.charCodeAt(i), 2);
|
||||
Sys.println("MOD : " + hex);
|
||||
Sys.println("MOD dcr: " + cptx);
|
||||
}
|
||||
}
|
||||
225
Task/The-ISAAC-Cipher/Java/the-isaac-cipher.java
Normal file
225
Task/The-ISAAC-Cipher/Java/the-isaac-cipher.java
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class IsaacRandom extends Random {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int[] randResult = new int[256]; // output of last generation
|
||||
private int valuesUsed; // the number of values already used up from randResult
|
||||
|
||||
// internal generator state
|
||||
private final int[] mm = new int[256];
|
||||
private int aa, bb, cc;
|
||||
|
||||
public IsaacRandom() {
|
||||
super(0);
|
||||
init(null);
|
||||
}
|
||||
|
||||
public IsaacRandom(int[] seed) {
|
||||
super(0);
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
public IsaacRandom(String seed) {
|
||||
super(0);
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
private void generateMoreResults() {
|
||||
cc++;
|
||||
bb += cc;
|
||||
|
||||
for (int i=0; i<256; i++) {
|
||||
int x = mm[i];
|
||||
switch (i&3) {
|
||||
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] + aa;
|
||||
int y = mm[i] = mm[(x>>>2) & 0xFF] + aa + bb;
|
||||
randResult[i] = bb = mm[(y>>>10) & 0xFF] + x;
|
||||
}
|
||||
|
||||
valuesUsed = 0;
|
||||
}
|
||||
|
||||
private static void mix(int[] s) {
|
||||
s[0]^=s[1]<<11; s[3]+=s[0]; s[1]+=s[2];
|
||||
s[1]^=s[2]>>>2; s[4]+=s[1]; s[2]+=s[3];
|
||||
s[2]^=s[3]<<8; s[5]+=s[2]; s[3]+=s[4];
|
||||
s[3]^=s[4]>>>16; s[6]+=s[3]; s[4]+=s[5];
|
||||
s[4]^=s[5]<<10; s[7]+=s[4]; s[5]+=s[6];
|
||||
s[5]^=s[6]>>>4; s[0]+=s[5]; s[6]+=s[7];
|
||||
s[6]^=s[7]<<8; s[1]+=s[6]; s[7]+=s[0];
|
||||
s[7]^=s[0]>>>9; s[2]+=s[7]; s[0]+=s[1];
|
||||
}
|
||||
|
||||
private void init(int[] seed) {
|
||||
if (seed != null && seed.length != 256) {
|
||||
seed = Arrays.copyOf(seed, 256);
|
||||
}
|
||||
aa = bb = cc = 0;
|
||||
int[] initState = new int[8];
|
||||
Arrays.fill(initState, 0x9e3779b9); // the golden ratio
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
mix(initState);
|
||||
}
|
||||
|
||||
for (int i=0; i<256; i+=8) {
|
||||
if (seed != null) {
|
||||
for (int j=0; j<8; j++) {
|
||||
initState[j] += seed[i+j];
|
||||
}
|
||||
}
|
||||
mix(initState);
|
||||
for (int j=0; j<8; j++) {
|
||||
mm[i+j] = initState[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (seed != null) {
|
||||
for (int i=0; i<256; i+=8) {
|
||||
for (int j=0; j<8; j++) {
|
||||
initState[j] += mm[i+j];
|
||||
}
|
||||
|
||||
mix(initState);
|
||||
|
||||
for (int j=0; j<8; j++) {
|
||||
mm[i+j] = initState[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valuesUsed = 256; // Make sure generateMoreResults() will be called by the next next() call.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int next(int bits) {
|
||||
if (valuesUsed == 256) {
|
||||
generateMoreResults();
|
||||
assert(valuesUsed == 0);
|
||||
}
|
||||
int value = randResult[valuesUsed];
|
||||
valuesUsed++;
|
||||
return value >>> (32-bits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
super.setSeed(0);
|
||||
if (mm == null) {
|
||||
// We're being called from the superclass constructor. We don't have our
|
||||
// state arrays instantiated yet, and we're going to do proper initialization
|
||||
// later in our own constructor anyway, so just ignore this call.
|
||||
return;
|
||||
}
|
||||
int[] arraySeed = new int[256];
|
||||
arraySeed[0] = (int) (seed & 0xFFFFFFFF);
|
||||
arraySeed[1] = (int) (seed >>> 32);
|
||||
init(arraySeed);
|
||||
}
|
||||
|
||||
public synchronized void setSeed(int[] seed) {
|
||||
super.setSeed(0);
|
||||
init(seed);
|
||||
}
|
||||
|
||||
public synchronized void setSeed(String seed) {
|
||||
super.setSeed(0);
|
||||
char[] charSeed = seed.toCharArray();
|
||||
int[] intSeed = new int[charSeed.length];
|
||||
for (int i=0; i<charSeed.length; i++) {
|
||||
intSeed[i] = charSeed[i];
|
||||
}
|
||||
init(intSeed);
|
||||
}
|
||||
|
||||
public int randomChar() {
|
||||
long unsignedNext = nextInt() & 0xFFFFFFFFL; // The only way to force unsigned modulo behavior in Java is to convert to a long and mask off the copies of the sign bit.
|
||||
return (int) (unsignedNext % 95 + 32); // nextInt(95) + 32 would yield a more equal distribution, but then we would be incompatible with the original C code
|
||||
}
|
||||
|
||||
public enum CipherMode { ENCIPHER, DECIPHER, NONE };
|
||||
|
||||
public byte[] vernamCipher(byte[] input) {
|
||||
byte[] result = new byte[input.length];
|
||||
for (int i=0; i<input.length; i++) {
|
||||
result[i] = (byte) (randomChar() ^ input[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte caesarShift(CipherMode mode, byte ch, int shift, byte modulo, byte start) {
|
||||
if (mode == CipherMode.DECIPHER) {
|
||||
shift = -shift;
|
||||
}
|
||||
int n = (ch-start) + shift;
|
||||
n %= modulo;
|
||||
if (n<0) {
|
||||
n += modulo;
|
||||
}
|
||||
return (byte) (start + n);
|
||||
}
|
||||
|
||||
public byte[] caesarCipher(CipherMode mode, byte[] input, byte modulo, byte start) {
|
||||
byte[] result = new byte[input.length];
|
||||
for (int i=0; i<input.length; i++) {
|
||||
result[i] = caesarShift(mode, input[i], randomChar(), modulo, start);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String toHexString(byte[] input) {
|
||||
// NOTE: This method prefers simplicity over performance.
|
||||
StringBuilder sb = new StringBuilder(input.length*2);
|
||||
for (byte b : input) {
|
||||
sb.append(String.format("%02X", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final byte MOD = 95;
|
||||
final byte START = 32;
|
||||
|
||||
String secret = "a Top Secret secret";
|
||||
String key = "this is my secret key";
|
||||
|
||||
IsaacRandom random = new IsaacRandom(key);
|
||||
byte[] vernamResult;
|
||||
byte[] caesarResult;
|
||||
String vernamDecrypted;
|
||||
String caesarDecrypted;
|
||||
try {
|
||||
vernamResult = random.vernamCipher(secret.getBytes("ASCII"));
|
||||
caesarResult = random.caesarCipher(CipherMode.ENCIPHER, secret.getBytes("ASCII"), MOD, START);
|
||||
random.setSeed(key);
|
||||
vernamDecrypted = new String(random.vernamCipher(vernamResult), "ASCII");
|
||||
caesarDecrypted = new String(random.caesarCipher(CipherMode.DECIPHER, caesarResult, MOD, START), "ASCII");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError("JVM isn't conforming - ASCII encoding isn't available");
|
||||
}
|
||||
System.out.printf("Message: %s\n", secret);
|
||||
System.out.printf("Key : %s\n", key);
|
||||
System.out.printf("XOR : %s\n", toHexString(vernamResult));
|
||||
System.out.printf("XOR dcr: %s\n", vernamDecrypted);
|
||||
System.out.printf("MOD : %s\n", toHexString(caesarResult));
|
||||
System.out.printf("MOD dcr: %s\n", caesarDecrypted);
|
||||
}
|
||||
}
|
||||
213
Task/The-ISAAC-Cipher/Pascal/the-isaac-cipher.pascal
Normal file
213
Task/The-ISAAC-Cipher/Pascal/the-isaac-cipher.pascal
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
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)
|
||||
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;
|
||||
|
||||
|
||||
PROCEDURE Isaac;
|
||||
VAR i,x,y: CARDINAL;
|
||||
BEGIN
|
||||
cc := cc + 1; // cc just gets incremented once per 256 results
|
||||
bb := bb + cc; // then combined with bb
|
||||
|
||||
FOR i := 0 TO 255 DO BEGIN
|
||||
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;
|
||||
// this reset was not in the original readable.c
|
||||
randcnt:=0; // prepare to use the first set of results
|
||||
END; {Isaac}
|
||||
|
||||
|
||||
// if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
|
||||
PROCEDURE mix(VAR a,b,c,d,e,f,g,h: CARDINAL);
|
||||
BEGIN
|
||||
a := a 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; {randinit}
|
||||
|
||||
|
||||
{ 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,l: CARDINAL;
|
||||
BEGIN
|
||||
ascii2hex := '';
|
||||
l := Length(s);
|
||||
FOR i := 1 TO l DO
|
||||
ascii2hex += Dec2Numb(ord(s[i]),2,16);
|
||||
END;
|
||||
|
||||
|
||||
{ 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;
|
||||
|
||||
|
||||
{ Get position of the letter in chosen alphabet }
|
||||
FUNCTION letternum(letter, start: CHAR): byte;
|
||||
BEGIN
|
||||
letternum := (ord(letter)-ord(start));
|
||||
END;
|
||||
|
||||
|
||||
{ Caesar-shift a character <shift> places: Generalized Vigenere }
|
||||
FUNCTION Caesar(m: iMode; ch: CHAR; shift, modulo: INTEGER; start: CHAR): CHAR;
|
||||
VAR n: INTEGER;
|
||||
BEGIN
|
||||
IF m = iDecrypt THEN shift := -shift;
|
||||
n := letternum(ch,start) + shift;
|
||||
n := n MOD modulo;
|
||||
IF n<0 THEN n += modulo;
|
||||
Caesar := chr(ord(start)+n);
|
||||
END;
|
||||
|
||||
|
||||
{ Vigenere mod 95 encryption & decryption. Output: ASCII string }
|
||||
FUNCTION Vigenere(msg: STRING; m: iMode): STRING;
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
Vigenere := '';
|
||||
FOR i := 1 to length(msg) DO
|
||||
Vigenere += Caesar(m,msg[i],iRandA,95,' ');
|
||||
END;
|
||||
|
||||
|
||||
BEGIN
|
||||
// 1) seed ISAAC with the key
|
||||
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.
|
||||
31
Task/The-ISAAC-Cipher/Perl/the-isaac-cipher.pl
Normal file
31
Task/The-ISAAC-Cipher/Perl/the-isaac-cipher.pl
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use warnings;
|
||||
use strict;
|
||||
use Math::Random::ISAAC;
|
||||
|
||||
my $message = "a Top Secret secret";
|
||||
my $key = "this is my secret key";
|
||||
|
||||
my $enc = xor_isaac($key, $message);
|
||||
my $dec = xor_isaac($key, join "", pack "H*", $enc);
|
||||
|
||||
print "Message: $message\n";
|
||||
print "Key : $key\n";
|
||||
print "XOR : $enc\n";
|
||||
print "XOR dcr: ", join("", pack "H*", $dec), "\n";
|
||||
|
||||
sub xor_isaac {
|
||||
my($key, $msg) = @_;
|
||||
|
||||
# Make an ISAAC stream with the desired seed
|
||||
my $rng = Math::Random::ISAAC->new( map { ord } split "",$key );
|
||||
|
||||
# Get ISAAC output in the order the task wants
|
||||
my @iranda = map { $_ % 95 + 32 } # Alpha-tize as the task desires
|
||||
reverse # MRI gives state from the end
|
||||
map { $rng->irand } # Get random inputs...
|
||||
0..255; # a state chunk at a time
|
||||
# Encode:
|
||||
join "", map { sprintf "%02X",$_ } # join hex digits
|
||||
map { ord($_) ^ shift(@iranda) } # xor it with rand char
|
||||
split "", $msg; # Take each character
|
||||
}
|
||||
105
Task/The-ISAAC-Cipher/PicoLisp/the-isaac-cipher.l
Normal file
105
Task/The-ISAAC-Cipher/PicoLisp/the-isaac-cipher.l
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
(de add32 @
|
||||
(mod32 (pass +)) )
|
||||
|
||||
(de mod32 (N)
|
||||
(& N `(hex "FFFFFFFF")) )
|
||||
|
||||
(de isaac()
|
||||
(let (Y 0 S (-13 6 -2 16 .))
|
||||
(setq *CC (add32 *CC 1))
|
||||
(setq *BB (add32 *BB *CC))
|
||||
(for (I . X) *MM
|
||||
(set (nth *MM I)
|
||||
(setq Y
|
||||
(add32
|
||||
(get *MM (inc (% (>> 2 X) 256)))
|
||||
(setq *AA
|
||||
(add32
|
||||
(x| *AA (>> (pop 'S) *AA))
|
||||
(get *MM (inc (% (+ 127 I) 256))) ) )
|
||||
*BB ) ) )
|
||||
(set (nth *RR I)
|
||||
(setq *BB
|
||||
(add32
|
||||
(get *MM (inc (% (>> 10 Y) 256)))
|
||||
X ) ) ) ) ) )
|
||||
|
||||
(de mixA()
|
||||
(let S (-11 2 -8 16 -10 4 -8 9 .)
|
||||
(for I 8
|
||||
(set (nth *A I)
|
||||
(mod32
|
||||
(x|
|
||||
(get *A I)
|
||||
(mod32
|
||||
(>>
|
||||
(pop 'S)
|
||||
(get *A (inc (% I 8))) ) ) ) ) )
|
||||
(set (nth *A (inc (% (+ 2 I) 8)))
|
||||
(add32
|
||||
(get *A (inc (% (+ 2 I) 8)))
|
||||
(get *A I) ) )
|
||||
(set (nth *A (inc (% I 8)))
|
||||
(add32
|
||||
(get *A (inc (% I 8)))
|
||||
(get *A (inc (% (inc I) 8))) ) ) ) ) )
|
||||
|
||||
(de iseed ()
|
||||
(do 4
|
||||
(mixA) )
|
||||
(for (I 1 (> 256 I) (inc 'I 8))
|
||||
(for (J I (> (+ 8 I) J) (inc J))
|
||||
(set (nth *A (inc (% (dec J) 8)))
|
||||
(add32
|
||||
(get *A (inc (% (dec J) 8)))
|
||||
(get *RR J) ) ) )
|
||||
(mixA)
|
||||
(for (J I (> (+ 8 I) J) (inc J))
|
||||
(set (nth *MM J)
|
||||
(get *A (inc (% (dec J) 8))) ) ) )
|
||||
(for (I 1 (> 256 I) (inc 'I 8))
|
||||
(for (J I (> (+ 8 I) J) (inc J))
|
||||
(set (nth *A (inc (% (dec J) 8)))
|
||||
(add32
|
||||
(get *A (inc (% (dec J) 8)))
|
||||
(get *MM J) ) ) )
|
||||
(mixA)
|
||||
(for (J I (> (+ 8 I) J) (inc J))
|
||||
(set (nth *MM J)
|
||||
(get *A (inc (% (dec J) 8))) ) ) )
|
||||
(isaac) )
|
||||
|
||||
(let
|
||||
(*AA 0
|
||||
*BB 0
|
||||
*CC 0
|
||||
*MM (need 256 0)
|
||||
*RC 0
|
||||
*RR (need
|
||||
-256
|
||||
(mapcar
|
||||
char
|
||||
(head 256 (chop "this is my secret key")) ) 0 )
|
||||
*A (need 8 `(hex "9E3779B9")) )
|
||||
(iseed)
|
||||
(println
|
||||
(pack
|
||||
(mapcar
|
||||
'((B) (pad 2 (hex B)))
|
||||
(make
|
||||
(for I (mapcar char (chop "a Top Secret secret"))
|
||||
(link
|
||||
(x|
|
||||
I
|
||||
(+
|
||||
32
|
||||
(%
|
||||
(get
|
||||
*RR
|
||||
(if (>= 256 (inc '*RC))
|
||||
*RC
|
||||
(isaac)
|
||||
(one *RC) ) )
|
||||
95 ) ) ) ) ) ) ) ) ) )
|
||||
|
||||
(bye)
|
||||
196
Task/The-ISAAC-Cipher/Python/the-isaac-cipher.py
Normal file
196
Task/The-ISAAC-Cipher/Python/the-isaac-cipher.py
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
import random
|
||||
import collections
|
||||
|
||||
INT_MASK = 0xFFFFFFFF # we use this to emulate 32-bit overflow semantics by masking off higher bits after operations
|
||||
|
||||
class IsaacRandom(random.Random):
|
||||
"""
|
||||
Random number generator using the ISAAC algorithm.
|
||||
"""
|
||||
|
||||
def seed(self, seed=None):
|
||||
"""
|
||||
Initialize internal state.
|
||||
|
||||
The seed, if given, can be a string, an integer, or an iterable that contains
|
||||
integers only. If no seed is given, a fixed default state is set up; unlike
|
||||
our superclass, this class will not attempt to randomize the seed from outside sources.
|
||||
"""
|
||||
def mix():
|
||||
init_state[0] ^= ((init_state[1]<<11)&INT_MASK); init_state[3] += init_state[0]; init_state[3] &= INT_MASK; init_state[1] += init_state[2]; init_state[1] &= INT_MASK
|
||||
init_state[1] ^= (init_state[2]>>2) ; init_state[4] += init_state[1]; init_state[4] &= INT_MASK; init_state[2] += init_state[3]; init_state[2] &= INT_MASK
|
||||
init_state[2] ^= ((init_state[3]<<8 )&INT_MASK); init_state[5] += init_state[2]; init_state[5] &= INT_MASK; init_state[3] += init_state[4]; init_state[3] &= INT_MASK
|
||||
init_state[3] ^= (init_state[4]>>16) ; init_state[6] += init_state[3]; init_state[6] &= INT_MASK; init_state[4] += init_state[5]; init_state[4] &= INT_MASK
|
||||
init_state[4] ^= ((init_state[5]<<10)&INT_MASK); init_state[7] += init_state[4]; init_state[7] &= INT_MASK; init_state[5] += init_state[6]; init_state[5] &= INT_MASK
|
||||
init_state[5] ^= (init_state[6]>>4 ) ; init_state[0] += init_state[5]; init_state[0] &= INT_MASK; init_state[6] += init_state[7]; init_state[6] &= INT_MASK
|
||||
init_state[6] ^= ((init_state[7]<<8 )&INT_MASK); init_state[1] += init_state[6]; init_state[1] &= INT_MASK; init_state[7] += init_state[0]; init_state[7] &= INT_MASK
|
||||
init_state[7] ^= (init_state[0]>>9 ) ; init_state[2] += init_state[7]; init_state[2] &= INT_MASK; init_state[0] += init_state[1]; init_state[0] &= INT_MASK
|
||||
|
||||
super().seed(0) # give a chance for the superclass to reset its state - the actual seed given to it doesn't matter
|
||||
if seed is not None:
|
||||
if isinstance(seed, str):
|
||||
seed = [ord(x) for x in seed]
|
||||
elif isinstance(seed, collections.Iterable):
|
||||
seed = [x & INT_MASK for x in seed]
|
||||
elif isinstance(seed, int):
|
||||
val = abs(seed)
|
||||
seed = []
|
||||
while val:
|
||||
seed.append(val & INT_MASK)
|
||||
val >>= 32
|
||||
else:
|
||||
raise TypeError('Seed must be string, integer or iterable of integer')
|
||||
|
||||
# make sure the seed list is exactly 256 elements long
|
||||
if len(seed)>256:
|
||||
del seed[256:]
|
||||
elif len(seed)<256:
|
||||
seed.extend([0]*(256-len(seed)))
|
||||
|
||||
self.aa = self.bb = self.cc = 0
|
||||
self.mm = []
|
||||
init_state = [0x9e3779b9]*8
|
||||
|
||||
for _ in range(4):
|
||||
mix()
|
||||
|
||||
for i in range(0, 256, 8):
|
||||
if seed is not None:
|
||||
for j in range(8):
|
||||
init_state[j] += seed[i+j]
|
||||
init_state[j] &= INT_MASK
|
||||
mix()
|
||||
self.mm += init_state
|
||||
|
||||
if seed is not None:
|
||||
for i in range(0, 256, 8):
|
||||
for j in range(8):
|
||||
init_state[j] += self.mm[i+j]
|
||||
init_state[j] &= INT_MASK
|
||||
mix()
|
||||
for j in range(8):
|
||||
self.mm[i+j] = init_state[j]
|
||||
|
||||
self.rand_count = 256
|
||||
self.rand_result = [0]*256
|
||||
|
||||
def getstate(self):
|
||||
return super().getstate(), self.aa, self.bb, self.cc, self.mm, self.rand_count, self.rand_result
|
||||
|
||||
def setstate(self, state):
|
||||
super().setstate(state[0])
|
||||
_, self.aa, self.bb, self.cc, self.mm, self.rand_count, self.rand_result = state
|
||||
|
||||
def _generate(self):
|
||||
# Generate 256 random 32-bit values and save them in an internal field.
|
||||
# The actual random functions will dish out these values to callers.
|
||||
self.cc = (self.cc + 1) & INT_MASK
|
||||
self.bb = (self.bb + self.cc) & INT_MASK
|
||||
|
||||
for i in range(256):
|
||||
x = self.mm[i]
|
||||
mod = i & 3
|
||||
if mod==0:
|
||||
self.aa ^= ((self.aa << 13) & INT_MASK)
|
||||
elif mod==1:
|
||||
self.aa ^= (self.aa >> 6)
|
||||
elif mod==2:
|
||||
self.aa ^= ((self.aa << 2) & INT_MASK)
|
||||
else: # mod == 3
|
||||
self.aa ^= (self.aa >> 16)
|
||||
self.aa = (self.mm[i^128] + self.aa) & INT_MASK
|
||||
y = self.mm[i] = (self.mm[(x>>2) & 0xFF] + self.aa + self.bb) & INT_MASK
|
||||
self.rand_result[i] = self.bb = (self.mm[(y>>10) & 0xFF] + x) & INT_MASK
|
||||
|
||||
self.rand_count = 0
|
||||
|
||||
def next_int(self):
|
||||
"""Return a random integer between 0 (inclusive) and 2**32 (exclusive)."""
|
||||
if self.rand_count == 256:
|
||||
self._generate()
|
||||
result = self.rand_result[self.rand_count]
|
||||
self.rand_count += 1
|
||||
return result
|
||||
|
||||
def getrandbits(self, k):
|
||||
"""Return a random integer between 0 (inclusive) and 2**k (exclusive)."""
|
||||
result = 0
|
||||
ints_needed = (k+31)//32
|
||||
ints_used = 0
|
||||
while ints_used < ints_needed:
|
||||
if self.rand_count == 256:
|
||||
self._generate()
|
||||
ints_to_take = min(256-self.rand_count, ints_needed)
|
||||
for val in self.rand_result[self.rand_count : self.rand_count+ints_to_take]:
|
||||
result = (result << 32) | val
|
||||
self.rand_count += ints_to_take
|
||||
ints_used += ints_to_take
|
||||
result &= ((1<<k)-1) # mask off extra bits, if any
|
||||
return result
|
||||
|
||||
def random(self):
|
||||
"""Return a random float between 0 (inclusive) and 1 (exclusive)."""
|
||||
# A double stores 53 significant bits, so scale a 53-bit integer into the [0..1) range.
|
||||
return self.getrandbits(53) * (2**-53)
|
||||
|
||||
def rand_char(self):
|
||||
"""Return a random integer from the printable ASCII range [32..126]."""
|
||||
return self.next_int() % 95 + 32
|
||||
|
||||
def vernam(self, msg):
|
||||
"""
|
||||
Encrypt/decrypt the given bytes object with the XOR algorithm, using the current generator state.
|
||||
|
||||
To decrypt an encrypted string, restore the state of the generator to the state it had
|
||||
during encryption, then call this method with the encrypted string.
|
||||
"""
|
||||
return bytes((self.rand_char() & 0xFF) ^ x for x in msg)
|
||||
|
||||
# Constants for selecting Caesar operation modes.
|
||||
ENCIPHER = 'encipher'
|
||||
DECIPHER = 'decipher'
|
||||
|
||||
@staticmethod
|
||||
def _caesar(ciphermode, ch, shift, modulo, start):
|
||||
if ciphermode == IsaacRandom.DECIPHER:
|
||||
shift = -shift
|
||||
n = ((ch-start)+shift) % modulo
|
||||
if n<0:
|
||||
n += modulo
|
||||
return start+n
|
||||
|
||||
def caesar(self, ciphermode, msg, modulo, start):
|
||||
"""
|
||||
Encrypt/decrypt a string using the Caesar algorithm.
|
||||
|
||||
For decryption to work, the generator must be in the same state it was during encryption,
|
||||
and the same modulo and start parameters must be used.
|
||||
|
||||
ciphermode must be one of IsaacRandom.ENCIPHER or IsaacRandom.DECIPHER.
|
||||
"""
|
||||
return bytes(self._caesar(ciphermode, ch, self.rand_char(), modulo, start) for ch in msg)
|
||||
|
||||
if __name__=='__main__':
|
||||
import binascii
|
||||
|
||||
def hexify(b):
|
||||
return binascii.hexlify(b).decode('ascii').upper()
|
||||
|
||||
MOD = 95
|
||||
START = 32
|
||||
|
||||
msg = 'a Top Secret secret'
|
||||
key = 'this is my secret key'
|
||||
isaac_random = IsaacRandom(key)
|
||||
vernam_encoded = isaac_random.vernam(msg.encode('ascii'))
|
||||
caesar_encoded = isaac_random.caesar(IsaacRandom.ENCIPHER, msg.encode('ascii'), MOD, START)
|
||||
isaac_random.seed(key)
|
||||
vernam_decoded = isaac_random.vernam(vernam_encoded).decode('ascii')
|
||||
caesar_decoded = isaac_random.caesar(IsaacRandom.DECIPHER, caesar_encoded, MOD, START).decode('ascii')
|
||||
|
||||
print('Message:', msg)
|
||||
print('Key :', key)
|
||||
print('XOR :', hexify(vernam_encoded))
|
||||
print('XOR dcr:', vernam_decoded)
|
||||
print('MOD :', hexify(caesar_encoded))
|
||||
print('MOD dcr:', caesar_decoded)
|
||||
1
Task/The-ISAAC-Cipher/README
Normal file
1
Task/The-ISAAC-Cipher/README
Normal file
|
|
@ -0,0 +1 @@
|
|||
Data source: http://rosettacode.org/wiki/The_ISAAC_Cipher
|
||||
208
Task/The-ISAAC-Cipher/REXX/the-isaac-cipher-1.rexx
Normal file
208
Task/The-ISAAC-Cipher/REXX/the-isaac-cipher-1.rexx
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/* REXX ---------------------------------------------------------------
|
||||
* 24.07.2014 Walter Pachl translated from Pascal
|
||||
* extend with decryption (following Pascal)
|
||||
* 25.07.2014 WP changed i+=8 to I=I+8 (courtesy GS)
|
||||
* 26.07-2014 WP removed extraneous semicolons
|
||||
*--------------------------------------------------------------------*/
|
||||
Numeric Digits 32
|
||||
aa=0
|
||||
bb=0
|
||||
cc=0
|
||||
mm.=0
|
||||
randcnt=0
|
||||
randrsl.=0
|
||||
msg='a Top Secret secret'
|
||||
key='this is my secret key'
|
||||
iMode='iEncrypt'
|
||||
|
||||
Call iSeed key,1 /* 1) seed ISAAC with the key */
|
||||
xctx=Vernam(msg) /* 2) Vernam XOR encryption */
|
||||
mode='iEncrypt'
|
||||
mctx=Vigenere(msg,mode) /* 3) MOD encryption */
|
||||
Call iSeed key,1
|
||||
xptx=Vernam(xctx) /* a) XOR (Vernam) */
|
||||
mode='iDecrypt'
|
||||
mptx=Vigenere(mctx,mode) /* b) MOD (Vigenere) */
|
||||
/* program output */
|
||||
Say 'Message: 'msg
|
||||
Say 'Key : 'key
|
||||
Say 'XOR : 'c2x(xctx)
|
||||
Say 'MOD : 'c2x(mctx)
|
||||
Say 'XOR dcr: 'xptx
|
||||
Say 'MOD dcr: 'mptx
|
||||
Exit
|
||||
|
||||
isaac: Procedure Expose mm. aa bb cc randrsl. randcnt
|
||||
cc=add(cc,1)
|
||||
bb=add(bb,cc)
|
||||
Do i=0 To 255
|
||||
x=mm.i
|
||||
im4=i//4
|
||||
Select
|
||||
When im4=0 Then aa=xor(aa,shl(aa,13))
|
||||
When im4=1 Then aa=xor(aa,shr(aa, 6))
|
||||
When im4=2 Then aa=xor(aa,shl(aa, 2))
|
||||
When im4=3 Then aa=xor(aa,shr(aa,16))
|
||||
End
|
||||
z=(i+128)//256
|
||||
aa=add(mm.z,aa)
|
||||
z=shr(x,2)//256
|
||||
y=add(mm.z,aa,bb)
|
||||
mm.i=y
|
||||
z=shr(y,10)//256
|
||||
bb=add(mm.z,x)
|
||||
randrsl.i=bb
|
||||
End
|
||||
randcnt=0
|
||||
Return
|
||||
|
||||
mix: Procedure Expose a b c d e f g h mm. aa bb cc randrsl. randcnt
|
||||
a=xor(a,shl(b,11)); d=add(d,a); b=add(b,c)
|
||||
b=xor(b,shr(c, 2)); e=add(e,b); c=add(c,d)
|
||||
c=xor(c,shl(d, 8)); f=add(f,c); d=add(d,e)
|
||||
d=xor(d,shr(e,16)); g=add(g,d); e=add(e,f)
|
||||
e=xor(e,shl(f,10)); h=add(h,e); f=add(f,g)
|
||||
f=xor(f,shr(g, 4)); a=add(a,f); g=add(g,h)
|
||||
g=xor(g,shl(h, 8)); b=add(b,g); h=add(h,a)
|
||||
h=xor(h,shr(a, 9)); c=add(c,h); a=add(a,b)
|
||||
Return
|
||||
|
||||
iRandInit: Procedure Expose mm. randrsl. randcnt
|
||||
Parse Arg flag
|
||||
aa=0; bb=0; cc=0
|
||||
a= 2654435769 /* $9e3779b9; // the golden ratio */
|
||||
|
||||
b=a; c=a; d=a; e=a; f=a; g=a; h=a
|
||||
|
||||
do i=0 TO 3
|
||||
Call mix
|
||||
End
|
||||
|
||||
i=0
|
||||
do until i>255 /* fill in mm[] with messy stuff */
|
||||
IF flag THEN Do /* use all the information in the seed */
|
||||
Call setix
|
||||
a=add(a,randrsl.i); b=add(b,randrsl.i1)
|
||||
c=add(c,randrsl.i2); d=add(d,randrsl.i3)
|
||||
e=add(e,randrsl.i4); f=add(f,randrsl.i5)
|
||||
g=add(g,randrsl.i6); h=add(h,randrsl.i7)
|
||||
End
|
||||
Call mix
|
||||
mm.i=a; mm.i1=b; mm.i2=c; mm.i3=d
|
||||
mm.i4=e; mm.i5=f; mm.i6=g; mm.i7=h
|
||||
i=i+8
|
||||
End
|
||||
|
||||
IF flag THEN Do /* do a second pass to make all of the seed affect all of mm */
|
||||
i=0
|
||||
do until i>255 /* fill in mm[] with messy stuff */
|
||||
Call setix
|
||||
a=add(a,mm.i); b=add(b,mm.i1); c=add(c,mm.i2); d=add(d,mm.i3)
|
||||
e=add(e,mm.i4); f=add(f,mm.i5); g=add(g,mm.i6); h=add(h,mm.i7)
|
||||
Call mix
|
||||
mm.i=a; mm.i1=b; mm.i2=c; mm.i3=d
|
||||
mm.i4=e; mm.i5=f; mm.i6=g; mm.i7=h
|
||||
i=i+8
|
||||
End
|
||||
End
|
||||
Call isaac /* fill in the first set of results */
|
||||
randcnt=0; /* prepare to use the first set of results */
|
||||
Return
|
||||
|
||||
iseed: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/*---------------------------------------------------------------------
|
||||
* Seed ISAAC with a given string.
|
||||
* The string can be any size. The first 256 values will be used.
|
||||
*--------------------------------------------------------------------*/
|
||||
Parse Arg seed,flag
|
||||
mm.=0
|
||||
m=Length(seed)-1
|
||||
Do i=0 TO 255
|
||||
IF i>m THEN /* in case seed has less than 256 elements */
|
||||
randrsl.i=0
|
||||
ELSE
|
||||
randrsl.i=c2d(substr(seed,i+1,1))
|
||||
end
|
||||
Call iRandInit flag /* initialize ISAAC with seed */
|
||||
Return
|
||||
|
||||
iRandom: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get a random 32-bit value 0..MAXINT */
|
||||
iRandom=randrsl.randcnt
|
||||
randcnt=randcnt+1
|
||||
If randcnt>255 Then Do
|
||||
Call isaac
|
||||
randcnt=0
|
||||
End
|
||||
Return irandom
|
||||
|
||||
iRandA: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get a random character in printable ASCII range */
|
||||
iRandA=iRandom()//95+32
|
||||
Return iRandA
|
||||
|
||||
xor: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
Parse Arg a,b
|
||||
ac=d2c(a,4)
|
||||
bc=d2c(b,4)
|
||||
res=c2d(bitxor(ac,bc))
|
||||
return res//4294967296
|
||||
|
||||
Vernam: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* XOR encrypt on random stream. Output: string of hex chars */
|
||||
Parse Arg msg
|
||||
Vernam=''
|
||||
Do i=1 to length(msg)
|
||||
Vernam=Vernam||d2c(xor(iRandA(),c2d(substr(msg,i,1))))
|
||||
End
|
||||
Return Vernam
|
||||
|
||||
letternum: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get position of the letter in chosen alphabet */
|
||||
Parse Arg letter,start
|
||||
letternum=c2d(letter)-c2d(start)
|
||||
Return letternum
|
||||
|
||||
Caesar: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Caesar-shift a character <shift> places: Generalized Vigenere */
|
||||
Parse Arg m,ch,shift,modulo,start
|
||||
IF m='iDecrypt' TheN shift=-shift
|
||||
n=letternum(ch,start)+shift
|
||||
n=n//modulo
|
||||
IF n<0 Then n=n+modulo
|
||||
Caesar=d2c(c2d(start)+n)
|
||||
Return Caesar
|
||||
|
||||
Vigenere: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Vigenere mod 95 encryption. Output: string of hex chars */
|
||||
Parse Arg msg,m
|
||||
Vigenere=''
|
||||
Do i=1 to length(msg)
|
||||
Vigenere=Vigenere||Caesar(m,substr(msg,i,1),iRandA(),95,' ')
|
||||
End
|
||||
Return Vigenere
|
||||
|
||||
shl: Procedure
|
||||
res=arg(1)*(2**arg(2))
|
||||
return res//4294967296
|
||||
|
||||
shr: Procedure
|
||||
res=arg(1)%(2**arg(2))
|
||||
return res//4294967296
|
||||
|
||||
setix:
|
||||
i1=i+1
|
||||
i2=i+2
|
||||
i3=i+3
|
||||
i4=i+4
|
||||
i5=i+5
|
||||
i6=i+6
|
||||
i7=i+7
|
||||
Return
|
||||
|
||||
add: Procedure
|
||||
/* add argumemnts modulo 4294967296 */
|
||||
res=arg(1)+arg(2)
|
||||
If arg(3)<>'' Then
|
||||
res=res+arg(3)
|
||||
return res//4294967296
|
||||
239
Task/The-ISAAC-Cipher/REXX/the-isaac-cipher-2.rexx
Normal file
239
Task/The-ISAAC-Cipher/REXX/the-isaac-cipher-2.rexx
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/* REXX ---------------------------------------------------------------
|
||||
* 25.07.2014 Walter Pachl framing version 1 for processing a file
|
||||
*--------------------------------------------------------------------*/
|
||||
Parse Arg fid
|
||||
select
|
||||
When fid='' Then
|
||||
fid='test_file.txt'
|
||||
When fid='?' Then Do
|
||||
Say 'rexx iscf file prompts you for a key,'
|
||||
Say 'encrypts file into fn.enc'
|
||||
Say 'and decrypts fn.enc into fn.dec'
|
||||
Exit
|
||||
End
|
||||
Otherwise
|
||||
Nop
|
||||
End
|
||||
Say 'Please enter a key'
|
||||
Parse Pull key
|
||||
enc=fn(fid)'.enc' ; 'erase' enc
|
||||
dec=fn(fid)'.dec' ; 'erase' dec
|
||||
Do While lines(fid)>0
|
||||
l=linein(fid)
|
||||
Call lineout enc,iscx(l,key,'e')
|
||||
End
|
||||
Call lineout enc
|
||||
Do While lines(enc)>0
|
||||
l=linein(enc)
|
||||
Call lineout dec,iscx(l,key,'d')
|
||||
End
|
||||
Call lineout dec
|
||||
Say 'original:'
|
||||
'type' fid
|
||||
Say 'encrypted:'
|
||||
'type' enc
|
||||
Say 'decrypted:'
|
||||
'type' dec
|
||||
Exit
|
||||
iscx: Procedure
|
||||
/* REXX ---------------------------------------------------------------
|
||||
* 24.07.2014 Walter Pachl translated from Pascal
|
||||
* extend with decoding
|
||||
*--------------------------------------------------------------------*/
|
||||
Numeric Digits 32
|
||||
aa=0
|
||||
bb=0
|
||||
cc=0
|
||||
mm.=0
|
||||
randcnt=0
|
||||
randrsl.=0
|
||||
Parse Arg msg,key,mode
|
||||
|
||||
Call iSeed key,1 /* 1) seed ISAAC with the key */
|
||||
If mode='e' Then
|
||||
mode='iEncrypt'
|
||||
Else
|
||||
mode='iDecrypt'
|
||||
mctx=Vigenere(msg,mode) /* 3) MOD encryption */
|
||||
Return mctx
|
||||
|
||||
isaac: Procedure Expose mm. aa bb cc randrsl. randcnt
|
||||
cc=add(cc,1)
|
||||
bb=add(bb,cc)
|
||||
Do i=0 To 255
|
||||
x=mm.i
|
||||
im4=i//4
|
||||
Select
|
||||
When im4=0 Then aa=xor(aa,shl(aa,13))
|
||||
When im4=1 Then aa=xor(aa,shr(aa, 6))
|
||||
When im4=2 Then aa=xor(aa,shl(aa, 2))
|
||||
When im4=3 Then aa=xor(aa,shr(aa,16))
|
||||
End
|
||||
z=(i+128)//256
|
||||
aa=add(mm.z,aa)
|
||||
z=shr(x,2)//256
|
||||
y=add(mm.z,aa,bb)
|
||||
mm.i=y
|
||||
z=shr(y,10)//256
|
||||
bb=add(mm.z,x)
|
||||
randrsl.i=bb
|
||||
End
|
||||
randcnt=0
|
||||
Return
|
||||
|
||||
mix: Procedure Expose a b c d e f g h mm. aa bb cc randrsl. randcnt
|
||||
a=xor(a,shl(b,11)); d=add(d,a); b=add(b,c)
|
||||
b=xor(b,shr(c, 2)); e=add(e,b); c=add(c,d)
|
||||
c=xor(c,shl(d, 8)); f=add(f,c); d=add(d,e)
|
||||
d=xor(d,shr(e,16)); g=add(g,d); e=add(e,f)
|
||||
e=xor(e,shl(f,10)); h=add(h,e); f=add(f,g)
|
||||
f=xor(f,shr(g, 4)); a=add(a,f); g=add(g,h)
|
||||
g=xor(g,shl(h, 8)); b=add(b,g); h=add(h,a)
|
||||
h=xor(h,shr(a, 9)); c=add(c,h); a=add(a,b)
|
||||
Return
|
||||
|
||||
iRandInit: Procedure Expose mm. randrsl. randcnt
|
||||
Parse Arg flag
|
||||
aa=0; bb=0; cc=0
|
||||
a= 2654435769 /* $9e3779b9; // the golden ratio */
|
||||
|
||||
b=a; c=a; d=a; e=a; f=a; g=a; h=a
|
||||
|
||||
do i=0 TO 3
|
||||
Call mix
|
||||
End
|
||||
|
||||
i=0
|
||||
do until i>255 /* fill in mm[] with messy stuff */
|
||||
IF flag THEN Do /* use all the information in the seed */
|
||||
Call setix
|
||||
a=add(a,randrsl.i); b=add(b,randrsl.i1)
|
||||
c=add(c,randrsl.i2); d=add(d,randrsl.i3)
|
||||
e=add(e,randrsl.i4); f=add(f,randrsl.i5)
|
||||
g=add(g,randrsl.i6); h=add(h,randrsl.i7)
|
||||
End
|
||||
Call mix
|
||||
mm.i=a; mm.i1=b; mm.i2=c; mm.i3=d
|
||||
mm.i4=e; mm.i5=f; mm.i6=g; mm.i7=h
|
||||
i+=8
|
||||
End
|
||||
|
||||
IF flag THEN Do /* do a second pass to make all of the seed affect all of mm */
|
||||
i=0
|
||||
do until i>255 /* fill in mm[] with messy stuff */
|
||||
Call setix
|
||||
a=add(a,mm.i); b=add(b,mm.i1); c=add(c,mm.i2); d=add(d,mm.i3)
|
||||
e=add(e,mm.i4); f=add(f,mm.i5); g=add(g,mm.i6); h=add(h,mm.i7)
|
||||
Call mix
|
||||
mm.i=a; mm.i1=b; mm.i2=c; mm.i3=d
|
||||
mm.i4=e; mm.i5=f; mm.i6=g; mm.i7=h
|
||||
i+=8
|
||||
End
|
||||
End
|
||||
Call isaac /* fill in the first set of results */
|
||||
randcnt=0; /* prepare to use the first set of results */
|
||||
Return
|
||||
|
||||
iseed: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/*---------------------------------------------------------------------
|
||||
* Seed ISAAC with a given string.
|
||||
* The string can be any size. The first 256 values will be used.
|
||||
*--------------------------------------------------------------------*/
|
||||
Parse Arg seed,flag
|
||||
mm.=0
|
||||
m=Length(seed)-1
|
||||
Do i=0 TO 255
|
||||
IF i>m THEN /* in case seed has less than 256 elements */
|
||||
randrsl.i=0
|
||||
ELSE
|
||||
randrsl.i=c2d(substr(seed,i+1,1))
|
||||
end
|
||||
Call iRandInit flag /* initialize ISAAC with seed */
|
||||
Return
|
||||
|
||||
iRandom: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get a random 32-bit value 0..MAXINT */
|
||||
iRandom=randrsl.randcnt
|
||||
randcnt=randcnt+1
|
||||
If randcnt>255 Then Do
|
||||
Call isaac
|
||||
randcnt=0
|
||||
End
|
||||
Return irandom
|
||||
|
||||
iRandA: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get a random character in printable ASCII range */
|
||||
iRandA=iRandom()//95+32
|
||||
Return iRandA
|
||||
|
||||
xor: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
Parse Arg a,b
|
||||
ac=d2c(a,4)
|
||||
bc=d2c(b,4)
|
||||
res=c2d(bitxor(ac,bc))
|
||||
return res//4294967296
|
||||
|
||||
Vernam: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* XOR encrypt on random stream. Output: string of hex chars */
|
||||
Parse Arg msg
|
||||
Vernam=''
|
||||
Do i=1 to length(msg)
|
||||
Vernam=Vernam||d2c(xor(iRandA(),c2d(substr(msg,i,1))))
|
||||
End
|
||||
Return Vernam
|
||||
|
||||
letternum: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Get position of the letter in chosen alphabet */
|
||||
Parse Arg letter,start
|
||||
letternum=c2d(letter)-c2d(start)
|
||||
Return letternum
|
||||
|
||||
Caesar: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Caesar-shift a character <shift> places: Generalized Vigenere */
|
||||
Parse Arg m,ch,shift,modulo,start
|
||||
IF m='iDecrypt' TheN shift=-shift
|
||||
n=letternum(ch,start)+shift
|
||||
n=n//modulo
|
||||
IF n<0 Then n=n+modulo
|
||||
Caesar=d2c(c2d(start)+n)
|
||||
Return Caesar
|
||||
|
||||
Vigenere: Procedure Expose aa bb cc randcnt randrsl. mm.
|
||||
/* Vigenere mod 95 encryption. Output: string of hex chars */
|
||||
Parse Arg msg,m
|
||||
Vigenere=''
|
||||
Do i=1 to length(msg)
|
||||
Vigenere=Vigenere||Caesar(m,substr(msg,i,1),iRandA(),95,' ')
|
||||
End
|
||||
Return Vigenere
|
||||
|
||||
shl: Procedure
|
||||
res=arg(1)*(2**arg(2))
|
||||
return res//4294967296
|
||||
|
||||
shr: Procedure
|
||||
res=arg(1)%(2**arg(2))
|
||||
return res//4294967296
|
||||
|
||||
setix:
|
||||
i1=i+1
|
||||
i2=i+2
|
||||
i3=i+3
|
||||
i4=i+4
|
||||
i5=i+5
|
||||
i6=i+6
|
||||
i7=i+7
|
||||
Return
|
||||
|
||||
add: Procedure
|
||||
/* add argumemnts modulo 4294967296 */
|
||||
res=arg(1)+arg(2)
|
||||
If arg(3)<>'' Then
|
||||
res=res+arg(3)
|
||||
return res//4294967296
|
||||
|
||||
fn: Procedure
|
||||
/* REXX */
|
||||
parse Arg fid
|
||||
Parse Var fid fn '.' ft
|
||||
Return fn
|
||||
255
Task/The-ISAAC-Cipher/Racket/the-isaac-cipher.rkt
Normal file
255
Task/The-ISAAC-Cipher/Racket/the-isaac-cipher.rkt
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
#lang racket
|
||||
;; Imperative version: Translation of C
|
||||
;; Vigenère: Translation of Pascal
|
||||
(module+ test (require tests/eli-tester))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
;; standard.h: Standard definitions and types, Bob Jenkins
|
||||
(define UB4MAXVAL #xffffffff)
|
||||
(define-syntax-rule (bit target mask) (bitwise-and target mask))
|
||||
;; C-like operators
|
||||
(define-syntax-rule (u4-truncate x) (bit x UB4MAXVAL))
|
||||
(define-syntax-rule (u4<< a b) (u4-truncate (arithmetic-shift a b)))
|
||||
(define-syntax-rule (u4>> a b) (u4-truncate (arithmetic-shift a (- b))))
|
||||
(define-syntax-rule (_++ i) (let ((rv i)) (set! i (u4-truncate (add1 i))) rv))
|
||||
(define-syntax-rule (u4+= a b) (begin (set! a (u4-truncate (+ a b))) a))
|
||||
(define-syntax-rule (^= a b) (begin (set! a (u4-truncate (bitwise-xor a b))) a))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
;; rand.h: definitions for a random number generator
|
||||
(define RANDSIZL 8)
|
||||
(define RANDSIZ (u4<< 1 RANDSIZL))
|
||||
(define RANDSIZ-1 (sub1 RANDSIZ))
|
||||
|
||||
(struct randctx
|
||||
(cnt
|
||||
rsl ; RANDSIZ*4 bytes (makes u4's)
|
||||
mem ; RANDSIZ*4 bytes (makes u4's)
|
||||
a b c) #:mutable)
|
||||
|
||||
(define (new-randctx)
|
||||
(randctx 0 (make-bytes (* 4 RANDSIZ) 0) (make-bytes (* 4 RANDSIZ) 0) 0 0 0))
|
||||
|
||||
(define (bytes->hex-string B (start 0) (end #f) #:join (join "") #:show-bytes? (show-bytes? #f))
|
||||
(define hexes
|
||||
(for/list ((b (in-bytes B start end)))
|
||||
(~a (number->string b 16) #:width 2 #:align 'right #:pad-string "0")))
|
||||
(string-join
|
||||
(append hexes (if show-bytes?
|
||||
(list " \"" (bytes->string/utf-8 B #f start (or end (bytes-length B))) "\"")
|
||||
null))
|
||||
join))
|
||||
|
||||
(define format-randctx
|
||||
(match-lambda
|
||||
[(randctx C (app bytes->hex-string R) (app bytes->hex-string M) a b c)
|
||||
(format "randctx: cnt:~a~%rsl:~s~%mem:~s~%a:~a b:~a c:~a" C R M a b c)]))
|
||||
|
||||
(define be? (system-big-endian?))
|
||||
|
||||
(define (bytes->u4 ary idx)
|
||||
(integer-bytes->integer ary #f be? (* idx 4) (* (add1 idx) 4)))
|
||||
|
||||
(define (u4->bytes! ary idx v)
|
||||
(integer->integer-bytes (bit v UB4MAXVAL) 4 #f be? ary (* idx 4)))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
;; rand.c: "By Bob Jenkins. My random number generator, ISAAC. Public Domain."
|
||||
(define (ind mm x)
|
||||
(define idx (bitwise-and x (u4<< RANDSIZ-1 2)))
|
||||
(integer-bytes->integer mm #f be? idx (+ idx 4)))
|
||||
|
||||
(define (isaac C)
|
||||
(define M (randctx-mem C))
|
||||
(define R (randctx-rsl C))
|
||||
(define mm 0)
|
||||
(define r 0)
|
||||
(define-syntax-rule (rng-step mix)
|
||||
(begin
|
||||
(define x (bytes->u4 M m))
|
||||
(set! a (u4-truncate (+ (bitwise-xor a mix) (bytes->u4 M (_++ m2)))))
|
||||
(define y (+ (ind M x) a b))
|
||||
(u4->bytes! M (_++ m) y)
|
||||
(set! b (u4-truncate (+ (ind M (u4>> y RANDSIZL)) x)))
|
||||
(u4->bytes! R (_++ r) b)))
|
||||
|
||||
(define a (randctx-a C))
|
||||
|
||||
(set-randctx-c! C (add1 (randctx-c C)))
|
||||
|
||||
(define b (u4-truncate (+ (randctx-b C) (randctx-c C))))
|
||||
|
||||
(define m mm)
|
||||
(define m2 (+ m (/ RANDSIZ 2)))
|
||||
(define mend m2)
|
||||
|
||||
(define-syntax-rule (4-step-loop variant)
|
||||
(let loop ()
|
||||
(when (< variant mend)
|
||||
(rng-step (u4<< a 13)) (rng-step (u4>> a 6))
|
||||
(rng-step (u4<< a 2)) (rng-step (u4>> a 16))
|
||||
(loop))))
|
||||
|
||||
(4-step-loop m)
|
||||
(set! m2 mm)
|
||||
(4-step-loop m2)
|
||||
|
||||
(set-randctx-b! C b)
|
||||
(set-randctx-a! C a))
|
||||
|
||||
;; dot infix notation because I'm too lazy to move the operators left!
|
||||
(define-syntax-rule (mix-line<< A B N D C)
|
||||
(begin (A . ^= . (B . u4<< . N)) (D . u4+= . A) (B . u4+= . C)))
|
||||
(define-syntax-rule (mix-line>> A B N D C)
|
||||
(begin (A . ^= . (B . u4>> . N)) (D . u4+= . A) (B . u4+= . C)))
|
||||
|
||||
(define-syntax-rule (mix a b c d e f g h)
|
||||
(begin (mix-line<< a b 11 d c) (mix-line>> b c 2 e d)
|
||||
(mix-line<< c d 8 f e) (mix-line>> d e 16 g f)
|
||||
(mix-line<< e f 10 h g) (mix-line>> f g 4 a h)
|
||||
(mix-line<< g h 8 b a) (mix-line>> h a 9 c b)))
|
||||
|
||||
;; if (flag==TRUE), then use the contents of randrsl[] to initialize mm[].
|
||||
(define (rand-init C flag?)
|
||||
(set-randctx-a! C 0)
|
||||
(set-randctx-b! C 0)
|
||||
(set-randctx-c! C 0)
|
||||
|
||||
;; seed-ctx should set these up (with the seed!):
|
||||
;; (set-ctx-rsl! C (make-bytes (* 4 RANDSIZ) 0))
|
||||
;; (set-ctx-mem! C (make-bytes (* 4 RANDSIZ) 0))
|
||||
(define R (randctx-rsl C))
|
||||
(define M (randctx-mem C))
|
||||
|
||||
(define φ #x9e3779b9) ; the golden ratio
|
||||
(match-define (list a b c d e f g h) (make-list 8 φ))
|
||||
|
||||
(for ((_ 4)) (mix a b c d e f g h)) ; scramble it
|
||||
|
||||
(define-syntax-rule (mix-and-assign i M2)
|
||||
(begin
|
||||
(mix a b c d e f g h)
|
||||
(u4->bytes! M2 (+ i 0) a) (u4->bytes! M2 (+ i 1) b)
|
||||
(u4->bytes! M2 (+ i 2) c) (u4->bytes! M2 (+ i 3) d)
|
||||
(u4->bytes! M2 (+ i 4) e) (u4->bytes! M2 (+ i 5) f)
|
||||
(u4->bytes! M2 (+ i 6) g) (u4->bytes! M2 (+ i 7) h)))
|
||||
|
||||
(define-syntax-rule (mix-with-mem M1 M2)
|
||||
(for ((i (in-range 0 RANDSIZ 8)))
|
||||
(a . u4+= . (bytes->u4 M1 (+ i 0))) (b . u4+= . (bytes->u4 M1 (+ i 1)))
|
||||
(c . u4+= . (bytes->u4 M1 (+ i 2))) (d . u4+= . (bytes->u4 M1 (+ i 3)))
|
||||
(e . u4+= . (bytes->u4 M1 (+ i 4))) (f . u4+= . (bytes->u4 M1 (+ i 5)))
|
||||
(g . u4+= . (bytes->u4 M1 (+ i 6))) (h . u4+= . (bytes->u4 M1 (+ i 7)))
|
||||
(mix-and-assign i M2)))
|
||||
|
||||
(cond
|
||||
[flag? ; initialize using the contents of r[] as the seed
|
||||
(mix-with-mem R M)
|
||||
(mix-with-mem M M)] ; do a second pass to make all of the seed affect all of m
|
||||
[else ; fill in m[] with messy stuff
|
||||
(for ((i (in-range 0 RANDSIZ 8))) (mix-and-assign i M))])
|
||||
|
||||
(isaac C) ; fill in the first set of results
|
||||
(set-randctx-cnt! C 0)) ; prepare to use the first set of results
|
||||
|
||||
(define (seed-ctx C key #:flag? (flag? #t))
|
||||
(bytes-fill! (randctx-mem C) 0)
|
||||
(define R (randctx-rsl C))
|
||||
(bytes-fill! (randctx-rsl C) 0)
|
||||
(for ((k (in-bytes key)) (i (in-range (quotient (bytes-length R) 4)))) (u4->bytes! R i k))
|
||||
(rand-init C flag?))
|
||||
|
||||
;; Get a random 32-bit value 0..MAXINT
|
||||
(define (i-random C)
|
||||
(define cnt (randctx-cnt C))
|
||||
(define r (bytes->u4 (randctx-rsl C) cnt))
|
||||
(define cnt+1 (add1 cnt))
|
||||
(cond [(>= cnt+1 RANDSIZ) (isaac C) (set-randctx-cnt! C 0)]
|
||||
[else (set-randctx-cnt! C cnt+1)])
|
||||
r)
|
||||
|
||||
;; Get a random character in printable ASCII range
|
||||
(define ((i-rand-a C))
|
||||
(+ 32 (modulo (i-random C) 95)))
|
||||
|
||||
(define (Vernham rnd-fn msg)
|
||||
(define gsm (make-bytes (bytes-length msg)))
|
||||
(for ((i (in-naturals)) (m (in-bytes msg)))
|
||||
(define r (rnd-fn))
|
||||
(define b (bitwise-xor m r))
|
||||
(bytes-set! gsm i b))
|
||||
gsm)
|
||||
|
||||
;; Get position of the letter in chosen alphabet
|
||||
;; Caesar-shift a character <shift> places: Generalized Vigenere
|
||||
(define ((Caesar mod-n start) encrypt? shift ch)
|
||||
(define (letter-num letter/byte)
|
||||
(- letter/byte (char->integer start)))
|
||||
|
||||
(define shift-fn (if encrypt? + -))
|
||||
(+ (char->integer start) (modulo (shift-fn (letter-num ch) shift) mod-n)))
|
||||
|
||||
;; Vigenère mod 95 encryption & decryption. Output: bytes
|
||||
(define Vigenère-Caeser (Caesar 95 #\space))
|
||||
(define (Vigenère encrypt? rand-fn msg)
|
||||
(list->bytes
|
||||
(for/list ((b (in-bytes msg)))
|
||||
(Vigenère-Caeser encrypt? (rand-fn) b))))
|
||||
|
||||
{module+ main
|
||||
(define message #"a Top Secret secret")
|
||||
(define key #"this is my secret key")
|
||||
(define C (new-randctx))
|
||||
(seed-ctx C key)
|
||||
(define vern.msg (Vernham (i-rand-a C) message))
|
||||
;; Pascal doesn't reset the context betwen XOR and MOD
|
||||
;; (seed-ctx C key)
|
||||
(define vigen.msg (Vigenère #t (i-rand-a C) message))
|
||||
(seed-ctx C key)
|
||||
(define vern2.msg (Vernham (i-rand-a C) vern.msg))
|
||||
;; Pascal doesn't reset the context betwen XOR and MOD
|
||||
;; (seed-ctx C key)
|
||||
(define unvigen.msg (Vigenère #f (i-rand-a C) vigen.msg))
|
||||
;; This is what MOD looks like from the context as seeded with key
|
||||
(seed-ctx C key)
|
||||
(define vigen-at-seed.msg (Vigenère #t (i-rand-a C) message))
|
||||
(seed-ctx C key)
|
||||
(define unvigen-at-seed.msg (Vigenère #f (i-rand-a C) vigen-at-seed.msg))
|
||||
|
||||
(printf #<<EOS
|
||||
Message: [~a]
|
||||
Key: [~a]
|
||||
|
||||
< context reseeded
|
||||
Vernham (XOR): [~a]
|
||||
Vigenère (MOD): [~a]
|
||||
|
||||
< context reseeded
|
||||
Vernham (XOR(XOR)): [~a]
|
||||
Vigenère (-MOD): [~a]
|
||||
|
||||
< context reseeded (different to Pascal Vigenère encryption)
|
||||
Vigenère (MOD): [~a]
|
||||
< context reseeded
|
||||
Vigenère (-MOD): [~a]
|
||||
EOS
|
||||
message
|
||||
key
|
||||
(bytes->hex-string vern.msg)
|
||||
(bytes->hex-string vigen.msg #:show-bytes? #t)
|
||||
(bytes->hex-string vern2.msg #:show-bytes? #t)
|
||||
(bytes->hex-string unvigen.msg #:show-bytes? #t)
|
||||
(bytes->hex-string vigen-at-seed.msg #:show-bytes? #t)
|
||||
(bytes->hex-string unvigen-at-seed.msg #:show-bytes? #t)
|
||||
)}
|
||||
|
||||
{module+ test
|
||||
;; "If the initial internal state is all zero, after ten calls the values of aa, bb, and cc in
|
||||
;; hexadecimal will be d4d3f473, 902c0691, and 0000000a."
|
||||
(let ()
|
||||
(define C (new-randctx))
|
||||
(for ((_ 10)) (isaac C))
|
||||
(test (randctx-a C) => #xd4d3f473
|
||||
(randctx-b C) => #x902c0691
|
||||
(randctx-c C) => 10))
|
||||
}
|
||||
110
Task/The-ISAAC-Cipher/Tcl/the-isaac-cipher-1.tcl
Normal file
110
Task/The-ISAAC-Cipher/Tcl/the-isaac-cipher-1.tcl
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package require Tcl 8.6
|
||||
|
||||
oo::class create ISAAC {
|
||||
variable aa bb cc mm randrsl randcnt
|
||||
|
||||
constructor {seed} {
|
||||
namespace eval tcl {
|
||||
namespace eval mathfunc {
|
||||
proc mm {idx} {
|
||||
upvar 1 mm list
|
||||
lindex $list [expr {$idx % [llength $list]}]
|
||||
}
|
||||
proc clamp {value} {
|
||||
expr {$value & 0xFFFFFFFF}
|
||||
}
|
||||
}
|
||||
}
|
||||
proc mix1 {i v} {
|
||||
upvar 1 a a
|
||||
lset a $i [expr {clamp([lindex $a $i] ^ $v)}]
|
||||
lset a [set idx [expr {($i+3)%8}]] \
|
||||
[expr {clamp([lindex $a $idx] + [lindex $a $i])}]
|
||||
lset a [set idx [expr {($i+1)%8}]] \
|
||||
[expr {clamp([lindex $a $idx] + [lindex $a [expr {($i+2)%8}]])}]
|
||||
}
|
||||
|
||||
binary scan $seed[string repeat \u0000 256] c256 randrsl
|
||||
set mm [lrepeat 256 0]
|
||||
set randcnt [set aa [set bb [set cc 0]]]
|
||||
|
||||
set a [lrepeat 8 0x9e3779b9]
|
||||
foreach i {1 2 3 4} {
|
||||
mix1 0 [expr {[lindex $a 1] << 11}]
|
||||
mix1 1 [expr {[lindex $a 2] >> 2}]
|
||||
mix1 2 [expr {[lindex $a 3] << 8}]
|
||||
mix1 3 [expr {[lindex $a 4] >> 16}]
|
||||
mix1 4 [expr {[lindex $a 5] << 10}]
|
||||
mix1 5 [expr {[lindex $a 6] >> 4}]
|
||||
mix1 6 [expr {[lindex $a 7] << 8}]
|
||||
mix1 7 [expr {[lindex $a 0] >> 9}]
|
||||
}
|
||||
for {set i 0} {$i < 256} {incr i 8} {
|
||||
set a [lmap av $a bv [lrange $randrsl $i [expr {$i+7}]] {
|
||||
expr {clamp($av + $bv)}
|
||||
}]
|
||||
mix1 0 [expr {[lindex $a 1] << 11}]
|
||||
mix1 1 [expr {[lindex $a 2] >> 2}]
|
||||
mix1 2 [expr {[lindex $a 3] << 8}]
|
||||
mix1 3 [expr {[lindex $a 4] >> 16}]
|
||||
mix1 4 [expr {[lindex $a 5] << 10}]
|
||||
mix1 5 [expr {[lindex $a 6] >> 4}]
|
||||
mix1 6 [expr {[lindex $a 7] << 8}]
|
||||
mix1 7 [expr {[lindex $a 0] >> 9}]
|
||||
for {set j 0} {$j < 8} {incr j} {
|
||||
lset mm [expr {$i+$j}] [lindex $a $j]
|
||||
}
|
||||
}
|
||||
for {set i 0} {$i < 256} {incr i 8} {
|
||||
set a [lmap av $a bv [lrange $mm $i [expr {$i+7}]] {
|
||||
expr {clamp($av + $bv)}
|
||||
}]
|
||||
mix1 0 [expr {[lindex $a 1] << 11}]
|
||||
mix1 1 [expr {[lindex $a 2] >> 2}]
|
||||
mix1 2 [expr {[lindex $a 3] << 8}]
|
||||
mix1 3 [expr {[lindex $a 4] >> 16}]
|
||||
mix1 4 [expr {[lindex $a 5] << 10}]
|
||||
mix1 5 [expr {[lindex $a 6] >> 4}]
|
||||
mix1 6 [expr {[lindex $a 7] << 8}]
|
||||
mix1 7 [expr {[lindex $a 0] >> 9}]
|
||||
for {set j 0} {$j < 8} {incr j} {
|
||||
lset mm [expr {$i+$j}] [lindex $a $j]
|
||||
}
|
||||
}
|
||||
my Step
|
||||
}
|
||||
|
||||
method Step {} {
|
||||
incr bb [incr cc]
|
||||
set i -1
|
||||
foreach x $mm {
|
||||
set shift [lindex {13 -6 2 -16} [expr {[incr i] % 4}]]
|
||||
set aa [expr {$aa ^ ($shift>0 ? $aa<<$shift : $aa>>-$shift)}]
|
||||
set aa [expr {clamp($aa + mm($i+128))}]
|
||||
set y [expr {clamp(mm($x>>2) + $aa + $bb)}]
|
||||
lset mm $i $y
|
||||
set bb [expr {clamp(mm($y>>10) + $x)}]
|
||||
lset randrsl $i $bb
|
||||
}
|
||||
}
|
||||
|
||||
method random {} {
|
||||
set r [lindex $randrsl $randcnt]
|
||||
if {[incr randcnt] == 256} {
|
||||
my Step
|
||||
set randcnt 0
|
||||
}
|
||||
return $r
|
||||
}
|
||||
|
||||
method RandA {} {
|
||||
expr {([my random] % 95) + 32}
|
||||
}
|
||||
method vernam {msg} {
|
||||
binary scan $msg c* b
|
||||
for {set i 0} {$i < [llength $b]} {incr i} {
|
||||
lset b $i [expr {[lindex $b $i] & 255 ^ [my RandA]}]
|
||||
}
|
||||
return [binary encode hex [binary format c* $b]]
|
||||
}
|
||||
}
|
||||
6
Task/The-ISAAC-Cipher/Tcl/the-isaac-cipher-2.tcl
Normal file
6
Task/The-ISAAC-Cipher/Tcl/the-isaac-cipher-2.tcl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
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]"
|
||||
Loading…
Add table
Add a link
Reference in a new issue