예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        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());
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        /// <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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        /// <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);
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }
예제 #15
0
        /// <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);
        }
예제 #16
0
        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());
        }
예제 #17
0
        /// <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);
        }
예제 #18
0
        /// <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);
        }
예제 #19
0
        /// <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);
        }
예제 #20
0
        /// <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);
        }
예제 #21
0
        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);
        }
예제 #22
0
        /// <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];
                }
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
 private BitBlock Expansion(BitBlock r0)
 {
     return(BlockTransmutation(tables.ExpansionTable, r0, 48));
 }
예제 #25
0
 private BitBlock InitialPermutation(BitBlock next64BitBlock)
 {
     return(BlockTransmutation(tables.InitialPermutationTable, next64BitBlock, 64));
 }
예제 #26
0
 private BitBlock Permutation(BitBlock input)
 {
     return(BlockTransmutation(tables.PermutationTable, input, 32));
 }
예제 #27
0
        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);
        }
예제 #28
0
 private BitBlock PC1(BitBlock masterKey)
 {
     return(BlockTransmutation(tables.PC1Table, masterKey, 56));
 }
예제 #29
0
 private BitBlock FinalPermutation(BitBlock input)
 {
     return(BlockTransmutation(tables.FinalPermutationTable, input, 64));
 }
예제 #30
0
 private BitBlock PC2(BitBlock CnDn)
 {
     return(BlockTransmutation(tables.PC2Table, CnDn, 48));
 }