Documente Academic
Documente Profesional
Documente Cultură
RAPORT Lucrare de laborator Nr.5 Tema: Algoritmi simetrici de criptare. Algoritmul DES.
A efectuat :
A verificat:
Chiinu 2012
Scopul lucrrii De implimentat algoritmul de criptare DES. Sarcina lucrarii De realizat un program care ar implementa funcionarea algoritmului DES.
Noiuni teoretice despre algoritmul DES Standardul de Criptare a Datelor (n englez Data Encryption Standard, DES) este un cifru (o metod de criptare a informaiei), selectat ca standard federal de procesare a informaiilor n Statele Unite n 1976, i care s-a bucurat ulterior de o larg utilizare pe plan internaional. Algoritmul a fost controversat iniial, avnd elemente secrete, lungimea cheii scurt i fiind bnuit c ascunde de fapt o porti pentru NSA. DES a fost analizat intens de ctre profesionaliti n domeniu i a motivat nelegerea cifrurilor bloc i criptanaliza lor. DES este astzi considerat nesigur pentru multe aplicaii. Acest lucru se datoreaz n principiu cheii de 56 de bii, considerat prea scurt; cheile DES au fost sparte n mai puin de 24 de ore. De asemenea, exist unele rezultate analitice care demonstreaz slbiciunile teoretice ale cifrului, dei nu este fezabil aplicarea lor. Se crede c algoritmul este practic sigur n forma Triplu DES, dei exist atacuri teoretice i asupra acestuia. n ultimii ani, cifrul a fost nlocuit de Advanced Encryption Standard (AES). n unele documentaii, se face distincie ntre DES ca standard i algoritmul de la baza lui, numit DEA (Algoritmul de Criptare a Datelor - n englez, Data Encryption Algorithm). 2 2.1 Descriere DES este cifrul bloc arhetip un algoritm care ia un ir de lungime fix de bii de text normal i l transform print-o serie de operaii complexe ntr-un ir de bii criptai de aceeai lungime. n cazul DES, mrimea blocului este de 64 bii. DES folosete de asemenea i o cheie pentru particularizarea transformrii, astfel nct numai cei care cunosc cheia folosit s poat efectua decriptarea. Cheia este format din 64 de bii; totui, numai 56 dintre ei sunt folosii propriu-zis de algoritm. Opti bii sunt utilizai ca bii de paritate i nu sunt necesari dup acest test. Deci cheia efectiv are doar 56 de bii, i aa este citat de obicei. Ca i alte cifruri bloc, DES nu este o cale sigur de criptare folosit de sine-stttor. El trebuie folosit ntr-un mod de operare. FIPS-81 specific cteva feluri pentru utilizarea cu DES. Alte comentarii despre acest lucru apar n FIPS-74. Structura general Structura general a algoritmului: sunt 16 pai identici de procesare, numii runde. Exist i cte o permutare iniial i final, numite PI and PF, care sunt funcii inverse (PI "anuleaz" aciunea lui PF i vice versa). PI i PF nu au aproape nici o importan criptografic, dar au fost incluse pentru a facilita ncrcarea i descrcarea blocurilor folosind hardware-ul din anii 1970. naintea rundelor principale, blocul este mprit n dou jumti, de cte 32 de bii, i procesate alternativ; aceast alternare este cunoscut drept Schema Feistel. Structura Feistel asigur c criptarea i decriptarea sunt procese foarte asemntoare singura dieferen este ordinea aplicrii subcheilor invers la decriptare. Restul algoritmului este identic. Acest lucru simplific implementarea, n special cea hardware, deoarece nu e nevoie de algoritmi separai. Funcia F amestec jumtate din bloc cu o subcheie. Rezultatului funciei F este combinat cu cealalt jumtate de bloc, iar jumtile sunt interschimbate naintea urmtoarei runde. Dup ultima rund, jumtile nu sunt schimbate; aceasta este o trstur a structurii Feistel care face din criptare i decriptare procese similare. 2.2 2
Reazilarea sarcinii Pentru implementarea algoritmului DES a fost ales limbajul de programare C# i IDE Visual Studio 2010.
using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Collections;
namespace lab5DES { class AlgDES { int[] IP = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; int[] FP = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 }; int[] Ext = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24, 25, 26, 28, 29, 30, 7, 11, 15, 19, 23, 27, 31, 17, 26, 10, 14, 9, 6, 25 8, 12, 16, 20, 24, 28, 32, 9, 13, 17, 21, 25, 29, 1
int[] P =
}; 16,
7, 20, 21, 29, 12, 28, 1, 15, 23, 5, 18, 31, 2, 8, 24, 32, 27, 3, 19, 13, 30, 22, 11, 4,
}; int[,] S1 = { {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}; int[,] S2 = { {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}; int[,] S3 = { {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} }; int[,] S4 = { {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} }; int[,] S5 = { {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}
}; int[,] S6 = { {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} }; int[,] S7 = { {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} }; int[,] S8 = { {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} }; int[] PC1 = { 57, 49, 41, 1, 58, 10, 2, 19, 11, 63, 55, 7, 62, 14, 6, 21, 13, }; int[] PC2 = { 14, 3, 23, 16, 41, 30, 44, 46, int[] Rot = { }; 1, 1, 17, 28, 19, 7, 52, 40, 49, 42, 11, 15, 12, 27, 31, 51, 39, 50, 24, 6, 4, 20, 37, 45, 56, 36, 1, 21, 26, 13, 47, 33, 34, 29, 1 5, 10, 8, 2, 55, 48, 53, 32 33, 50, 59, 3, 47, 54, 61, 5, 25, 42, 51, 60, 39, 46, 53, 28, 17, 34, 43, 52, 31, 38, 45, 20, 9, 26, 35, 44, 23, 30, 37, 12, 18, 27, 36, 15, 22, 29, 4
2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
}; //Functia Sau - exclusiv pentru 2 secvente binare public char[] XOR(char[] a, char[] b) { char[] result = new char[a.Length]; for(int i = 0 ; i < a.Length; i++) { if(a[i] == b[i]){ result[i] = '0'; }else { result[i] = '1'; } } return result; } //Transformarea a 8 secvente binare cite 6 biti in public string B6toB4(char[] B, int nr) { int a = 0; int b = 0; int b4 = 0; int[] iB = new int[6]; for (int i = 0; i < 6; i++) { if (B[i] == '1') { iB[i] = 1; } else { iB[i] = 0; } } string sb4 = string.Empty;
4 biti
a = (iB[0] * 2) + iB[5];//aflam numarul intreg din bitul 1 si 6 b = (iB[1] * 8) + (iB[2] * 4) + (iB[3] * 2) + iB[4]; // aflam numarul intreg din bitii 2,3,4,5 // gasim valiarea corespunzatoare din tabelele Si[a,b] switch (nr) {
0: 1: 2: 3: 4: 5: 6: 7:
b4 b4 b4 b4 b4 b4 b4 b4
= = = = = = = =
} //Transformarea din valoare zecimal[ ]n binar[ if (b4 < 8 && b4 > 3) { sb4 = "0"; } else if (b4 == 0 || b4 == 1) { sb4 = "000"; } else if (b4 < 4 && b4 > 1 ) {sb4 = "00";} sb4 += Convert.ToString(b4, 2); return sb4; // returnam sir de secvente binare a cite 4 biti } // functia F public char[] F(char[] Keyi, char[] Ri) { char[] RiExt = new char[48]; char[] B = new char[48]; char[,] bTable = new char[8, 6]; // B = E(Ri) XOR Ki string b4 = string.Empty; char[] b6 = new char[6]; char[] cb4 = new char[32]; char[] Pb4 = new char[32]; int count = 0; //Extention Ri pina la 48 biti for(int i = 0; i < 48; i++){ RiExt[i] = Ri[Ext[i]-1]; } //Operatia XOR dintre partea dreapta extinsa si cheia corespunzatiare turului B = XOR(RiExt,Keyi); // construirea tabelului din 8 secvente a cite 6 biti for (int i = 0; i < 8; i++) { for (int j = 0; j < 6; j++) { bTable[i, j] = B[count]; count++; } } //Transformarea secventelor din 6 biti in 4 biti for(int i = 0; i< 8;i++){ for (int j = 0; j < 6; j++) { b6[j] = bTable[i, j]; } b4 += B6toB4(b6, i);//Functia de transformare } //Permutarea P cb4 = b4.ToCharArray(0,32); for(int i = 0; i < P.Length; i++) { Pb4[i] = cb4[P[i] - 1]; } return Pb4; //Intoarcerea secventei de 32 biti } //Functia de criptare a blocului de 64 biti string EncryptBloc(char[] Block, char[,] key) { string encodedText = string.Empty; char[] IPBlock = new char[64]; char[] Left = new char[32]; char[] Right = new char[32]; char[] keyI = new char[48]; char[] fResult = new char[56]; char [] Rinext = new char[32]; char[] L16R16 = new char[64]; char[] FPL16R16 = new char[64]; //Permutarea initiala for (int i = 0; i < Block.Length; i++) { IPBlock[i] = Block[IP[i]-1]; }
//Impartirea blocului de 64 biti in partea dreapta si stinga a cite 32 biti for(int i = 0; i < 32; i++) { Left[i] = IPBlock[i]; Right[i] = IPBlock[i+32]; } //Ciclul pentru 16 tururi de criptare a unui bloc for(int i = 0; i < 16; i++) { //extragerea cheii corespunzatoare iteratiei de criptare for( int j = 0; j < 48; j++ ) { keyI[j] = key[i,j]; } fResult = F(keyI, Right);// rezultatul functiei F //Sau exclusiv dintre rezultatul functiei F si partea stinga Rinext = XOR(Left, fResult); // schimbarea partii stingi cu partea dreapta for (int j = 0; j < 32; j++) { Left[j] = Right[j]; } for (int j = 0; j < 32; j++) { Right[j] = Rinext[j]; } } //Construirea din partea Stinga si Dreapta a unei secvente de 64 biti dupa a 16-lea tur for (int i = 0; i < 32; i++) { L16R16[i] = Left[i]; L16R16[i + 32] = Right[i]; } //Permutarea finala for (int i = 0; i < 64; i++) { FPL16R16[i] = L16R16[FP[i] - 1]; } //Conversia din secventa de biti in sir de caractere encodedText = convetFromCharArrayOfBitesToString(FPL16R16); return encodedText; } //Functia pentru cinversi din sirul de biti in sirul de carectere public string convetFromCharArrayOfBitesToString(char[] arr) { int start = 0; int stop = 8; int count = 0; int val = 0; string result = string.Empty; while(stop < 65){ // transformarea a 64biti in numar intreg for (int i = start; i < stop; i++) { switch (count) { case 0: if (arr[i] == '1') { val case 1: if (arr[i] == '1') { val case 2: if (arr[i] == '1') { val case 3: if (arr[i] == '1') { val case 4: if (arr[i] == '1') { val case 5: if (arr[i] == '1') { val case 6: if (arr[i] == '1') { val case 7: if (arr[i] == '1') { val } count++; } start +=8; stop +=8; count = 0; //Introducerea in sir de caractere a caracterul din tabelul ASCCII extins result += char.ConvertFromUtf32(val); val = 0; } return result; }
+= += += += += += += +=
128; } break; 64; } break; 32; } break; 16; } break; 8; } break; 4; } break; 2; } break; 1; } break;
//Functia pentru rotatie circulara la stinga public char[] leftShift(char[] arr, int times) { char[] tmpShift = new char[times]; char[] tmpRemain = new char[arr.Length - times]; char[] resultArr = new char[arr.Length]; int j = 0; int r = 0; for (int i = 0; i < times; i++) { tmpShift[i] = arr[i]; } for (int i = times; i < arr.Length; i++) { tmpRemain[j] = arr[i]; j++; } j = 0; for (int i = r ; i < tmpRemain.Length; i++) { resultArr[i] = tmpRemain[i]; r++; } for (int i = 0; i < tmpShift.Length; i++) { resultArr[r] = tmpShift[i]; r++; } return resultArr; } // Functia pentru generarea a 16 chei public char[,] Generate16Keys(char[] key) { char[,] keys16 = new char[16,48]; char[] C0D0 = new char[56]; char[] C0 = new char[28]; char[] D0 = new char[28]; char[] Ci = new char[28]; char[] Di = new char[28]; char[] CiDi = new char[56]; char[] arrPC2 = new char[48]; //Eliminarea din cheia initiala a bitilor de paritare prin permutarea PC1 for (int i = 0; i < PC1.Length; i++) { C0D0[i] = key[PC1[i] - 1]; } int shiftTimes = 0; //Impartirea cheii de 56 biti in doua secvente a cite 28 biti for (int i = 0; i < 28; i++) { C0[i] = C0D0[i]; D0[i] = C0D0[i + 28]; } //Ciclul din pentru generarea a 16 chei for (int i = 0; i < 16; i++) { //Calcului mumarului de deplasari la stinga pentru cheia curenta for (int j = 0; j < i + 1; j++) { shiftTimes += Rot[j]; } Ci = leftShift(C0, shiftTimes);//Deplasarile la stinga Di = leftShift(D0, shiftTimes);//a fiecarei secvente de 28 biti shiftTimes = 0; //Construirea a unei secvente de 56 biti for (int q = 0; q < 28; q++) { CiDi[q] = Ci[q]; CiDi[q+28] = Di[q]; } //Permutarea PC2 for (int q = 0; q < 48; q++) { arrPC2[q] = CiDi[PC2[q] -1]; } //Introducerea cheii nou obtinute in tabel de chei for (int q = 0; q <48; q++) {
keys16[i,q] = arrPC2[q]; } } return keys16; //Intoarcerea a tabelului de 16 chei } //Functia pentru criptare sau decripatarea a siruli de caractere public string EncriptDecrypt(string Text, string Key, bool Encript) { char[] arr; char[] arrKey; char[,] keys16 = new char[16, 48]; int blocks = Text.Length / 8; int blockCount = 0; int len = 0; string result = string.Empty; string bintext = string.Empty; string binKey = string.Empty; string intermed = string.Empty; //transforamarea sirului de caractere in secventa de biti foreach (char ch in Text) { if (ch <= 128 && ch >= 64 ) { bintext += "0"; } else if (ch < 64 && ch >= 32) { bintext += "00"; } else if (ch < 32 && ch >= 16) { bintext += "000"; } else if (ch < 16 && ch >= 8) { bintext += "0000"; } else if (ch < 8 && ch >= 4) { bintext += "00000"; } else if (ch < 4 && ch >= 2) { bintext += "000000"; } else if (ch == 1 && ch == 0) { bintext += "0000000"; } intermed = Convert.ToString((int)ch, 2); bintext += intermed; len = bintext.Length; } // Transforamrea cheii in secventa de biti foreach (char ch in Key) { binKey += "00"; binKey += Convert.ToString((int)ch, 2); } arrKey = binKey.ToCharArray(0, 64); //Genereara a 16 chei keys16 = Generate16Keys(arrKey); // Ciclu de criptarea/decriptarea a fiecarui bloc a cite 64 biti while (blockCount < blocks) { arr = bintext.ToCharArray(0 + (64 * blockCount), 64); if (Encript) { result += EncryptBloc(arr, keys16); } else { result += DecryptBloc(arr, keys16); } int resLen = result.Length; blockCount++; } return result; } //functia pentru decriptarea blocului de 64 biti string DecryptBloc(char[] Block, char[,] key) { string encodedText = string.Empty; char[] IPBlock = new char[64]; char[] Left = new char[32]; char[] Right = new char[32]; char[] keyI = new char[48]; char[] fResult = new char[56]; char[] Linext = new char[32]; char[] L16R16 = new char[64]; char[] FPL16R16 = new char[64]; //Permutarea initiala for (int i = 0; i < Block.Length; i++) { IPBlock[i] = Block[IP[i] - 1]; } //impartirea a blocului de 64 biti in parte stinga si dreapta
for (int i = 0; i < 32; i++) { Left[i] = IPBlock[i]; Right[i] = IPBlock[i + 32]; } //16 iteratii de decriptare, incelem cu a 16 cheie for (int i = 15; i >= 0; i--) { for (int j = 0; j < 48; j++) { keyI[j] = key[i, j]; } //rezultatul functiei F fResult = F(keyI,Left); // Sau exclusiv dintre rezultatul functiei F si partea dreapta Linext = XOR(Right, fResult); //Atribuirea valorilar partilor drepte si stingi pentru iteratia urmatoare for (int j = 0; j < 32; j++) { Right[j] = Left[j]; } for (int j = 0; j < 32; j++) { Left[j] = Linext[j]; } } //Construirea din partea stinga si dreapta dupa a 16-a iteratie a sirului de 64 biti for (int i = 0; i < 32; i++) { L16R16[i] = Left[i]; L16R16[i + 32] = Right[i]; } //Permutarea finala for (int i = 0; i < 64; i++) { FPL16R16[i] = L16R16[FP[i] - 1]; } encodedText = convetFromCharArrayOfBitesToString(FPL16R16); return encodedText; } } }
Descrierea aplicatiei Interfaa grafic este format din o singur fereastr(Figura 3) cu campuri rezervate pentru mesajul ce urmeaz a fi criptat/decriptat, cheia de criptare/decriptare, 2 butoane pentru criptarea/decriptarea mesajului introdus, rezultatul rulrii algoritmului este prezentat in campul de mai jos de buton.
Concluzie Realizarea acestei lucrri de laborator mi-a permis studierea unui algoritm de criptare din grupul celor cu cheie simetric, i anume algoritmul DES. n urma analizei acestui algoritm, am determinat paii care trebuie urmai pentru a efectua att criptarea ct i decriptarea determinnd pentru fiecare din operaii cteva calcule de transformare a mesajului iniial/criptat i a cheii comune n obinerea unui mesaj criptat/decriptat. n general consider c pentru aplicaii mici alroritmul DES este foarte comod de ntrebuinat deoarece este relativ sigur ns pentru sisteme mari acest algoritm va da locul altor algoritmi mai evoluai i siguri. Bibliografia: 1. .. 2. http://msdn.microsoft.com [Descrierea claselor, proprietilor i metodelor limbajului C#]
10