Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Chris M. Thomasson 8/21/2016
- # Reverse Iteration Fractal Cipher (RIFC)
- # Pre-Alpha Version: 0.0.0.1
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- import math;
- import random;
- import hmac;
- import copy;
- import os;
- # RIFC General Complex Math Utilities
- #____________________________________________________________
- # Complex Absolute Value
- def ct_cabs(z):
- return math.sqrt(z.real**2 + z.imag**2);
- # Complex Argument
- def ct_carg(z):
- return math.atan2(z.imag, z.real);
- # Complex Argument Range [0...PI2]
- def ct_cargr(z):
- a = math.atan2(z.imag, z.real);
- if (a < 0): a = a + math.pi * 2;
- return a;
- # Get n from a power
- def ct_npow(p):
- return int(math.ceil(math.fabs(p)));
- # Complex Roots
- def ct_croots(z, p):
- l = ct_cabs(z);
- s = l**(1.0 / p);
- a = ct_carg(z) / p;
- n = ct_npow(p);
- astep = (math.pi * 2.0) / p;
- result = [];
- for i in range(n):
- r = complex(math.cos(a + astep * i) * s,
- math.sin(a + astep * i) * s);
- result.append(r);
- return result;
- # Find Root
- def ct_froot(z, r):
- n = 0;
- for i in r:
- d = z - i;
- l = math.sqrt(d.real**2 + d.imag**2);
- if l < 0.000001: return n;
- n = n + 1;
- return -1;
- # RIFC Number Conversions and Nit Utilities
- #____________________________________________________________
- # Convert base ten 10 to nits, pad to n
- def ct_base_10_to_nits_pad(v, b, n):
- nits = "";
- r = 0;
- for i in range(n):
- d = math.floor(v / b);
- r = v - (d * b);
- nits = nits + str(r);
- v = d;
- nits = nits[::-1];
- return nits;
- # Convert base ten 10 to nits
- def ct_base_10_to_nits(v, b):
- nits = "";
- r = 0;
- while 1:
- d = math.floor(v / b);
- r = v - (d * b);
- nits = nits + str(r);
- v = d;
- if (d == 0): break;
- nits = nits[::-1];
- return nits;
- # Convert nits to base 10
- def ct_nits_to_base_10(nits, b):
- p = len(nits) - 1;
- r = 0;
- for nit in nits:
- r = r + int(nit)*b**p;
- p = p - 1;
- return r;
- # Generate n random nits in range [0...(b-1)]
- def ct_gen_rand_nits(n, b):
- nits = "";
- for i in range(n):
- nits = nits + str(random.randint(0, b - 1));
- return nits;
- def ct_number_from_ptxt_bytes_n(ptxt, o, n):
- r = 0;
- imax = len(ptxt);
- p = 0;
- for i in range(o, n + 1):
- b = ord(ptxt[i]);
- a = b * 256**p;
- r = r + a;
- #print("ni[%s]:(b:%s, r:%s)" % (i, b, r));
- p = p + 1;
- return r;
- def ct_ptxt_bytes_from_number(n, b, e):
- r = 0;
- ni = 0;
- ptxt = "";
- # trail zero...
- if (n > b):
- if (n == e):
- ptxt = ptxt + chr(0);
- ptxt = ptxt + chr(0);
- return ptxt;
- xn = n - b;
- ptxt = ptxt + chr(xn);
- ptxt = ptxt + chr(0);
- return ptxt;
- while 1:
- d = math.floor(n / 256);
- r = n - (d * 256);
- ptxt = ptxt + chr(r);
- n = d;
- if (d == 0): break;
- return ptxt;
- # RIFC 2d Axes Class
- #___________________________________________________________
- class ct_rifc_axes_2d:
- def __init__(self, xmin, xmax, ymin, ymax):
- self.xmin = xmin;
- self.xmax = xmax;
- self.ymin = ymin;
- self.ymax = ymax;
- def __repr__(self):
- return "(xmin:%s, xmax:%s, ymin:%s, ymax:%s)" % (self.xmin, self.xmax, self.ymin, self.ymax)
- def __str__(self): return self.__repr__();
- def width(self): return self.xmax - self.xmin;
- def height(self): return self.ymax - self.ymin;
- def offset(self, axes):
- a = ct_rifc_axes_2d(
- self.xmin + axes.xmin,
- self.xmax + axes.xmax,
- self.ymin + axes.ymax,
- self.ymax + axes.ymax
- );
- return a;
- # RIFC 2d Plane Class
- #___________________________________________________________
- class ct_rifc_plane_2d:
- def __init__(self, width, height, axes):
- self.axes = copy.copy(axes);
- self.width = width;
- self.height = height;
- self.xstep = self.axes.width() / width;
- self.ystep = self.axes.height() / height;
- self.aratio = height / width;
- def __repr__(self):
- return "(axes:%s, width:%s, height:%s, xstep:%s, ystep:%s, aratio:%s)" % (self.axes,
- self.width, self.height,
- self.xstep, self.ystep,
- self.aratio);
- def __str__(self): return self.__repr__();
- def project_to(self, p):
- x = math.floor((p.real - self.axes.xmin) / self.xstep * self.aratio);
- y = math.floor((self.axes.ymax - p.imag) / self.ystep);
- return complex(x, y);
- def project_int_to(self, p):
- return complex(self.axes.xmin + p.real * self.xstep,
- self.axes.ymax - p.imag * self.ystep);
- # RIFC Secret Key Class
- #____________________________________________________________
- class ct_rifc_skey:
- def __init__(self, axes, z, c, p, r_n, s, hmkey):
- self.axes = copy.copy(axes);
- self.z = z;
- self.c = copy.copy(c);
- self.p = copy.copy(p);
- self.r_n = r_n;
- a = 256**2;
- nits = ct_base_10_to_nits((a + 256 + 1), ct_npow(p[0]));
- self.n_n = len(nits) + 1;
- self.s = s;
- self.hmack = copy.copy(hmkey);
- def __repr__(self):
- return "(axes:%s, z:%s, c:%s, p:%s, r_n:%s, n_n:%s, s:%s, hmack:%s)" % (self.axes, self.z, self.c, self.p, self.r_n, self.n_n, self.s, self.hmack);
- def __str__(self): return self.__repr__();
- # RIFC Native Encrypt Class
- #____________________________________________________________
- class ct_rifc_encrypt:
- def __init__(self, skey):
- self.skey = skey; # mutable reference
- def __repr__(self):
- return "(skey:%s)" % (self.skey);
- def __str__(self): return self.__repr__();
- def process(self, z, c, p, ptxt):
- i = 0;
- for nit in ptxt:
- r = ct_croots(z - c, p);
- z = r[int(nit)];
- #print("encrypt_process:z[%s]:(%s):(%s)" % (i, nit, z));
- i = i + 1;
- return z;
- # RIFC Native Decrypt Class
- #____________________________________________________________
- class ct_rifc_decrypt:
- def __init__(self, skey):
- self.skey = skey; # mutable reference
- def __repr__(self):
- return "(skey:%s)" % (self.skey);
- def __str__(self): return self.__repr__();
- def process(self, z, c, p, n):
- ptxt = "";
- for i in range(n):
- f = z**p + c;
- r = ct_croots(f - c, p);
- nit = ct_froot(z, r);
- ptxt = ptxt + str(nit);
- #print("decrypt_process:z[%s]:(%s):(%s)" % (n - i - 1, nit, z));
- z = f;
- i = i + 1;
- ptxt = ptxt[::-1]; # reverse nits
- return [ptxt, z];
- # RIFC Block Compatible Nit Class
- #____________________________________________________________
- class ct_rifc_nitblock:
- def __init__(self, z, ptxt, ptxt_nits, rand_nits):
- self.z = z;
- self.ptxt = ptxt;
- self.ptxt_nits = ptxt_nits;
- self.rand_nits = rand_nits;
- def __repr__(self):
- return "(z:%s, ptxt:%s, ptxt_nits:%s, ptxt_n_nits:%s, rand_nits:%s)" % (self.z, self.ptxt, self.ptxt_nits, self.ptxt_n_nits, self.rand_nits);
- def __str__(self): return self.__repr__();
- def compare(self, rhs):
- if (self.ptxt_nits != rhs.ptxt_nits or
- self.rand_nits != rhs.rand_nits):
- return False;
- return True;
- def ct_rifc_nitblock_from_number(fskey, z, n):
- ptxt_nits = ct_base_10_to_nits_pad(n, ct_npow(fskey.p[0]), fskey.n_n);
- rand_nits = ct_gen_rand_nits(fskey.r_n, ct_npow(fskey.p[1]));
- return ct_rifc_nitblock(z, n, ptxt_nits, rand_nits);
- # RIFC Block Cipher Class
- #____________________________________________________________
- class ct_rifc_block:
- def __init__(self, fskey):
- self.fskey = fskey;
- def __repr__(self):
- return "(fskey:%s)" % (self.fskey);
- def __str__(self): return self.__repr__();
- def encrypt(self, nblk):
- fencrypt = ct_rifc_encrypt(self.fskey);
- #print("\nBlock Encryption Process");
- #print("___________________________________________________");
- #print("nblk:%s" % (nblk));
- #print("--------------------------------------");
- #print("\nplaintext");
- #print("--------------------------------------");
- z = nblk.z;
- z = fencrypt.process(z, fskey.c[0], fskey.p[0], nblk.ptxt_nits);
- #print("\nrandom plaintext");
- #print("--------------------------------------");
- z = fencrypt.process(z, fskey.c[1], fskey.p[1], nblk.rand_nits);
- #print("___________________________________________________\n");
- return z;
- def decrypt(self, z):
- fdecrypt = ct_rifc_decrypt(self.fskey);
- #print("\nBlock Decryption Process");
- #print("___________________________________________________");
- #print("\nrandom plaintext");
- #print("--------------------------------------");
- z = fdecrypt.process(z, self.fskey.c[1], self.fskey.p[1], self.fskey.r_n);
- rand_nits = z[0];
- #print("\nplaintext");
- #print("--------------------------------------");
- z = fdecrypt.process(z[1], self.fskey.c[0], self.fskey.p[0], self.fskey.n_n);
- ptxt_nits = z[0];
- #print("___________________________________________________\n");
- nblk = ct_rifc_nitblock(z[1], ct_nits_to_base_10(ptxt_nits, ct_npow(self.fskey.p[0])), ptxt_nits, rand_nits);
- return nblk;
- # RIFC Ciphertext Class
- #____________________________________________________________
- class ct_rifc_ciphertext:
- def __init__(self, hmhash, axes, ctxt):
- self.hmhash = hmhash;
- self.axes = axes;
- self.ctxt = ctxt;
- def __repr__(self):
- s = ("(%s)\n" % (self.hmhash));
- s = ("%s\n" % (self.axes));
- for cp in self.ctxt: s = s + ("%s\n" % (cp));
- return s;
- def __str__(self): return self.__repr__();
- def hmack_assert(self, hmhash_compare):
- return hmac.compare_digest(self.hmhash, hmhash_compare);
- # Main RIFC Cipher Class
- #____________________________________________________________
- class ct_rifc:
- def __init__(self, fskey):
- self.fskey = fskey;
- def __repr__(self):
- return "(fskey:%s)" % (self.fskey);
- def __str__(self): return self.__repr__();
- def ffe_gen_rand_axes(self, nmin, nmax):
- d = nmax - nmin;
- r = d / 2;
- xmin = -random.random() * r;
- xmax = random.random() * r;
- ymin = -random.random() * r;
- ymax = random.random() * r;
- return ct_rifc_axes_2d(xmin, xmax, ymin, ymax);
- def ffe_forward_iterate(self, z, c, p, s, n, e):
- for i in range(n):
- f = i % 3;
- z = z**self.fskey.p[f] + self.fskey.c[2];
- z = z**p + c;
- z = z * s;
- d = ct_cabs(z);
- if (d > e):
- return [z, i];
- return [z, n];
- def ffe_in_range(self, n, m):
- while (ct_cabs(n) > m):
- n = n * 0.413;
- return n;
- # Apply a Funny Fractal Mutation to the Plaintext
- def ffe_cipher_ptxt(self, ptxt, axes, encrypt):
- ffe_ctxt = "";
- n = len(ptxt);
- dims = int(math.ceil(math.sqrt(n)));
- plane = ct_rifc_plane_2d(dims, dims, axes);
- for i in range(n):
- vp = complex(i % dims, int(math.floor(i / dims)));
- z = plane.project_int_to(vp);
- ffe_fwd = self.ffe_forward_iterate(z, self.fskey.c[2], self.fskey.p[2], self.fskey.s, 64, 2.0);
- dis = ct_cabs(z);
- a = (ffe_fwd[0].real * 354125) + (ffe_fwd[0].imag * 234510) * (ffe_fwd[1] + dims / 2 + 1) * dis;
- a = int(math.floor(math.fabs(a * 13))) % 256;
- if (encrypt):
- ffe_ctxt = ffe_ctxt + chr(ord(ptxt[i]) ^ a);
- else:
- ffe_ctxt = ffe_ctxt + chr(a ^ ord(ptxt[i]));
- #print("ffe_fwd:%s" % (ffe_fwd));
- i = i + 1;
- return ffe_ctxt;
- # Apply a Funny Fractal Mutation to the Ciphertext
- def ffe_cipher_ctxt(self, ctxt, axes, encrypt):
- ffe_ctxt = [];
- n = len(ctxt);
- dims = int(math.ceil(math.sqrt(n)));
- plane = ct_rifc_plane_2d(dims, dims, axes);
- for i in range(n):
- vp = complex(i % dims, int(math.floor(i / dims)));
- z = plane.project_int_to(vp);
- ffe_fwd = self.ffe_forward_iterate(z, self.fskey.c[2], self.fskey.p[2], self.fskey.s, 64, 2.0);
- ffe_fwd[0] = self.ffe_in_range(ffe_fwd[0], 32);
- if (encrypt):
- mcp = ctxt[i] + ffe_fwd[0];
- else:
- mcp = ctxt[i] - ffe_fwd[0];
- ffe_ctxt.append(mcp);
- return ffe_ctxt;
- def encrypt(self, ptxt):
- ffe_rand_axes = self.ffe_gen_rand_axes(-3.14159, 3.14159);
- axes = self.fskey.axes.offset(ffe_rand_axes);
- #xxxptxt = self.ffe_cipher_ptxt(ptxt, axes, True);
- #yyyptxt = self.ffe_cipher_ptxt(xxxptxt, axes, False);
- ffe_ctxt = self.ffe_cipher_ptxt(ptxt, axes, True);
- #ffe_ctxt = ffe_ctxt + chr(0);
- #ffe_ctxt = ffe_ctxt + chr(0);
- i = 0;
- n = len(ffe_ctxt);
- nsum = 0;
- ciphertext = [];
- hmassert = hmac.new(self.fskey.hmack.encode());
- rifc_block = ct_rifc_block(self.fskey);
- z = self.fskey.z;
- d = int(math.floor(n / 2));
- r = n - d * 2;
- c = 0;
- for i in range(1, n, 2):
- xtxtc = ffe_ctxt[i - 1] + ffe_ctxt[i];
- a = len(xtxtc);
- c0 = ord(ffe_ctxt[i - 1]);
- c1 = ord(ffe_ctxt[i]);
- v = c1*256 + c0;
- if (c1 == 0):
- v = v + 65536;
- if (c0 == 0):
- v = 65800;
- nblk = ct_rifc_nitblock_from_number(fskey, z, v);
- cipherpoint = rifc_block.encrypt(nblk);
- # Crude Trial Encrypt of (cipherpoint)
- td_nblk = rifc_block.decrypt(cipherpoint);
- aa = ct_nits_to_base_10(td_nblk.ptxt_nits, ct_npow(self.fskey.p[0]));
- xtxt = ct_ptxt_bytes_from_number(td_nblk.ptxt, 65536, 65800);
- if (not nblk.compare(td_nblk) or v != aa or xtxtc != xtxt):
- print("****************** Trial Decrypt Engaged, encrypt side! ***********************");
- print("c-:%s, c1:%s" % (c0, c));
- xxi = 0;
- xtxt_0 = ct_ptxt_bytes_from_number(td_nblk.ptxt, 65536, 65800);
- xxa = xxi + 1;
- # Future work...
- #hmassert.update(str(cipherpoint).encode());
- ciphertext.append(cipherpoint);
- z = cipherpoint;
- for i in range(n - r, n):
- v = ord(ffe_ctxt[i]);
- nblk = ct_rifc_nitblock_from_number(fskey, z, v);
- cipherpoint = rifc_block.encrypt(nblk);
- # Crude Trial Encrypt of (cipherpoint)
- td_nblk = rifc_block.decrypt(cipherpoint);
- if (not nblk.compare(td_nblk)):
- print("****************** Trial Decrypt Engaged! ***********************");
- xxi = 0;
- xxa = xxi + 1;
- # Future work...
- #hmassert.update(str(cipherpoint).encode());
- ciphertext.append(cipherpoint);
- z = cipherpoint;
- # FFE Ciphertext Mutation
- xctxt = self.ffe_cipher_ctxt(ciphertext, axes, True);
- for cp in xctxt:
- hmassert.update(str(cp).encode());
- hmhash = hmassert.hexdigest();
- return ct_rifc_ciphertext(hmhash, axes, xctxt);
- def decrypt(self, ctxt):
- ffe_ptxt = "";
- rifc_block = ct_rifc_block(self.fskey);
- axes = ctxt.axes;
- hmassert = hmac.new(self.fskey.hmack.encode());
- # check HMAC
- for cp in ctxt.ctxt:
- hmassert.update(str(cp).encode());
- hmhash = hmassert.hexdigest();
- if (not ctxt.hmack_assert(hmhash)):
- print("\n\n************** !! HMAC VOILATION !! ****************\n\n");
- return "Bob is 0xDEADBEEF!!!";
- ffe_ctxt = self.ffe_cipher_ctxt(ctxt.ctxt, axes, False);
- for cp in ffe_ctxt:
- nblk = rifc_block.decrypt(cp);
- ffe_ptxt = ffe_ptxt + ct_ptxt_bytes_from_number(nblk.ptxt, 65536, 65800);
- a = len(ffe_ptxt);
- ptxt = self.ffe_cipher_ptxt(ffe_ptxt, axes, False);
- return ptxt;
- # Main RIFC Cipher Test
- #____________________________________________________________
- # For future use in a ciphertext plotter
- def ct_rifc_plot_gen_rand_ptxt(n):
- ptxt = "";
- for i in range(n):
- a = random.randint(0, 255);
- ptxt = ptxt + chr(a);
- return ptxt;
- # For future use in a ciphertext plotter
- def ct_rifc_plot_rand_test(rifc, n):
- for i in range(n):
- ptxt = ct_rifc_plot_gen_rand_ptxt(random.randint(8, 128));
- ciphertext = rifc.encrypt(ptxt);
- dptxt = rifc.decrypt(ciphertext);
- if (ptxt != dptxt):
- print("SHIT ************************ FAILED DECRYPT ********************* SHIT");
- n = len(ptxt);
- for i in range(n):
- a = ord(ptxt[i]);
- b = ord(dptxt[i]);
- if (a != b):
- print("**** DOUBLE SHIT ****");
- return False;
- print("i:%s\r" % (i), end="");
- print("\r\n\n");
- return True;
- print("Chris M. Thomasson 8/21/2016");
- print("Reverse Iteration Fractal Cipher (RIFC)");
- print("Pre-Alpha Version: 0.0.0.1");
- print("In-Memory Byte Level Version");
- print("File based version is on its way");
- print("=======================================================\n\n\n");
- original_plaintext = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
- fskey = ct_rifc_skey(ct_rifc_axes_2d(-0.5, 0.1, -0.87, .34),
- (-0.74543+0.11301j),
- [(.677+.2j), (-.0505+.64j), (-0.02+0.6j)],
- [3, 5, 2.314],
- 2, (1.0+0.0j), "hmac_skey_123");
- rifc = ct_rifc(fskey);
- #z^4+{.677;.2}
- #z^5+{-.0505;+.64}
- print("rifc:%s\n\n" % (rifc));
- #ct_rifc_plot_rand_test(rifc, 20000);
- print("original_plaintext, length: %s" % (len(original_plaintext)));
- print("______________________________________________");
- print(original_plaintext);
- print("______________________________________________");
- ciphertext = rifc.encrypt(original_plaintext);
- print("\n\nciphertext, length %s" % (len(ciphertext.ctxt)));
- print("______________________________________________");
- print(ciphertext);
- print("______________________________________________\n\n");
- # Eve can try to mess with the ciphertext,
- # but Bob will be alerted! :^D
- #ciphertext.ctxt[0] = ciphertext.ctxt[0] + (.000000000-.000000000j);
- #ciphertext.ctxt[0] = (0.7530623063524057+0.5739172586889129j);
- decrypted_plaintext = rifc.decrypt(ciphertext);
- print("decrypted_plaintext, length: %s" % (len(decrypted_plaintext)));
- print("______________________________________________");
- print(decrypted_plaintext);
- print("______________________________________________\n\n");
- # eof
Advertisement
Add Comment
Please, Sign In to add comment