/// <summary> /// Decryption of a byte array. /// The key data should be a hash of the PSI's hash function. /// </summary> /// <param name="inputData">Input byte array</param> /// <param name="keyData">Key data</param> /// <returns>Decrypted byte array</returns> public byte[] DecryptByteArray(byte[] inputData, byte[] keyData) { //Input Bytes werden invertiert und in ByteGrids aufgeteilt. [SCHRITT 1 DER ENTSCHLÜSSELUNG] ByteSplitterDecrypt byteSplitter = new ByteSplitterDecrypt(statics.ByteInverter.invertBytes(inputData)); //Speicherreservierung für die Entschlüsselungsdaten. byte[] outputAllocArray = new byte[byteSplitter.getGridAmount() * 256]; //Die erste S-Box wird definiert. Sie wird aus dem keyData-Array über die Hash-Funktion errechnet. byte[] lastSBox = HashFunction256.createByteHash(System.Text.Encoding.ASCII.GetString(keyData)); //Der Schlüssel für den ersten Block ist keyData. byte[] lastKey = keyData; //Entschlüsselung der Blöcke: for (int i = 0; i < byteSplitter.getGridAmount(); i++) { //Erstellung eines temporären ByteArrays zur weiteren Verarbeitung. byte[] tmpBytes = byteSplitter.getGridAt(i).getGridBytes(); //S-Box wird aufgelöst. [SCHRITT 2 DER ENTSCHLÜSSELUNG] tmpBytes = NeutralizeSBox(tmpBytes, lastSBox); //ByteArray wird zurück in ByteGrid geschrieben. ByteGrid tmpGrid = new ByteGrid(tmpBytes); //Vertikale Permutation: [SCHRITT 3 DER ENTSCHLÜSSELUNG] for (int j = 0; j < 16; j++) { tmpGrid.permutateVertical(j, (byte)(16 - (lastKey[16 + j] % 16))); } //Horizontale Permutation: [SCHRITT 4 DER ENTSCHLÜSSELUNG] for (int j = 0; j < 16; j++) { tmpGrid.permutateHorizontal(j, (byte)(16 - (lastKey[j] % 16))); } //Speichern der Grids für den späteren Gebrauch. byte[] nextKey = HashFunction32.createByteHashFromGrid(tmpGrid); byte[] nextSBox = HashFunction256.createByteHashFromGrid(tmpGrid); //Bytes werden umgewandelt zu ByteArray. tmpBytes = tmpGrid.getGridBytes(); //Der entschlüsselte Block wird in outputAllocArray an die richtige Stelle kopiert. for (int j = 0; j < tmpBytes.Length; j++) { outputAllocArray[i * 256 + j] = tmpBytes[j]; } //Die S-Box für den nächsten Block wird aus dem originalen aktuellen Block errechnet. lastSBox = nextSBox; //Der Key für den nächsten Block wird aus dem originalen aktuellen Block errechnet. lastKey = nextKey; } //EndOfFile Token wird erstellt. byte[] EOFToken = new byte[statics.Definitions.dataFinishingToken.Length]; System.Array.Copy(statics.Definitions.dataFinishingToken, EOFToken, statics.Definitions.dataFinishingToken.Length); System.Array.Reverse(EOFToken); int followingEquals = 0; int arrayCutoffPosition = 0; for (int i = outputAllocArray.Length - 1; i > (outputAllocArray.Length - 288); i--) { if (outputAllocArray[i] == EOFToken[followingEquals]) { followingEquals++; if (followingEquals == EOFToken.Length - 1) { arrayCutoffPosition = i; break; } } } //Abschneiden der überschüssigen Bytes. byte[] outputData = new byte[arrayCutoffPosition - 1]; System.Array.Copy(outputAllocArray, outputData, arrayCutoffPosition - 1); //Zurückgeben der entschlüsselten Daten. return(outputData); }
/// <summary> /// Creates a hash of the string as string. /// </summary> /// <param name="Value">String to hash</param> /// <param name="Length">Length of output</param> /// <returns>Hash as string</returns> public string getHashAsString(string Value, int Length = 32) { utility.HashFunction tmp = new utility.HashFunction(Length); return(tmp.convertByteHashToString(tmp.createByteHash(Value))); }
/// <summary> /// Encryption of a byte array. /// The key data should be a hash of the PSI's hash function. /// </summary> /// <param name="inputData">Input byte array</param> /// <param name="keyData">Key data (should be 32 bytes in size)</param> /// <returns>Encrypted byte array</returns> public byte[] EncryptByteArray(byte[] inputData, byte[] keyData) { //Zerlegung in ByteGrids durch die ByteSplitter-Klasse. ByteSplitterEncrypt byteSplitter = new ByteSplitterEncrypt(inputData); //Reservierung des Arbeitsspeichers für die verschlüsselten Blöcke. //Ein Block hat eine Größe von 16x16 Bytes, d.h. ist 256 Bytes groß. byte[] outputBytes = new byte[256 * byteSplitter.getGridAmount()]; //Die erste S-Box wird definiert. Sie wird aus dem keyData-Array über die Hash-Funktion errechnet. byte[] lastSBox = HashFunction256.createByteHash(System.Text.Encoding.ASCII.GetString(keyData)); //Der Schlüssel für den ersten Block ist keyData. byte[] lastKey = keyData; //Verschlüsselung der Blöcke: for (int i = 0; i < byteSplitter.getGridAmount(); i++) { //Erstellung eines temporären ByteGrids zur weiteren Verarbeitung. ByteGrid tmpGrid = byteSplitter.getGridAt(i); //Speichern der Grids für den späteren Gebrauch. byte[] nextKey = HashFunction32.createByteHashFromGrid(tmpGrid); byte[] nextSBox = HashFunction256.createByteHashFromGrid(tmpGrid); //Horizontale Permutation: [SCHRITT 1 DER VERSCHLÜSSELUNG] for (int j = 0; j < 16; j++) { //In Zeile j werden die Bytes um (lastKey[j] mod 16) nach links verschoben. tmpGrid.permutateHorizontal(j, (byte)(lastKey[j] % 16)); } //Vertikale Permutation: [SCHRITT 2 DER VERSCHLÜSSELUNG] for (int j = 0; j < 16; j++) { //In Spalte j werden die Bytes um (lastKey[16 + j] mod 16) nach unten verschoben. tmpGrid.permutateVertical(j, (byte)(lastKey[16 + j] % 16)); } //Das ByteGrid wird als ByteArray dargestellt. byte[] shuffledBytes = tmpGrid.getGridBytes(); //Die S-Box wird angewendet. [SCHRITT 3 DER VERSCHLÜSSELUNG] shuffledBytes = ApplySBox(shuffledBytes, lastSBox); //Der verschlüsselte Block wird in outputBytes an die richtige Stelle kopiert. for (int j = 0; j < shuffledBytes.Length; j++) { outputBytes[i * 256 + j] = shuffledBytes[j]; } //Die S-Box für den nächsten Block wird aus dem originalen aktuellen Block errechnet. lastSBox = nextSBox; //Der Key für den nächsten Block wird aus dem originalen aktuellen Block errechnet. lastKey = nextKey; } //Rückgabe und Invertierung des verschlüsselten Arrays. [SCHRITT 4 DER VERSCHLÜSSELUNG] return(statics.ByteInverter.invertBytes(outputBytes)); }