#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
using namespace std;
typedef struct {
uint64_t state;
uint64_t taps;
} LFSR;
int parity(uint64_t N)
{
int p = __builtin_parity(N);
N = __builtin_bswap64(N);
return (p+__builtin_parity(N))%2;
}
int read_lfsr(LFSR* L)
{
uint64_t rightMostBit = L->state &1;
return rightMostBit;
}
void next_state(LFSR* L)
{
uint64_t next_bit = parity(L->state & L->taps);
L-> state = L->state >> 1;
L->state = L->state | (next_bit << 63);
}
void init_LFSR(LFSR* L, uint64_t initial_state, uint64_t taps)
{
L->state = initial_state;
L->taps = taps;
}
unsigned char get_stream_byte(LFSR* L)
{
unsigned char C = 0;
int i = 7;
for(;i>=0;i--)
{
C |= (read_lfsr(L)<<i);
next_state(L);
}
return C;
}
void encrypt(const char* pt, const char* ct,LFSR *L)
{
FILE* PT = fopen(pt,"r");
FILE* CT = fopen(ct,"w");
assert(PT);
assert(CT);
int c;
while((c=getc(PT))!=-1)
{
unsigned char sb = get_stream_byte(L);
fputc(sb^c,CT);
}
fclose(PT);
fclose(CT);
}
void decrypt(const char* pt, const char* ct,LFSR *L)
{
uint64_t initial_state;
L->state = initial_state;
encrypt(pt,ct,L);
}
void get_128_keystream_bits(const char* ct, const char* kpt)
{
FILE* ct_f = fopen(ct,"r");
FILE* fp = fopen("key_stream.txt","w");
FILE* fs = fopen("key.txt","w");
int i = 0;
for(;i<16;i++)
{
unsigned char ctc = getc(ct_f);
unsigned char b = ctc^kpt[i];
int j = 7;
for(;j>= 0;j--)
{
char current_bit = parity(b&(1 << j));
fprintf(fp, "%u\n", current_bit);
fprintf(fs, "%u", current_bit);
}
}
fclose(fp);
fclose(ct_f);
}
void shape_keystream()
{
FILE* fp = fopen("key_stream.txt","r");
FILE* VS = fopen("V.mat.sage","w");
FILE* SS = fopen("S.mat.sage","w");
assert(fp);
assert(SS);
assert(VS);
int buffer[128];
for(int i = 0; i < 128; i++)
{
fscanf(fp, "%d", &buffer[i]);
}
fprintf(SS, "A = matrix(Zmod(2),[[");
for(int i = 0; i < 64; i++)
{
for(int j = 0; j < 64; j++)
{
if(i + j < 127 && j < 63)
fprintf(SS, "%d,", buffer[i + j]);
else
fprintf(SS, "%d", buffer[i + j]);
}
if (i < 63)
{
fprintf(SS, "],\n[");
}
}
fprintf(SS, "]])\n");
fprintf(VS, "x = vector(Zmod(2),[");
for(int i = 64; i < 128; i++)
{
fprintf(VS, "%d", buffer[i]);
if (i < 127)
{
fprintf(VS, ",");
}
else
fprintf(VS, "])");
}
fclose(fp);
fclose(SS);
fclose(VS);
}
int main()
{
LFSR L;
uint64_t initial_state = 0xc2d075d0518516e9L;
uint64_t taps = 0x578140d19a35c76c;
init_LFSR(&L,initial_state,taps);
encrypt("toy_pt.txt","ct.dat",&L);
init_LFSR(&L,initial_state,taps);
decrypt("ct.dat","toy_ot.txt",&L);
get_128_keystream_bits("target_ciphertext","THE PROJECT GUTEN");
shape_keystream();
}