Created
April 10, 2018 20:15
-
-
Save Estella/17aafb60b67b229102bed620be9a9f95 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*******************************************************************************************************/ | |
// PRINCESS - Metamorphic Cipher (64bit WORDS, 18 Rounds, 1024bit key, 512bit block), based on RC5 | |
/*******************************************************************************************************/ | |
// Written for fun, dedicated to girlfriend named Princess, who I love dearly. -Estella Mystagic | |
// Requries 64bit platform | |
// gcc -O2 princess_v1.c -o princess | |
/*******************************************************************************************************/ | |
#include <stdio.h> | |
#include <time.h> | |
/*******************************************************************************************************/ | |
// Debug Config | |
/*******************************************************************************************************/ | |
#define DEBUG_DUMPKEY 1 | |
#define DEBUG_KEYSETUP 1 | |
#define DEBUG_META 1 | |
#define DEBUG_META2 1 | |
#define DEBUG_ROUNDS 2 // one higher then actual amount. | |
/*******************************************************************************************************/ | |
typedef unsigned long long int WORD; | |
/*******************************************************************************************************/ | |
// Tweakable Configuration | |
/*******************************************************************************************************/ | |
WORD P = 0xb7e151628aed2a6a, Q = 0x9e3779b97f4a7c15, I = 0x243f6a8885a308d3; // constants (PHI,PI,E) | |
/*******************************************************************************************************/ | |
#define w 64 // word size in bits | |
#define r 18 // number of rounds | |
#define b 128 // number of bytes in 1024bit key | |
#define c 16 // number words in key = ceil(8*b/w) | |
#define t 152 // size of table S = 8*(r+1) words | |
/*******************************************************************************************************/ | |
WORD S[t]; // expanded key table | |
/*******************************************************************************************************/ | |
#define ROL(x,y) (((x)<<(y&(w-1))) | ((x)>>(w-(y&(w-1))))) | |
#define ROR(x,y) (((x)>>(y&(w-1))) | ((x)<<(w-(y&(w-1))))) | |
#define XOR(x,y) (x^y) | |
#define NOP(x) (x) | |
#define INV(x) (~x) | |
/*******************************************************************************************************/ | |
// Metamorphic Crypto Logic Unit (CLU) | |
/*******************************************************************************************************/ | |
WORD PRINCESS_CLU(WORD AA, WORD BB, int MODE) { | |
int meta = (BB % 5); | |
switch(meta) { | |
case 0: | |
if (MODE) { AA = ROL(AA,BB); } else { AA = ROR(AA,BB); } | |
break; | |
case 1: | |
if (MODE) { AA = ROR(AA,BB); } else { AA = ROL(AA,BB); } | |
break; | |
case 2: | |
if (MODE) { AA = XOR(AA,BB); } else { AA = XOR(BB,AA); } | |
break; | |
case 3: | |
AA = INV(AA); | |
break; | |
case 4: | |
AA = NOP(AA); | |
break; | |
} | |
if (DEBUG_META) { printf("M: %d CLU %d: AA = %016llX, BB = %016llX\n",MODE,meta,AA,BB); } | |
return AA; | |
} | |
/*******************************************************************************************************/ | |
void PRINCESS_ENCRYPT(WORD *pt, WORD *ct) { | |
WORD i,j,AA,BB, | |
A=pt[0]+S[0], B=pt[1]+S[1], C=pt[2]+S[2], D=pt[3]+S[3], | |
E=pt[4]+S[4], F=pt[5]+S[5], G=pt[6]+S[6], H=pt[7]+S[7]; | |
for (i=1; i<=r; i++) { | |
A = ROL(A^B,B)+S[2*i]; | |
B = ROL(B^A,A)+S[2*i+1]; | |
C = ROR(C^D,D)+S[2*i+2]; | |
D = ROR(D^C,C)+S[2*i+3]; | |
E = ROR(E^F,F)+S[2*i+4]; | |
F = ROR(F^E,E)+S[2*i+5]; | |
G = ROL(G^H,H)+S[2*i+6]; | |
H = ROL(H^G,G)+S[2*i+7]; | |
A = PRINCESS_CLU(A,S[i],0); | |
B = PRINCESS_CLU(B,S[i],0); | |
C = PRINCESS_CLU(C,S[i],0); | |
D = PRINCESS_CLU(D,S[i],0); | |
E = PRINCESS_CLU(E,S[i],0); | |
F = PRINCESS_CLU(F,S[i],0); | |
G = PRINCESS_CLU(G,S[i],0); | |
H = PRINCESS_CLU(H,S[i],0); | |
} | |
ct[0] = A; ct[1] = B; ct[2] = C; ct[3] = D; | |
ct[4] = E; ct[5] = F; ct[6] = G; ct[7] = H; | |
for (i=1; i<=r; i++) { | |
for (j=0; j<8;j++) { | |
AA = ct[j]; | |
BB = S[i]; | |
ct[j] = PRINCESS_CLU(ct[j],S[i],0); | |
if (DEBUG_META2) { printf("%lld - ENC MUTATE: %lld:%016llX <= %016llX , %016llX\n",i,j,ct[j],AA,BB); } | |
i++; | |
} | |
} | |
} | |
/*******************************************************************************************************/ | |
void PRINCESS_DECRYPT(WORD *ct, WORD *pt) { | |
WORD i,j,AA,BB; | |
for (i=r; i>0; i--) { | |
for (j=8; j>0;j--) { | |
AA = ct[j-1]; | |
BB = S[i-1]; | |
ct[j-1] = PRINCESS_CLU(ct[j-1],S[i-1],1); | |
if (DEBUG_META) { printf("%lld - DEC MUTATE: %lld:%016llX <= %016llX , %016llX\n",i-1,j-1,ct[j-1],AA,BB); } | |
i--; | |
} | |
} | |
WORD H=ct[7], G=ct[6], F=ct[5], E=ct[4], | |
D=ct[3], C=ct[2], B=ct[1], A=ct[0]; | |
for (i=r; i>0; i--) { | |
H = PRINCESS_CLU(H,S[i],1); | |
G = PRINCESS_CLU(G,S[i],1); | |
F = PRINCESS_CLU(F,S[i],1); | |
E = PRINCESS_CLU(E,S[i],1); | |
D = PRINCESS_CLU(D,S[i],1); | |
C = PRINCESS_CLU(C,S[i],1); | |
B = PRINCESS_CLU(B,S[i],1); | |
A = PRINCESS_CLU(A,S[i],1); | |
H = ROR(H-S[2*i+7],G)^G; | |
G = ROR(G-S[2*i+6],H)^H; | |
F = ROL(F-S[2*i+5],E)^E; | |
E = ROL(E-S[2*i+4],F)^F; | |
D = ROL(D-S[2*i+3],C)^C; | |
C = ROL(C-S[2*i+2],D)^D; | |
B = ROR(B-S[2*i+1],A)^A; | |
A = ROR(A-S[2*i],B)^B; | |
} | |
pt[7] = H-S[7]; pt[6] = G-S[6]; pt[5] = F-S[5]; pt[4] = E-S[4], | |
pt[3] = D-S[3]; pt[2] = C-S[2]; pt[1] = B-S[1]; pt[0] = A-S[0]; | |
} | |
/*******************************************************************************************************/ | |
// Silly Overly Complex Key Expansion with metamorphic functions. | |
/*******************************************************************************************************/ | |
void PRINCESS_SETUP(unsigned char *K) { | |
WORD i, j, jj, jc ,jd, k, u=w/8, A, B, C, D, L[c]; | |
for (i=b-1,L[c-1]=0; i!=-1; i--) { | |
L[i/u] = (L[i/u]<<8)+K[i]; | |
} | |
if (DEBUG_KEYSETUP) { printf("keysetup stage1 (metamorphic constants):\n"); } | |
for (S[0]=P,i=1; i<t; i++) { | |
int meta = ((I^(Q^i^S[i])+P) % 3); | |
if (meta == 0) { | |
S[i] = S[i-1]+Q; | |
} else if (meta == 1) { | |
S[i] = S[i-1]+P; | |
} else if (meta == 2) { | |
S[i] = S[i-1]+I; | |
} | |
if (DEBUG_KEYSETUP) { printf("S1: %d: S[%lld] = %016llX\n",meta,i,S[i]); } | |
} | |
if (DEBUG_KEYSETUP) { printf("keysetup stage2 (metamorphic mixer):\n"); } | |
for (A=B=i=j=k=0; k<3*t; k++,i=(i+1)%t,j=(j+1)%c) { | |
int meta = ((A^B^k^i^j) % 4); | |
if (meta == 0) { | |
A = S[i] = ROL(S[i]+(A+B),3); | |
B = L[j] = ROL(L[j]+(A+B),(A+B)); | |
} else if (meta == 1) { | |
A = S[i] = ROL(S[i]+(A+B)^P,3); | |
B = L[j] = ROL(L[j]+(A+B)^Q,(A+B)); | |
} else if (meta == 2) { | |
A = S[i] = ROR(S[i]+(A+B)+Q,3); | |
B = L[j] = ROR(L[j]+(A+B)+P,(A+B)); | |
} else if (meta == 3) { | |
A = S[i] = ROR(S[i]+(A+B)-Q,3); | |
B = L[j] = ROR(L[j]+(A+B)-P,(A+B)); | |
} | |
A = S[i] = PRINCESS_CLU(A,B,((A^B) % 2)); | |
B = L[j] = PRINCESS_CLU(B,A,((A^B) % 2)); | |
if (DEBUG_KEYSETUP) { printf("S2: %d: S[%lld] = %016llX, L[%lld] = %016llX\n",meta,i,S[i],j,L[j]); } | |
} | |
if (DEBUG_KEYSETUP) { printf("keysetup stage3 (key array order - metamorphic mixer):\n"); } | |
for (i=0; i<t; i++) { | |
jc = (S[i % t] + S[(i + 1) % t]) % t; | |
jd = (S[i % t] + S[(i + 2) % t]) % t; | |
C = S[jc]; | |
D = S[jd]; | |
jj = (jc+jd) % t; | |
int meta = ((i^jc^jd^C^D^jj) % 5); | |
if (meta == 0) { | |
S[jj] = PRINCESS_CLU(C,D, (S[i % t] ^ C) % 2); | |
} else if (meta == 1) { | |
S[jj] = PRINCESS_CLU(D,C, (S[i % t] ^ D) % 2); | |
} else if (meta == 2) { | |
S[i] = PRINCESS_CLU((D+Q),(D+I), (S[i % t] ^ (C+P)) % 2); | |
} else if (meta == 3) { | |
S[i] = PRINCESS_CLU((C^D+Q),(D^I-P), (S[i % t] ^ D-Q) % 2); | |
} else if (meta == 4) { | |
S[jj] = PRINCESS_CLU((D+Q^I),(D+I-Q+P^C), (S[i % t] ^ (C+P^Q+I)) % 2); | |
} | |
if (DEBUG_KEYSETUP) { printf("S3: %d - %lld: S[%lld] = %016llX <= C: S[%lld] = %016llX, D: S[%lld] = %016llX\n",meta,i,jj,S[i],jc,C,jd,D); } | |
} | |
if (DEBUG_KEYSETUP) { printf("keysetup stage4 (metamorphic mixer):\n"); } | |
for (A=B=i=j=k=0; k<3*t; k++,i=(i+1)%t,j=(j+1)%c) { | |
int meta = ((A^B^k^i^j) % 4); | |
if (meta == 0) { | |
A = S[i] = ROL(S[i]+(A+B)+P^Q,3); | |
B = L[j] = ROL(L[j]+(A+B)+Q^I,(A+B)); | |
} else if (meta == 1) { | |
A = S[i] = ROL(S[i]+(A+B)-P^I,3); | |
B = L[j] = ROL(L[j]+(A+B)^Q+I,(A+B)); | |
} else if (meta == 2) { | |
A = S[i] = ROR(S[i]+(A+B)+Q^I,3); | |
B = L[j] = ROR(L[j]+(A+B)^I+P,(A+B)); | |
} else if (meta == 3) { | |
A = S[i] = ROR(S[i]+(A+B)-Q-I,3); | |
B = L[j] = ROR(L[j]+(A+B)^P+I,(A+B)); | |
} | |
A = S[i] = PRINCESS_CLU(A,B,((A^B^S[i]) % 2)); | |
B = L[j] = PRINCESS_CLU(B,A,((A^B^L[j]) % 2)); | |
if (DEBUG_KEYSETUP) { printf("S4: %d: S[%lld] = %016llX, L[%lld] = %016llX\n",meta,i,S[i],j,L[j]); } | |
} | |
if (DEBUG_DUMPKEY) { | |
printf("Dumping expanded keysetup:\n"); | |
for (jj=0; jj<t; jj += 8) { | |
//printf("S[%lld] = %016llX\n",jj,S[jj]); | |
printf("%016llX %016llX %016llX %016llX %016llX %016llX %016llX %016llX\n",S[jj],S[jj+1],S[jj+2],S[jj+3],S[jj+4],S[jj+5],S[jj+6],S[jj+7]); | |
} | |
printf("Dumping expanded keysetup (short form):\n"); | |
for (jj=0; jj<t; jj++) { | |
printf("%016llX\n",S[jj]); | |
} | |
} | |
} | |
/*******************************************************************************************************/ | |
int main() { | |
WORD i, j, pt1[8], pt2[8], ct[8] = {0,0}; | |
unsigned char key[b]; | |
time_t t0, t1; | |
printf("PRINCESS - Metamorphic Cipher (64bit WORDS, 18 Rounds, 1024bit key, 512bit block):\n"); | |
for (i=1;i<DEBUG_ROUNDS;i++) { | |
pt1[0]=ct[0]; pt1[1]=ct[1]; pt1[2]=ct[2]; pt1[3]=ct[3], pt1[4]=ct[4]; pt1[5]=ct[5]; pt1[6]=ct[6]; pt1[7]=ct[7]; | |
for (j=0;j<b;j++) { key[j] = ct[0]%(255-j); } | |
PRINCESS_SETUP(key); | |
PRINCESS_ENCRYPT(pt1,ct); | |
PRINCESS_DECRYPT(ct,pt2); | |
printf("\n%lld. key:\n ",i); | |
for (j=0; j<64; j++) { printf("%.2X",key[j]); } | |
printf("\n "); | |
for (j=64; j<128; j++) { printf("%.2X",key[j]); } | |
printf("\n"); | |
printf("\n P: %016llX %016llX %016llX %016llX %016llX %016llX %016llX %016llX\n C: %016llX %016llX %016llX %016llX %016llX %016llX %016llX %016llX\n", | |
pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5], pt1[6], pt1[7], | |
ct[0], ct[1], ct[2], ct[3], ct[4], ct[5], ct[6], ct[7]); | |
if (pt1[0] != pt2[0] || pt1[1] != pt2[1] || pt1[2] != pt2[2] || pt1[3] != pt2[3] || pt1[4] != pt2[4] || pt1[5] != pt2[5] || pt1[6] != pt2[6] || pt1[7] != pt2[7]) { | |
printf("\n DECRYPT ERROR:\n %016llX %016llX %016llX %016llX %016llX %016llX %016llX %016llX\n %016llX %016llX %016llX %016llX %016llX %016llX %016llX %016llX\n", | |
pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5], pt1[6], pt1[7], | |
pt2[0], pt2[1], pt2[2], pt2[3], pt2[4], pt2[5], pt2[6], pt2[7]); | |
} | |
} | |
/* | |
// Timing tests, make sure to turn off debug outputs, before doing a million iterations. | |
time (&t0); | |
for (i=1;i<1000000;i++) { PRINCESS_ENCRYPT(ct,ct); } | |
time (&t1); | |
printf ("\n Time_t for 1 mil blocks: %ld \n", t1-t0); | |
*/ | |
return 0; | |
} | |
/*******************************************************************************************************/ | |
// EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment