public string Encrypt(string plainText, string key) { string plainTextPadded = Helpers.PadMod8(plainText, ' '); string masterKeyPadded = Helpers.PadMod8(key, '-'); BitBlock masterKey = new BitBlock(masterKeyPadded); BitBlock[] subKeys = GenerateSubKeys(ProcessType.Encrypt, masterKey); char[] plainTextCharArray = plainTextPadded.ToCharArray(); byte[] allEncryptedBytes = new byte[plainTextCharArray.Length]; int inputIndex = 0; int numberOfInputBlocksof64BitsToEncrypt = plainTextCharArray.Length / 8; for (int i = 0; i < numberOfInputBlocksof64BitsToEncrypt; i++) { byte[] next8BytesToEncrypt = Encoding.UTF8.GetBytes(plainTextCharArray, inputIndex, 8); byte[] next8EncryptedBytes = Process(subKeys, next8BytesToEncrypt); Array.Copy(next8EncryptedBytes, 0, allEncryptedBytes, inputIndex, 8); inputIndex += 8; } string cipherText = Convert.ToBase64String(allEncryptedBytes); return(cipherText); }
private BigInteger GenerateN(int desiredSize, out BigInteger p, out BigInteger q) { // Calculate half the desired length in bits int half = desiredSize / 2; BigInteger n = 0; int n_length = 0; // Run the loop until the result of pXq is of the desired length and n is a prime do { p = GenerateRandomPrime(half); q = GenerateRandomPrime(half); n = p * q; // Convert n to byte array byte[] n_asByteArray = n.ToByteArray(); // Convert n to Bit Block BitBlock n_asBitBlock = new BitBlock(n_asByteArray); // Get n's length n_length = n_asBitBlock.Length; } while (n_length != desiredSize); // Repease until n is the right lenth return(n); }
private BitBlock F(BitBlock r, BitBlock subKey) { BitBlock expansion_Output = Expansion(r); BitBlock xor_Output = expansion_Output ^ subKey; BitBlock s1 = BitBlock.SubDivide(xor_Output, 0, 5); BitBlock s2 = BitBlock.SubDivide(xor_Output, 6, 11); BitBlock s3 = BitBlock.SubDivide(xor_Output, 12, 17); BitBlock s4 = BitBlock.SubDivide(xor_Output, 18, 23); BitBlock s5 = BitBlock.SubDivide(xor_Output, 24, 29); BitBlock s6 = BitBlock.SubDivide(xor_Output, 30, 35); BitBlock s7 = BitBlock.SubDivide(xor_Output, 36, 41); BitBlock s8 = BitBlock.SubDivide(xor_Output, 42, 47); BitBlock s1_Output = S(s1, 1); BitBlock s2_Output = S(s2, 2); BitBlock s3_Output = S(s3, 3); BitBlock s4_Output = S(s4, 4); BitBlock s5_Output = S(s5, 5); BitBlock s6_Output = S(s6, 6); BitBlock s7_Output = S(s7, 7); BitBlock s8_Output = S(s8, 8); BitBlock sBlocksConcatenated = s1_Output + s2_Output + s3_Output + s4_Output + s5_Output + s6_Output + s7_Output + s8_Output; BitBlock permutation_Output = Permutation(sBlocksConcatenated); return(permutation_Output); }
/// <summary> /// Converts a base10 integer into a base2 binary /// </summary> /// <param name="value"></param> /// <returns></returns> public static BitBlock ConvertDecimalToBinary(int decimalNumber, int bitBlockSizeNeeded) { int remainder; BitBlock output = new BitBlock(bitBlockSizeNeeded); int i = bitBlockSizeNeeded - 1; while (decimalNumber > 0) { remainder = decimalNumber % 2; decimalNumber /= 2; if (remainder == 1) { output[i] = true; } else { output[i] = false; } i--; } return(output); }
public string Decrypt(string cipherText, string key) { key = Helpers.PadMod8(key, '-'); BitBlock masterKey = new BitBlock(key); BitBlock[] subKeys = GenerateSubKeys(ProcessType.Decrypt, masterKey); byte[] encryptedBytes = Convert.FromBase64String(cipherText); StringBuilder plainText = new StringBuilder(); int inputIndex = 0; int numberOfInputBlocksof64BitsToDecrypt = encryptedBytes.Length / 8; for (int i = 0; i < numberOfInputBlocksof64BitsToDecrypt; i++) { byte[] next8BytesToDecrypt = Helpers.SubArray(encryptedBytes, inputIndex, 8); byte[] next8DecryptedBytes = Process(subKeys, next8BytesToDecrypt); string decryptedString = Encoding.UTF8.GetString(next8DecryptedBytes); plainText.Append(decryptedString); inputIndex += 8; } return(plainText.ToString().TrimEnd()); }
private BigInteger GenerateRandomPrime(int desiredSize) { // Create empty blocks for our prime BitBlock potentialPrime_asBitBlock = new BitBlock(desiredSize); BigInteger potentialPrime; do { // Convert potential prime to byte array byte[] potentialPrime_asByteArray = BitBlock.ConvertToByteArray(potentialPrime_asBitBlock); // Fill potential prime with random bits cryptoServiceProvider.GetBytes(potentialPrime_asByteArray); // Convert potential prime to Big Integers potentialPrime = new BigInteger(potentialPrime_asByteArray); // If we created negative potential prime, change to positive if (potentialPrime.Sign == -1) { potentialPrime *= -1; } } while (!isPrime(potentialPrime, securityToken)); return(potentialPrime); }
private byte[] Process(BitBlock[] subKeys, byte[] next8ByteBlock) { BitBlock next64BitBlock = new BitBlock(next8ByteBlock); BitBlock initialPermutation_Output = InitialPermutation(next64BitBlock); BitBlock leftSide = initialPermutation_Output.LeftSide(); BitBlock rightSide = initialPermutation_Output.RightSide(); // 16 Rounds of Encryption/Decryption for (int i = 0; i <= 15; i++) { BitBlock F_Output = F(rightSide, subKeys[i]); BitBlock tempRightSide = leftSide ^ F_Output; leftSide = rightSide; rightSide = tempRightSide; } BitBlock finalPermutation_Output = FinalPermutation(rightSide + leftSide); byte[] byteArray = BitBlock.ConvertToByteArray(finalPermutation_Output); return(byteArray); }
/// <summary> /// Converts a BitBlock into an array of bytes. /// The number of items in the BitBlock must be divisible by 8. /// </summary> /// <param name="input"></param> /// <returns></returns> public static byte[] ConvertToByteArray(BitBlock input) { int size = input.Length; if (size % 8 != 0) { throw new Exception("Input lenght must be divisible and greater by/than 8"); } byte[] byteArray = new byte[size / 8]; int b = 0; BitBlock bb = new BitBlock(8); for (int i = 0; i < size; i++) { bb[i % 8] = input[i]; if ((i + 1) % 8 == 0) { byte _byte = BitBlock.ConvertBinaryToDecimal(bb); byteArray[b++] = _byte; } } return(byteArray); }
private BitBlock S(BitBlock input, int sreferenceTableNumber) { BitBlock outerBits = new BitBlock(2); BitBlock middleBits = new BitBlock(4); outerBits[0] = input[0]; outerBits[1] = input[5]; middleBits[0] = input[1]; middleBits[1] = input[2]; middleBits[2] = input[3]; middleBits[3] = input[4]; int middleNumber = BitBlock.ConvertBinaryToDecimal(middleBits); int outerNumber = BitBlock.ConvertBinaryToDecimal(outerBits); int tableValue = 0; switch (sreferenceTableNumber) { case 1: tableValue = tables.SBox1Table[outerNumber, middleNumber]; break; case 2: tableValue = tables.SBox2Table[outerNumber, middleNumber]; break; case 3: tableValue = tables.SBox3Table[outerNumber, middleNumber]; break; case 4: tableValue = tables.SBox4Table[outerNumber, middleNumber]; break; case 5: tableValue = tables.SBox5Table[outerNumber, middleNumber]; break; case 6: tableValue = tables.SBox6Table[outerNumber, middleNumber]; break; case 7: tableValue = tables.SBox7Table[outerNumber, middleNumber]; break; case 8: tableValue = tables.SBox8Table[outerNumber, middleNumber]; break; } BitBlock bitBlock = BitBlock.ConvertDecimalToBinary(tableValue, 4); return(bitBlock); }
/// <summary> /// Right Shift /// </summary> /// <param name="input"></param> /// <param name="unitsToShift"></param> /// <returns></returns> public static BitBlock operator >>(BitBlock input, int unitsToShift) { int size = input.Length; BitBlock output = new BitBlock(size); for (int i = 0; i < size; i++) { output[(i + unitsToShift) % size] = input[i]; } return(output); }
/// <summary> /// Returns a portion of the input bit block from position index to length /// </summary> /// <param name="input"></param> /// <param name="index"></param> /// <param name="length"></param> /// <returns></returns> public static BitBlock SubDivide(BitBlock input, int index, int length) { BitBlock output = new BitBlock(length - index + 1); int j = 0; for (int i = index; i <= length; i++) { output[j++] = input[i]; } return(output); }
/// <summary> /// Returns the right half of inputBlock /// </summary> /// <param name="inputBlock"></param> /// <returns>A BitArray array consisting of the right side of inputBlock</returns> public BitBlock RightSide() { int halfInputBlockLength = this.bits.Length / 2; BitBlock outputBlock = new BitBlock(halfInputBlockLength); for (int i = 0; i <= halfInputBlockLength - 1; i++) { outputBlock[i] = this.bits[i + halfInputBlockLength]; } return(outputBlock); }
private BitBlock SubDivide(BitBlock input, int start, int finish) { BitBlock output = new BitBlock(finish - start + 1); int j = 0; for (int i = start; i <= finish; i++) { output[j++] = input[i]; } return(output); }
public string Encrypt(string plainText, string masterKey) { string key1 = String.Empty; string key2 = String.Empty; string key3 = String.Empty; Create3keysFromMasterKey(masterKey, out key1, out key2, out key3); string masterKeyPadded1 = PadMasterKey(key1); string masterKeyPadded2 = PadMasterKey(key2); string masterKeyPadded3 = PadMasterKey(key3); BitBlock masterKey1 = new BitBlock(masterKeyPadded1); BitBlock masterKey2 = new BitBlock(masterKeyPadded2); BitBlock masterKey3 = new BitBlock(masterKeyPadded3); BitBlock[] subKeysForEncryption1 = GenerateSubKeys(ProcessType.Encrypt, masterKey1); BitBlock[] subKeysForDecryption2 = GenerateSubKeys(ProcessType.Decrypt, masterKey2); BitBlock[] subKeysForEncryption3 = GenerateSubKeys(ProcessType.Encrypt, masterKey3); string plainTextPadded = PadPlainText(plainText); char[] plainTextCharArray = plainTextPadded.ToCharArray(); byte[] allEncryptedBytes = new byte[plainTextCharArray.Length]; int inputIndex = 0; int numberOfInputBlocksof64BitsToEncrypt = plainTextCharArray.Length / 8; for (int i = 0; i < numberOfInputBlocksof64BitsToEncrypt; i++) { byte[] next8BytesToEncrypt = Encoding.UTF8.GetBytes(plainTextCharArray, inputIndex, 8); byte[] encryptedBytes_Pass1 = Process(subKeysForEncryption1, next8BytesToEncrypt); byte[] decryptedBytes_Pass2 = Process(subKeysForDecryption2, encryptedBytes_Pass1); byte[] encryptedBytes_Pass3 = Process(subKeysForEncryption3, decryptedBytes_Pass2); Array.Copy(encryptedBytes_Pass3, 0, allEncryptedBytes, inputIndex, 8); inputIndex += 8; } string cipherText = Convert.ToBase64String(allEncryptedBytes); return(cipherText); }
/// <summary> /// Converts a base2 binary value into a base10 integer /// </summary> /// <returns></returns> public static byte ConvertBinaryToDecimal(BitBlock input) { int[] bitsAsOnesAndZeros = ConvertToIntegerArrayOfBits(input); double intRepresentation = 0; int exponent = 0; for (int i = (bitsAsOnesAndZeros.Length - 1); i >= 0; i--) { intRepresentation += bitsAsOnesAndZeros[i] * (Math.Pow(2, exponent)); exponent++; } return((byte)intRepresentation); }
public string Decrypt(string cipherText, string masterKey) { string key1 = String.Empty; string key2 = String.Empty; string key3 = String.Empty; Create3keysFromMasterKey(masterKey, out key1, out key2, out key3); string masterKeyPadded1 = PadMasterKey(key1); string masterKeyPadded2 = PadMasterKey(key2); string masterKeyPadded3 = PadMasterKey(key3); BitBlock masterKey1 = new BitBlock(masterKeyPadded1); BitBlock masterKey2 = new BitBlock(masterKeyPadded2); BitBlock masterKey3 = new BitBlock(masterKeyPadded3); BitBlock[] subKeysForDecryption1 = GenerateSubKeys(ProcessType.Decrypt, masterKey1); BitBlock[] subKeysForEncryption2 = GenerateSubKeys(ProcessType.Encrypt, masterKey2); BitBlock[] subKeysForDecryption3 = GenerateSubKeys(ProcessType.Decrypt, masterKey3); byte[] encryptedBytes = Convert.FromBase64String(cipherText); StringBuilder plainText = new StringBuilder(); int inputIndex = 0; int numberOfInputBlocksof64BitsToDecrypt = encryptedBytes.Length / 8; for (int i = 0; i < numberOfInputBlocksof64BitsToDecrypt; i++) { byte[] next8BytesToDecrypt = SubArray(encryptedBytes, inputIndex, 8); byte[] decryptedBytes_Pass1 = Process(subKeysForDecryption1, next8BytesToDecrypt); byte[] encryptedBytes_Pass2 = Process(subKeysForEncryption2, decryptedBytes_Pass1); byte[] decryptedBytes_Pass3 = Process(subKeysForDecryption3, encryptedBytes_Pass2); string decryptedString = Encoding.UTF8.GetString(decryptedBytes_Pass3); plainText.Append(decryptedString); inputIndex += 8; } return(plainText.ToString().TrimEnd()); }
/// <summary> /// Converts the internal array of bools into an array of integers /// </summary> /// <returns></returns> public static int[] ConvertToIntegerArrayOfBits(BitBlock input) { int[] intArray = new int[input.Length]; for (int i = 0; i < input.Length; i++) { if (input[i] == false) { intArray[i] = 0; } else { intArray[i] = 1; } } return(intArray); }
/// <summary> /// XOR /// </summary> /// <param name="leftSide"></param> /// <param name="rightSide"></param> /// <returns></returns> public static BitBlock operator ^(BitBlock leftSide, BitBlock rightSide) { if (leftSide.Length != rightSide.Length) { throw new Exception("Bit Block lenghts need to match"); } int size = leftSide.Length; BitBlock outputBlock = new BitBlock(size); for (int i = 0; i < size; i++) { outputBlock[i] = leftSide[i] ^ rightSide[i]; } return(outputBlock); }
/// <summary> /// Uses reference tables to copy values from the input block to the output block /// </summary> /// <param name="referenceTable">Rerefence Table</param> /// <param name="inputBlock">Input Block</param> /// <param name="outputBlockSize">Output Block Size</param> /// <returns></returns> private static BitBlock BlockTransmutation(int[,] referenceTable, BitBlock inputBlock, int outputBlockSize) { int i = 0; BitBlock outputBlock = new BitBlock(outputBlockSize); for (int row = 0; row < referenceTable.GetLength(0); row++) { for (int col = 0; col < referenceTable.GetLength(1); col++) { int val = referenceTable[row, col]; outputBlock[i++] = inputBlock[--val]; } } return(outputBlock); }
/// <summary> /// Concatenates two BitBlocks into one /// </summary> /// <param name="leftSide"></param> /// <param name="rightSide"></param> /// <returns></returns> public static BitBlock operator +(BitBlock leftSide, BitBlock rightSide) { int size = leftSide.Length + rightSide.Length; int half = size / 2; BitBlock output = new BitBlock(size); for (int i = 0; i < leftSide.Length; i++) { output[i] = leftSide[i]; } for (int i = 0; i < rightSide.Length; i++) { output[i + leftSide.Length] = rightSide[i]; } return(output); }
private BigInteger GenerateP(int desiredSize) { // Create 2 empty blocks for p and q BitBlock p_asBitBlock = new BitBlock(desiredSize); BigInteger p = 0; bool isPPrime = false; do { // Convert p to byte array byte[] p_asByteArray = BitBlock.ConvertToByteArray(p_asBitBlock); // Fill p with random bits cryptoServiceProvider.GetBytes(p_asByteArray); // Convert p to Big Integer p = new BigInteger(p_asByteArray); // If we created negative p/q, change to positive if (p.Sign == -1) { p *= -1; } // Primality Test switch (this.primalityTestToUse) { case PrimalityTest.Fermat: isPPrime = Helpers.FermatPrimalityTest(p, this.securityToken); break; case PrimalityTest.RabinMiller: isPPrime = Helpers.MillerRabinPrimalityTest(p, this.securityToken); break; } } while (!isPPrime); return(p); }
/// <summary> /// Convert the incoming byte array into a BitBlock /// </summary> /// <param name="bytes"></param> public BitBlock(byte[] bytes) { // Create internal structure this.bits = new bool[bytes.Length * 8]; // Loop through the bytes to convert for (int i = 0; i < bytes.Length; i++) { // Grab each byte byte b = bytes[i]; // Convert it into a BitBlock BitBlock bb = ConvertDecimalToBinary(b, 8); // Concatenate all the bits for (int j = 0; j < bb.Length; j++) { this.bits[j + (i * 8)] = bb[j]; } } }
public static BigInteger SquareAndMultiply(BigInteger a, BigInteger exponent, BigInteger modulus) { BigInteger b = 1; if (exponent == 0) { return(b); // a^0 would be 1 } BigInteger A = a; byte[] exponentAsBytes = exponent.ToByteArray(); Array.Reverse(exponentAsBytes); // Reverse little endian BitBlock temp = new BitBlock(exponentAsBytes); BitBlock kbits = new BitBlock(temp.ToString().TrimStart('0').ToCharArray()); // Trim leading 0s kbits.Reverse(); // Reverse the bits so that k[0] will return the right most element if (kbits[0] == true) // Odd? { b = a; } for (int i = 1; i < kbits.Length; i++) { A = BigInteger.Pow(A, 2) % modulus; if (kbits[i] == true) { b = (A * b) % modulus; } } return(b); }
private BitBlock Expansion(BitBlock r0) { return(BlockTransmutation(tables.ExpansionTable, r0, 48)); }
private BitBlock InitialPermutation(BitBlock next64BitBlock) { return(BlockTransmutation(tables.InitialPermutationTable, next64BitBlock, 64)); }
private BitBlock Permutation(BitBlock input) { return(BlockTransmutation(tables.PermutationTable, input, 32)); }
private BitBlock[] GenerateSubKeys(ProcessType process, BitBlock masterKey) { BitBlock PC1_Output = PC1(masterKey); BitBlock cBlock = PC1_Output.LeftSide(); BitBlock dBlock = PC1_Output.RightSide(); BitBlock[] subKeys = new BitBlock[16]; switch (process) { case ProcessType.Encrypt: #region Encrypt for (int round = 1; round <= 16; round++) { if (round == 1 || round == 2 || round == 9 || round == 16) { cBlock = cBlock << 1; dBlock = dBlock << 1; } else { cBlock = cBlock << 2; dBlock = dBlock << 2; } BitBlock key = PC2(cBlock + dBlock); subKeys[round - 1] = key; } break; #endregion case ProcessType.Decrypt: #region Decrypt for (int round = 1; round <= 16; round++) { if (round == 1) { // No Rotation } else if (round == 2 || round == 9 || round == 16) { cBlock = cBlock >> 1; dBlock = dBlock >> 1; } else { cBlock = cBlock >> 2; dBlock = dBlock >> 2; } BitBlock key = PC2(cBlock + dBlock); subKeys[round - 1] = key; } break; #endregion } return(subKeys); }
private BitBlock PC1(BitBlock masterKey) { return(BlockTransmutation(tables.PC1Table, masterKey, 56)); }
private BitBlock FinalPermutation(BitBlock input) { return(BlockTransmutation(tables.FinalPermutationTable, input, 64)); }
private BitBlock PC2(BitBlock CnDn) { return(BlockTransmutation(tables.PC2Table, CnDn, 48)); }