Example #1
0
        public static void BC()
        {
            Random r = new Random();

            byte[] input = new byte[1 << 4];
            byte[] key   = new byte[1 << 4];
            r.NextBytes(input);
            r.NextBytes(key);

            Console.WriteLine("Input:");
            print(input);
            Console.WriteLine("Key:");
            print(key);

            blockCipher Block = new blockCipher(input, key);

            Console.WriteLine("EN:");
            print(Block.encrypt());

            blockCipher Block2 = new blockCipher(Block.encrypt(), key);

            Console.WriteLine("DC:");
            print(Block2.decrypt());
        }
Example #2
0
        /// <summary>
        /// Encrypt a given source file and save it to a given target file.
        /// </summary>
        /// <param name="sourceFileName">The filename of the source file. Presumed to exist.</param>
        /// <param name="destinationFileName">The filename of the target file. Will be overwritten.</param>
        /// <param name="key">The key to encrypt with</param>
        /// <param name="mode">The mode of encryption. Use Engine.* constants.</param>
        /// <param name="blockSize">The chosen block size.</param>
        public static void StartEncryption(String sourceFileName, String destinationFileName, String key, byte mode, int blockSize = 16)
        {
            if (mode != ECB && mode != CBC && mode != CFB && mode != OFB)
            {
                throw new Exception("Invalid block cipher mode of operation.");
            }

            // Auxiliary variables
            byte[] crlf = { Convert.ToByte('\r'), Convert.ToByte('\n') };

            // Key processing
            char[] keyChars  = key.ToCharArray();
            int    keyLength = Math.Max(key.Length, blockCipherEnDc.SIZE);

            byte[] keyBytes = new byte[keyLength];
            for (var i = 0; i < keyLength; ++i)
            {
                if (i < key.Length)
                {
                    keyBytes[i] = Convert.ToByte(keyChars[i]);
                }
                else
                {
                    keyBytes[i] = 0;
                }
            }

            // Open read handle. Treat all files as binary.
            FileStream   fr = File.OpenRead(sourceFileName);
            BinaryReader br = new BinaryReader(fr);

            // Open write handle.
            FileStream   fw = File.OpenWrite(destinationFileName);
            BinaryWriter bw = new BinaryWriter(fw);

            // Start by writing the header

            // The header consists of the following bytes:
            // 1-8 Original file length
            // 9-12 Block Size
            // 13 Block cipher mode of operation
            // 14-15 CRLF
            // 16-.. Initialization vector (according to blocksize)
            // ..-.. CRLF

            Int64 originalLength = Convert.ToInt64(fr.Length);

            Console.WriteLine(originalLength.ToString("X8"));
            bw.Write(originalLength);

            Int32 blockSizeField = Convert.ToInt32(blockSize);

            bw.Write(blockSizeField);

            bw.Write(mode);
            bw.Write(crlf);

            Random iv = new Random();

            byte[] initializationVector = new byte[blockSize];
            iv.NextBytes(initializationVector);
            bw.Write(initializationVector);

            bw.Write(crlf);

            // Header is written.
            // Write body
            long pos    = 0;
            long length = fr.Length;

            byte[]      readBuffer;
            byte[]      paddedBuffer;
            blockCipher Cipher;

            byte[] previousBlock = (byte[])initializationVector.Clone();

            while (pos < length)
            {
                // Load one block into buffer
                readBuffer   = br.ReadBytes(blockSize);
                paddedBuffer = PadByteArray(readBuffer, blockSize);
                byte[] cipherBuffer;
                byte[] pre;

                switch (mode)
                {
                case ECB:
                    Cipher = new blockCipher(paddedBuffer, keyBytes);
                    bw.Write(Cipher.encrypt());
                    break;

                case CBC:
                    pre          = XorByteArray(paddedBuffer, previousBlock);
                    Cipher       = new blockCipher(pre, keyBytes);
                    cipherBuffer = Cipher.encrypt();
                    bw.Write(cipherBuffer);
                    Array.Copy(cipherBuffer, previousBlock, blockSize);
                    break;

                case CFB:
                    Cipher       = new blockCipher(previousBlock, keyBytes);
                    pre          = Cipher.encrypt();
                    cipherBuffer = XorByteArray(pre, paddedBuffer);
                    bw.Write(cipherBuffer);
                    Array.Copy(cipherBuffer, previousBlock, blockSize);
                    break;

                case OFB:
                    Cipher       = new blockCipher(previousBlock, keyBytes);
                    pre          = Cipher.encrypt();
                    cipherBuffer = XorByteArray(paddedBuffer, pre);
                    bw.Write(cipherBuffer);
                    Array.Copy(pre, previousBlock, blockSize);
                    break;

                default:
                    break;
                }
                pos += blockSize;
            }

            // Body is written.

            // Close write handle
            bw.Close();
            fw.Close();

            // Close read handle
            br.Close();
            fr.Close();
        }
