Vissza

4. labor: az RC4, az LFSR, az A51 titkosítók


1. Írjunk programot, mely RC4 módszerrel, egy 128 bites kulcsot használva, titkosít és visszafejt egy tetszőleges bináris állományt, ahol a kulcsot egy szövegállományból olvassuk ki, amelyben a kulcs base64-es alakját tároljuk. A rejtjelezés során az rc4_output első 1024 bájtját ne használjuk fel. Mérjük meg a rejtjelezés időigényét különböző méretű bináris állományok esetében.

2. A bináris állomány OTP-vel volt titkosítva. Határozzuk meg a nyílt szöveget, azaz az eredeti docx állományt, ha tudjuk, hogy ugyanazzal a kulcsfolyammal volt titkosítva az OTP_Massag.jpg állomány, amelynek a titkosított tartalma cryptOTP_Massag állomány.

3. A bináris állomány OTP-vel volt titkosítva, úgy hogy egy 16 bájtos kulcsot körkörösen alkalmaztunk az XOR művelet során. Határozzuk meg az eredeti html állományt, tudva, hogy az eredeti html állomány első 16 bájtja <!DOCTYPE html>\n-el egyenlő.

4. Írjunk programot, mely A51 módszerrel titkosít és visszafejt egy tetszőleges bináris állományt, mérjük meg a rejtjelezés időigényét különböző méretű bináris állományok esetében.

5. A bináris jpg állomány 32 bites LFSR folyamtitkosítóval volt titkosítva. Határozzuk meg a nyílt szöveget, azaz az eredeti állományt, ha meg van adva egy hogy a 0xe0ffd8ff 464a1000 hexa érték titkosított értéke: 0x880006b0 de683e80.

6. Írjunk programot, amely LFSR-16 módszerrel egy kezdeti 16 bites kulcsot használva, titkosít és visszafejt egy tetszőleges bináris állományt, ahol a kulcsot egy szövegállományból olvassuk ki, amelyben a kulcs hexadecimális alakját tároljuk. Mérjük meg a rejtjelezés időigényét különböző méretű bináris állományok esetében.

7. Írjunk programot, amely meghatározza, hogy a poly1305.txt állományban található rejtjelezett tartalmak közül melyik hiteles, ahol a hitelesített rejtjelezét a ChaCha20-Poly1305-el végeztük. Az állományba négy soronként a következők vannak írva: az első sorban a kulcs, a másodikban a nonce, a harmadikban a rejtjelezett szöveg a negyedikben a hitelesítési tag található.

Segédanyag

Az RC4 egy folyamtitkosító (stream cipher) algoritmus. Első lépésként egy kezdeti kulcs alapján egy tetszőleges hosszúságú kulcsfolyamot generál. Egy tetszőleges bináris állomány titkosítása egy időben történik a kulcsfolyam generálásával. A titkosítás bájtonként, a XOR művelet alkalmazásával történik, ahol a nyíltszöveg aktuális bájtját XOR-oljuk az éppen kigenerált kulcsfolyam megfelelő elemével

A kulcsfolyam wikipedián található implementációja C-ben a következő:

unsigned char S[256];
unsigned int i, j;

void swap(unsigned char *s, unsigned int i, unsigned int j) {
unsigned char temp = s[i];
s[i] = s[j];
s[j] = temp;
}

/* KSA: Key-scheduling algorithm */
/* As S tömb inicializálása: kezdetben megegyezik az identitás permutációval */
/* A 256-al történő maradékos osztás 255-tel való & (AND) muvelettel van megvalósítva*/
void rc4_init(unsigned char *key, unsigned int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;

for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}

/* PRGA: Pseudo-random genaration algorithm*/
/*Az álvéletlen értékeket meghatározó algoritmus*/

unsigned char rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);

return S[(S[i] + S[j]) & 255];
}

/*A foprogram, amely egy kezdeti kulcs alapján meghatározz a kulcsfolyamot*/
#include <stdio.h>
int main() {
int k, output_length;
//a kulcsfolyam létrehozása egy kezdeti kulcsérték, a key alapján történik
unsigned char key[] = "Cryptography";
rc4_init(key, 12); // a kulcs hossza 12

output_length = 40; //a kulcsfolyam hossza
k = 0;
while (k < output_length) {
printf("%c", rc4_output());
k++;
}
}

A kulcsfolyam Java implementációja a következő:

public class RC4_class {
public final int[] S;
public static int i, j;

public RC4_class (){
this.S = new int[256];
}

public static void swap(int []s, int i, int j) {
int temp = s[i];
s[i] = s[j];
s[j] = temp;
}

public void rc4_init(char[] key, int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;

for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}

public int rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);

return S[(S[i] + S[j]) & 255];
}
}

8 bites LFSR string-titkosítás:

typedef unsigned char uint8;
uint8 lfsr_output8(uint8 lfsr);
void crypt8(string& c, string m, uint8 lfsr);

int main() {
string m("This is a plaintext for 2017 crypt Lab! Try for longer text or file ");
uint8 lfsr = 0x87;
string c = "", m1 = "";
crypt8(c, m, lfsr);
cout << "crypted text: " << c << endl << endl << endl;

crypt8(m1, c, lfsr);
cout << "decrypted text: " << m1 << endl << endl << endl;
}

void crypt8(string& c, string m, uint8 lfsr){
for (int i = 0; i < m.length(); ++i) {
lfsr = lfsr_output8(lfsr);
c += m[i] ^ lfsr;
}
}

uint8 lfsr_output8(uint8 lfsr){
uint8 bit;
bit = ((lfsr >> 0) ^ (lfsr >> 3)) & 1;
lfsr = (lfsr >> 1) | (bit << 7);
return lfsr;
}

16 bites LFSR string-titkosítás:

typedef unsigned short uint16;
uint16 lfsr_output16(uint16 lfsr);
void crypt16(string &c, string m, uint16 lfsr);

void main() {
string m("This is a plaintext for 2017 crypt Lab!Try for longer text or file");
if (m.length() & 1) m += " ";
string m1 = "";
string c = "";
uint16 lfsr = 0x8735;

crypt16(c, m, lfsr);
cout << "crypted text: " << c << endl << endl << endl;
crypt16(m1, c, lfsr);
cout << "decrypted text: " << m1 << endl << endl << endl;
}

uint16 lfsr_output16(uint16 lfsr)<{
uint16 bit;
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1;
lfsr = (lfsr >> 1) | (bit << 15);
return lfsr;
}

void crypt16(string &c, string m, uint16 lfsr) {
uint16 temp;
for (int i = 0; i < m.length(); i += 2) {
lfsr = lfsr_output16(lfsr);
temp = ((uint8)m[i] << 8) | (uint8)m[i + 1];
temp = temp ^ lfsr;

uint8 st1 = temp >> 8;
c += st1;
uint8 st2 = 0xff;
temp = temp & st2;
c += temp;
}
}