Navigation
Artikel
Stuff
RSS Feeds
|
Tutorials - XOR verschlüsseln und die Keylänge bestimmen - Kryptanalse Teil 1Sprachenübersicht/Kryptologie/Cryptology/XOR Keywords: XOR keylänge bestimmen, XOR verschlüsseln, XOR entschlüsseln Inhaltsverzeichnis
Vorwort Top
Code: 0 ⊕ 0 = 0 0 ⊕ 1 = 1 1 ⊕ 0 = 1 1 ⊕ 1 = 0
Der Quellcode für eine XOR Verschlüsselung Top
Kryptoanalyse Top
Quote: 1. Discover the length of the key by a procedure known as counting coincidences. XOR the ciphertext against itself shifted various numbers of bytes, and count those bytes that are equal. If the displacement is a multiple of the key length, then something over 6 percent of the bytes will be equal. If it is not, then less than 0.4 percent will be equal (assuming a random key encrypting normal ASCII text; other plaintext will have different numbers). This is called the index of coincidence. The smallest displacement that indicates a multiple of the key length is the length of the key.
Eine Implementierung in Matlab Top
Code: function [] = LengthXOR(EncryptedText) %LengthXOR returns the expected value of the keylength % %Reads the encrypted Text fd = fopen(EncryptedText, 'r'); if(fd == -1) error('Die Datei exisitert nicht.'); end %The encrypted text which we have to analyse Enc = fread(fd); fclose(fd); %Gets the length a = 1; b = 1; Average = 0; %We create the table of convenience while (a < length(Enc)) Carent = a + 1; Passed = 0; b = 1; while (b <= length(Enc)) if(Carent > length(Enc)) Carent = 1; end if(bitxor(Enc(Carent),Enc(b)) == 0) Passed = Passed + 1; end Carent = Carent + 1; b = b + 1; end Convidence(a) = Passed * 100.0/length(Enc); Average = Average + Convidence(a); a = a + 1; end %The average of the convenience Average = Average / length(Enc); disp(sprintf('Keylength Average: %f',Average)); %Plot the indices of convenience a = (1 : 1 : length(Enc)-1); plot(a, Convidence, 'g+-'); xlabel('Move / Steps') ylabel('Convidence / %') %axis([1,length(Enc)-1, 0, 100]) title('Keylength Analyse'); %We have to set an border NewAverage = input(sprintf('Average Border (0 = %d), try 4.5:', Average + 1.5)); if(NewAverage == 0) NewAverage = Average +1; end a = 1; b = 0; KeyLength = 0; KeyLengthVector(1, 1) = 0; %We create a table of convenience in the border while(a < length(Enc)) if(Convidence(a) > NewAverage) KeyLengthVector(b+1,1) = a; if(b == 0) KeyLength = a; end b = b + 1; end a = a + 1; end disp(sprintf('Keylength calculated by the first peek: %d',KeyLength)); %Keylengthtable b = 1; c = 1; NewKeyLengthVector(1,1) = 0; NewKeyLengthVector(1,2) = 0; while(b <= length(KeyLengthVector)) KeyLengthVector(b,2) = 0; a = 1; while(a <= length(KeyLengthVector)) if(rem(KeyLengthVector(a), KeyLengthVector(b)) == 0) KeyLengthVector(b,2) = KeyLengthVector(b,2) +1; end a = a + 1; end if(KeyLengthVector(b,2) > 1) NewKeyLengthVector(c,1) = KeyLengthVector(b,1); NewKeyLengthVector(c,2) = KeyLengthVector(b,2); c = c + 1; end b = b + 1; end disp('Other possible Keylengths [Keylenght, Num of peaks: the highter, the better]:'); disp(sortrows(NewKeyLengthVector,2));
Code: Key: AsWrTes Plaintext: Coincidence counting can help determine when two texts are written in the same language... [aus der Wikipedia] >> EncryptXOR('plaintext','keyfile','out'); LengthXOR('out'); Encryption Done... Keylength: 8 Plaintextlength: 297 Keylength Average: 1.639289 Average Border (0 = 3.139289e+00), try 4.5:3.139 Keylength calculated by the first peek: 8 Other possible Keylengths [Keylenght, Num of peaks: the highter, the better]: 48 2 40 3 56 3 32 4 24 6 16 8 8 17
C++ Quellcode Top
Code: #include <sstream> #include <iostream> #include <fstream> #include <iterator> std::string IntToString(int iValue) { std::stringstream ssStream; ssStream << iValue; return ssStream.str(); } std::string GetData(std::string strFileName) { std::ifstream FStream; FStream.open(strFileName.c_str()); FStream.unsetf(std::ios_base::skipws); std::istream_iterator<char> begin(FStream), end; std::string strFileData(begin, end); FStream.close(); return strFileData; } int main(int args, char* argv[]) { if(args != 4) { std::cout << "Usage: " << argv[0] << " <Input File> <Key File> <Output File>" << std::endl; return 0; } std::string strInputFile = argv[1]; std::string strKeyFile = argv[2]; std::string strOutputFile = argv[3]; std::string strInputFileData = GetData(strInputFile); std::string strKeyFileData = GetData(strKeyFile); std::ofstream OFStream; OFStream.open(strOutputFile.c_str(), std::ios::out); int KeyLength = 0; //Size der files auf 0 überprüfen //TODO int z = 0; for (int i = 0; i < (int) strInputFileData.size(); i++) { if(z >= (int) strKeyFileData.size()) z = 0; char Key = strKeyFileData[z]; char Input = strInputFileData[i]; char Output = Input ^ Key; OFStream << Output; z++; } OFStream.close(); /****************** DECRYPT **************/ // //1. Part: Try to get the keylength // std::string strOutputFileData = GetData(strOutputFile); int OutPutSize = strOutputFileData.size(); int Carent = 0; std::cout << "Output: " << OutPutSize << " chars\n"; std::cout << "Key: " << strKeyFileData.size() << " chars\n"; std::cout << "Input: " << strInputFileData.size() << " chars\n"; float *Coincidence = new float[OutPutSize]; float Average = 0; for(int i = 0; i < (OutPutSize - 1); i++) { Carent = i+1; int iPass = 0; for(int y = 0; y < OutPutSize; y++) { if(Carent >= OutPutSize) Carent = 0; char OutputShifted = strOutputFileData[Carent]; char Output = strOutputFileData[y]; char New = Output ^ OutputShifted; if(New == 0) iPass++; Carent++; } //std::cout << "Equal " << i << ": " << iPass << " in percent: " << ((float)iPass * 100.0 /(float)OutPutSize) << "%" << std::endl; Coincidence[i] = ((float)iPass * 100.0 /(float)OutPutSize); Average += Coincidence[i]; } // Calculates the average Average = Average / OutPutSize; for(int a = 0; a < OutPutSize; a++) if(Coincidence[a] > Average) { //The first peak index KeyLength = (a+1); break; } std::cout << "Key Length: " << KeyLength << std::endl; // //2. Part: Try to get the plaintext shifted with the keylength // //XOR the chipertext with itself shifted by the keylength Carent = KeyLength; std::string KeyShiftedByItself = ""; for(int c = 0; c < OutPutSize; c++) { if(Carent >= OutPutSize) Carent = 0; KeyShiftedByItself += strOutputFileData[Carent] ^ strOutputFileData[c]; Carent++; } // //3. Part: Analyse // // //in suchen, im suchen int Index = 0; int MaxCombo = 0; for(int d = 0; d < OutPutSize; d++) { Index = 0; while((int)KeyShiftedByItself[d + Index] == 0) { Index++; if(Index > MaxCombo && Index < 4) MaxCombo = Index; } } std::string Output = ""; std::string Key = ""; for(int h = 0; h < KeyLength; h++) Key += " "; std::string Pattern = ""; std::cout << "We found some pattern with " << MaxCombo << " chars which seems to appear frequently. Set the pattern:"; std::cin >> Pattern; std::cout << "Replace the first 0x00 with " << Pattern << std::endl; for(int e = 0; e < OutPutSize; e++) { bool Pass = true; for(int f = 0; f < MaxCombo; f++) { if(KeyShiftedByItself[e + f] != 0) Pass = false; } if(Pass == true) for(int g = 0; g < MaxCombo; g++) Key[(g % KeyLength)] = strOutputFileData[g] ^ Pattern[g]; } // for(int j = 0; j < OutPutSize; j++) // Output += strOutputFileData[j] ^ Key [j]; // std::cout << Output << std::endl; std::cout << Key; delete[] Coincidence; return 0; }
Wie geht es weiter? Top
Weblinks Top
Gibt es noch irgendwelche Fragen, oder wollen Sie über den Artikel diskutieren? Sprachenübersicht/Kryptologie/Cryptology/XOR/XOR verschlüsseln und die Keylänge bestimmen - Kryptanalse Teil 1 |