Example #3
0
        /// <summary>
        /// Decrypt a given source file and save it to a given target file.
        /// </summary>
        /// <param name="sourceFileName">The filename of the source file. Presumed to exist.</param>
        /// <param name="destinationFileName">The filename of the target file. Will be overwritten.</param>
        /// <param name="key">The key to decrypt with.</param>
        public static void StartDecryption(String sourceFileName, String destinationFileName, String key)
        {
            // Auxiliary variables
            int   readPos          = 0;  // Reading position
            Int64 originalFileSize = 0;  // Original file size
            Int64 remainingBody    = 0;  // Bytes left to read
            Int32 blockSize        = 0;
            byte  cipherMode       = 0;
            byte  cr = Convert.ToByte('\r');
            byte  lf = Convert.ToByte('\n');

            byte[] initializationVector;

            char[] keyChars  = key.ToCharArray();
            int    keyLength = Math.Max(key.Length, blockCipherEnDc.SIZE);

            byte[] keyBytes = new byte[keyLength];

            for (var i = 0; i < keyLength; ++i)
            {
                if (i < key.Length)
                {
                    keyBytes[i] = Convert.ToByte(keyChars[i]);
                }
                else
                {
                    keyBytes[i] = 0;
                }
            }

            // Open read handle. Treat all files as binary.
            FileStream   fr = File.OpenRead(sourceFileName);
            BinaryReader br = new BinaryReader(fr);

            // Open write handle.
            FileStream   fw = File.OpenWrite(destinationFileName);
            BinaryWriter bw = new BinaryWriter(fw);

            // Read header

            // 1. Original filesize
            originalFileSize = br.ReadInt64();
            readPos         += sizeof(Int64);

            // 2. Block size
            blockSize = br.ReadInt32();
            readPos  += sizeof(Int32);

            // 3. Cipher mode
            cipherMode = br.ReadByte();
            readPos   += sizeof(byte);

            // 4. CRLF -- validate their existence
            if (br.ReadByte() != cr)
            {
                throw new Exception("Invalid ciphertext header.");
            }
            readPos += sizeof(byte);

            if (br.ReadByte() != lf)
            {
                throw new Exception("Invalid ciphertext header.");
            }
            readPos += sizeof(byte);

            // 5. Initialization vector
            initializationVector = br.ReadBytes(blockSize);
            readPos += blockSize;

            // 6. CRLF again -- validate their existence
            if (br.ReadByte() != cr)
            {
                throw new Exception("Invalid ciphertext header.");
            }
            readPos += sizeof(byte);

            if (br.ReadByte() != lf)
            {
                throw new Exception("Invalid ciphertext header.");
            }
            readPos += sizeof(byte);

            // We're done with the header, we can now proceed to the body.

            remainingBody = originalFileSize;
            byte[] previousBlock = initializationVector;

            while (readPos < fr.Length)
            {
                byte[]      cipherBuffer = br.ReadBytes(blockSize);
                byte[]      toWrite      = new byte[blockSize];
                byte[]      plainBuffer;
                byte[]      preXor;
                blockCipher Cipher;

                // Decrypt the buffer and write to destination file
                switch (cipherMode)
                {
                case ECB:
                    Cipher      = new blockCipher(cipherBuffer, keyBytes);
                    plainBuffer = Cipher.decrypt();
                    toWrite     = plainBuffer;
                    break;

                case CBC:
                    Cipher        = new blockCipher(cipherBuffer, keyBytes);
                    preXor        = Cipher.decrypt();
                    plainBuffer   = XorByteArray(preXor, previousBlock);
                    toWrite       = plainBuffer;
                    previousBlock = cipherBuffer;
                    break;

                case CFB:
                    Cipher        = new blockCipher(previousBlock, keyBytes);
                    preXor        = Cipher.encrypt();
                    plainBuffer   = XorByteArray(preXor, cipherBuffer);
                    toWrite       = plainBuffer;
                    previousBlock = cipherBuffer;
                    break;

                case OFB:
                    Cipher        = new blockCipher(previousBlock, keyBytes);
                    preXor        = Cipher.encrypt();
                    plainBuffer   = XorByteArray(preXor, cipherBuffer);
                    toWrite       = plainBuffer;
                    previousBlock = preXor;
                    break;

                default:
                    break;
                }

                if (remainingBody < blockSize)
                {
                    byte[] writeBuffer = new byte[remainingBody];
                    Array.Copy(toWrite, writeBuffer, (int)remainingBody);

                    bw.Write(writeBuffer);
                }
                else
                {
                    bw.Write(toWrite);
                }

                readPos       += blockSize;
                remainingBody -= blockSize;
            }

            // Mode is read from the header of the file

            // Close write handle
            bw.Close();
            fw.Close();

            // Close read handle
            br.Close();
            fr.Close();
        }