+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include<string.h>
+
+typedef unsigned char uchar;
+
+
+
+
+typedef uint64_t u8;
+
+extern "C" {
+ int load_RGB_pixmap(char *filename, int *width, int *height, unsigned char**R_data, unsigned char**G_data, unsigned char**B_data);
+ void store_RGB_pixmap(char *filename, unsigned char *R_data, unsigned char *G_data, unsigned char *B_data, int width, int height);
+}
+using namespace std;
+
+
+
+typedef struct sfcctx { u8 a; u8 b; u8 c; u8 count; } sfcctx;
+#define rot64(x,k) (((x)<<(k))|((x)>>(64-(k))))
+
+#define rotation 24
+#define right_shift 11
+#define left_shift 3
+
+
+static inline u8 sfc( sfcctx *x ) {
+ u8 tmp = x->a + x->b + x->count++;
+ x->a = x->b ^ (x->b >> right_shift);
+ x->b = x->c + (x->c << left_shift);
+ x->c = rot64(x->c, rotation) + tmp;
+ return tmp;
+}
+
+static inline void sfcinit(sfcctx *x, uint64_t seed) {
+ x->a = seed;
+ x->b = seed;
+ x->c = seed;
+ x->count = 1;
+ for(int i=0;i<12;i++)
+ sfc(x);
+}
+
+
+
+typedef struct ranctx { u8 a; u8 b; u8 c; u8 d; } ranctx;
+
+
+
+static inline u8 jsf( ranctx *x ) {
+ u8 e = x->a - rot64(x->b, 7);
+ x->a = x->b ^ rot64(x->c, 13);
+ x->b = x->c + rot64(x->d, 37);
+ x->c = x->d + e;
+ x->d = e + x->a;
+ return x->d;
+}
+
+static inline void jsfinit(ranctx *x, uint64_t seed) {
+ x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
+}
+
+
+
+
+
+
+
+
+
+inline uint64_t xorshift64( const uint64_t state)
+{
+ uint64_t x = state;
+ x^= x << 13;
+ x^= x >> 7;
+ x^= x << 17;
+ return x;
+}
+
+static inline uint64_t splitmix64_stateless(uint64_t index) {
+ uint64_t z = (index + UINT64_C(0x9E3779B97F4A7C15));
+ z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
+ z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
+ return z ^ (z >> 31);
+}
+
+
+struct sulong2 {
+ uint64_t x;
+ uint64_t y;
+};
+
+typedef struct sulong2 ulong2;
+
+static inline uint64_t rotl(const uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+// call this one before calling xoroshiro128plus
+static inline void xoroshiro128plus_seed(ulong2 *xoro,uint64_t seed) {
+ xoro->x = splitmix64_stateless(seed);
+ xoro->y = splitmix64_stateless(seed + 1);
+}
+
+// returns random number, modifies xoroshiro128plus_s
+static inline uint64_t xoroshiro128plus(ulong2 *xoro) {
+ const uint64_t s0 = xoro->x;
+ uint64_t s1 = xoro->y;
+ const uint64_t result = s0 + s1;
+
+ s1 ^= s0;
+ xoro->x = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
+ xoro->y = rotl(s1, 36); // c
+
+ return result;
+}
+
+
+
+
+
+
+double TimeStart()
+{
+ struct timeval tstart;
+ gettimeofday(&tstart,0);
+ return( (double) (tstart.tv_sec + tstart.tv_usec*1e-6) );
+}
+
+double TimeStop(double t)
+{
+ struct timeval tend;
+
+ gettimeofday(&tend,0);
+ t = (double) (tend.tv_sec + tend.tv_usec*1e-6) - t;
+ return (t);
+}
+
+
+uint xorshift32(const uint t)
+{
+ /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
+ uint x = t;
+ x ^= x << 13;
+ x ^= x >> 17;
+ x ^= x << 5;
+ return x;
+}
+
+
+
+
+
+void rc4key(uchar *key, uchar *sc, int size_DK) {
+
+ for(int i=0;i<256;i++) {
+ sc[i]=i;
+ }
+
+
+ uchar j0 = 0;
+ for(int i0=0; i0<256; i0++) {
+ j0 = (j0 + sc[i0] + key[i0%size_DK] )&0xFF;
+ uchar tmp = sc[i0];
+ sc[i0] = sc[j0 ];
+ sc[j0] = tmp;
+ }
+}
+
+
+void rc4keyperm(uchar *key,int len, int rp,int *sc, int size_DK) {
+
+ //sc=1:len;
+
+
+
+ for (int i=0;i<len;i++) {
+ sc[i]=i;
+ }
+ for (int it = 0; it < rp; it++) {
+ int j0 = 1;
+ for(int i0 = 0; i0<len; i0++) {
+ j0 = (j0 + sc[i0] + sc[j0] + key[i0%size_DK] )% len;
+ int tmp = sc[i0];
+ sc[i0] = sc[j0];
+ sc[j0] = tmp;
+ }
+
+ }
+}
+
+
+void scprng(uint64_t *plain, uint64_t* cipher, int bufsize, int nb_bloc, uint64_t *Val, uchar *Sbox1, uchar *Sbox2, int *Pbox, int *Pbox2, uchar *DK, int delta) {
+ int update=0;
+
+
+ for(int nb=0;nb<nb_bloc;nb++) {
+
+ for(int j=0;j<bufsize;j++) {
+ //Val[j]=splitmix64_stateless(Val[j])^Val[Pbox[j]];
+ //Val[j]=xorshift64(Val[j])^Val[Pbox[j]]; //fail
+// Val[j]=xorshift64(Val[j])^Val[Pbox[j]]^Val[Pbox2[j]];
+ Val[j]=xorshift64(Val[j]);
+
+ //Val[j]=xoroshiro128plus(&xoro[j])^Val[Pbox[j]];
+ //Val[j]=jsf(&ctx[j])^Val[Pbox[j]]; //good
+ //Val[j]=sfc(&sfcd[j])^Val[Pbox[j]]; //good
+ }
+ for(int j=0;j<bufsize;j++) {
+ Val[j]=Val[j]^Val[Pbox[j]]^Val[Pbox2[j]];
+ }
+
+
+ for(int j=0;j<bufsize;j++) {
+ cipher[nb*bufsize+j]=Val[j]^plain[nb*bufsize+j];
+ }
+
+
+
+
+ if(update==delta) {
+ update=0;
+ uchar *ptr=(uchar*)Val;
+ for(int j=0;j<bufsize*8;j++)
+ ptr[j]^=Sbox2[Sbox1[ptr[j]+DK[j&63]]];
+ rc4keyperm(ptr, bufsize, 1, Pbox, 64);
+ //only for xorshift
+ rc4keyperm(&ptr[32], bufsize, 1, Pbox2, 64);
+
+
+ rc4key(ptr, Sbox1, 64);
+ rc4key(&ptr[64], Sbox2, 64);
+ }
+ else
+ update++;
+ }
+
+
+
+}
+
+
+int main(int argc, char **argv) {
+// printf("%d %d \n",sizeof(__uint64_t),sizeof(ulong));
+
+
+ uint nb_test=1;
+
+ int width;
+ int height;
+ uchar *data_R, *data_G, *data_B;
+ int imsize;
+ uchar *buffer;
+
+ int size_buf=128;
+
+ int lena=0;
+ int h=128;
+ for(int i=1; i<argc; i++){
+ if(strncmp(argv[i],"nb",2)==0) nb_test = atoi(&(argv[i][2])); //nb of test
+ if(strncmp(argv[i],"h",1)==0) h = atoi(&(argv[i][1])); //size of block
+ if(strncmp(argv[i],"sizebuf",7)==0) size_buf = atoi(&(argv[i][7])); //SIZE of the buffer
+ if(strncmp(argv[i],"lena",4)==0) lena = atoi(&(argv[i][4])); //Use Lena or buffer
+ }
+
+
+
+
+
+
+
+ if(lena==1) {
+ load_RGB_pixmap("lena.ppm", &width, &height, &data_R, &data_G, &data_B);
+// load_RGB_pixmap("8192.ppm", &width, &height, &data_R, &data_G, &data_B);
+ imsize=width*height*3;
+// load_RGB_pixmap("No_ecb_mode_picture.ppm", &width, &height, &data_R, &data_G, &data_B);
+ }
+ else {
+ width=height=size_buf;
+ imsize=width*height;
+ buffer=new uchar[imsize];
+ for(int i=0;i<imsize;i++) {
+ buffer[i]=lrand48();
+ }
+ }
+
+
+ uchar* seq= new uchar[imsize];
+ uchar* seq2= new uchar[imsize];
+
+ int oneD=width*height;
+ if(lena) {
+ for(int i=0;i<oneD;i++) {
+ seq[i]=data_R[i];
+ seq[oneD+i]=data_G[i];
+ seq[2*oneD+i]=data_B[i];
+ }
+ }
+ else {
+ for(int i=0;i<oneD;i++) {
+ seq[i]=buffer[i];
+ }
+ }
+
+ uint64_t *SEQ=(uint64_t*)seq;
+ uint64_t *SEQ2=(uint64_t*)seq2;
+
+
+
+ uint64_t val=1021;
+ uint64_t val2=1021;
+
+ uint r1=21,r2=93;
+
+ uchar DK[64];
+ for(int i=0;i<64;i++)
+ DK[i]=splitmix64_stateless(i);
+
+
+ uchar Sbox1[256];
+ uchar Sbox2[256];
+ rc4key(DK, Sbox1, 8);
+ rc4key(&DK[8], Sbox2, 8);
+
+ int Pbox[h];
+ int Pbox2[h];
+ rc4keyperm(&DK[16], h, 1, Pbox, 16);
+ rc4keyperm(&DK[32], h, 1, Pbox2, 16);
+
+
+// uint64_t plain[bufsize];
+// uint64_t cipher[bufsize];
+
+
+ uint64_t Val[h];
+ for(int i=0;i<h;i++) {
+ Val[Pbox[i]]=splitmix64_stateless(i+DK[i&63]);
+ }
+
+
+ int delta=8;
+
+
+
+
+ double t=TimeStart();
+
+ int nb_bloc=imsize/(h*8); //8 because we use 64bits numbers
+
+
+
+ for(uint iter=0;iter<nb_test;iter++) {
+ scprng(SEQ, SEQ2, h, nb_bloc, Val,Sbox1, Sbox2, Pbox, Pbox2, DK, delta);
+ }
+
+ double time=TimeStop(t);
+ printf("%e ",nb_test*nb_bloc*h*8/time);
+
+ if(lena) {
+ for(int i=0;i<oneD;i++) {
+ data_R[i]=seq2[i];
+ data_G[i]=seq2[oneD+i];
+ data_B[i]=seq2[2*oneD+i];
+ }
+ store_RGB_pixmap("lena2.ppm", data_R, data_G, data_B, width, height);
+ }
+
+
+ //reinit of parameters
+ rc4key(DK, Sbox1, 8);
+ rc4key(&DK[8], Sbox2, 8);
+
+ rc4keyperm(&DK[16], h, 1, Pbox, 16);
+ rc4keyperm(&DK[32], h, 1, Pbox2, 16);
+ for(int i=0;i<h;i++) {
+ Val[Pbox[i]]=splitmix64_stateless(i+DK[i&63]);
+ }
+
+ t=TimeStart();
+
+
+ for(uint iter=0;iter<nb_test;iter++) {
+ scprng(SEQ2, SEQ, h, nb_bloc, Val,Sbox1, Sbox2, Pbox, Pbox2, DK, delta);
+ }
+
+
+ time=TimeStop(t);
+ printf("%e\n",nb_test*nb_bloc*h*8/time);
+
+ if(lena) {
+ for(int i=0;i<oneD;i++) {
+ data_R[i]=seq[i];
+ data_G[i]=seq[oneD+i];
+ data_B[i]=seq[2*oneD+i];
+ }
+ store_RGB_pixmap("lena3.ppm", data_R, data_G, data_B, width, height);
+ }
+ else {
+ bool equal=true;
+ for(int i=0;i<imsize;i++) {
+ //cout<<(int)buffer[i]<<endl;
+ if(buffer[i]!=seq[i]) {
+ equal=false;
+ }
+ }
+// cout<<"RESULT CORRECT: "<<equal<<endl;
+ }
+
+
+
+}