protected void RunSegmentedVectorTest(int number, SegmentedVectorTestCase testCase)
        {
            CipherConfiguration config = GetCipherConfiguration(testCase);
            var plaintext = new byte[testCase.IV.Length];
            TestVectorSegment lastSegment = testCase.Segments.Last();
            int requiredCiphertextLength  = lastSegment.Offset + lastSegment.Length;
            var msCiphertext = new MemoryStream();

            using (var cs = new CipherStream(msCiphertext, true, config, testCase.Key, false)) {
                while (cs.BytesOut < requiredCiphertextLength)
                {
                    cs.Write(plaintext, 0, plaintext.Length);
                }
            }

            // Now we analyse the ciphertext segment-wise
            foreach (var segment in testCase.Segments)
            {
                msCiphertext.Seek(segment.Offset, SeekOrigin.Begin);
                var segmentCiphertext = new byte[segment.Length];
                msCiphertext.Read(segmentCiphertext, 0, segment.Length);
                byte[] referenceCiphertext = segment.Ciphertext;
                // Validate the segment
                Assert.IsTrue(referenceCiphertext.SequenceEqualShortCircuiting(segmentCiphertext),
                              "Segmented vector test #{0} (\"{1}\") failed at segment {2}!",
                              number, testCase.Name, segment.Name);
            }
        }
Exemple #2
0
        /// <summary>
        ///     Create a configuration for a stream cipher.
        /// </summary>
        /// <param name="cipher">Stream cipher to use.</param>
        /// <param name="keySize">Key size to use, in bits.</param>
        /// <returns>Stream cipher configuration DTO.</returns>
        public static CipherConfiguration CreateStreamCipherConfiguration(StreamCipher cipher, int?keySize = null)
        {
            var config = new CipherConfiguration {
                Type = CipherType.Stream
            };

            int keySizeNonNull = keySize ?? Athena.Cryptography.StreamCiphers[cipher].DefaultKeySizeBits;

            if (keySize == null || Athena.Cryptography.StreamCiphers[cipher].AllowableKeySizesBits.Contains(keySizeNonNull))
            {
                config.KeySizeBits = keySizeNonNull;
            }
            else
            {
                throw new CipherKeySizeException(cipher, keySizeNonNull);
            }
            config.CipherName = cipher.ToString();

            if (Athena.Cryptography.StreamCiphers[cipher].DefaultNonceSizeBits != -1)
            {
                config.InitialisationVector = new byte[Athena.Cryptography.StreamCiphers[cipher].DefaultNonceSizeBits / 8];
                StratCom.EntropySupplier.NextBytes(config.InitialisationVector);
            }

            return(config);
        }
Exemple #3
0
        /// <summary>
        ///     Initialises a stream cipher from cipher configuration DTO. Used by constructor.
        /// </summary>
        private static ICipherWrapper InitStreamCipher(bool encrypting, CipherConfiguration config, byte[] key, out int maxDelta)
        {
            var streamConfigWrapper = new StreamCipherConfigurationWrapper(config);

            if (key.Length != streamConfigWrapper.KeySizeBytes)
            {
                throw new ArgumentException("Key is not of the length declared in the cipher configuration.",
                                            "key");
            }

            StreamCipherEngine streamCipher;

            try {
                streamCipher = CipherFactory.CreateStreamCipher(streamConfigWrapper.GetStreamCipher());
                streamCipher.Init(encrypting, key, streamConfigWrapper.GetNonce());
            } catch (Exception e) {
                throw new ConfigurationInvalidException("Configuration of stream cipher is invalid.",
                                                        e.InnerException);
            }

            // This should always be 0, but we'll do it anyway...
            maxDelta = Athena.Cryptography.StreamCiphers[streamCipher.Identity].MaximumOutputSizeDifference(encrypting);

            return(new StreamCipherWrapper(encrypting, streamCipher, strideIncreaseFactor: 2));
        }
Exemple #4
0
        /// <summary>
        ///     Initialises a block cipher from cipher configuration DTO. Used by constructor.
        /// </summary>
        private static ICipherWrapper InitBlockCipher(bool encrypting, CipherConfiguration config, byte[] key, out int maxDelta)
        {
            var blockConfigWrapper = new BlockCipherConfigurationWrapper(config);

            if (key.Length != blockConfigWrapper.KeySizeBytes)
            {
                throw new ArgumentException("Key is not of the length declared in the cipher configuration.",
                                            "key");
            }

            BlockCipherBase blockCipherPrimitive = CipherFactory.CreateBlockCipher(blockConfigWrapper.GetBlockCipher(),
                                                                                   blockConfigWrapper.GetBlockSizeBits());
            // Overlay the cipher with the mode of operation
            BlockCipherModeBase blockCipher;

            try {
                blockCipher = CipherFactory.OverlayBlockCipherWithMode(blockCipherPrimitive, blockConfigWrapper.Mode);
            } catch (Exception e) {
                throw new ConfigurationInvalidException(
                          "Configuration of block cipher mode of operation is invalid.", e.InnerException);
            }
            IBlockCipherPadding padding     = null;
            BlockCipherPadding  paddingEnum = blockConfigWrapper.GetPadding();

            if (paddingEnum != BlockCipherPadding.None)
            {
                padding = CipherFactory.CreatePadding(paddingEnum);
                padding.Init(StratCom.EntropySupplier);
            }

            maxDelta = Athena.Cryptography.BlockCiphers[blockCipherPrimitive.Identity].MaximumOutputSizeDifference(encrypting);

            blockCipher.Init(encrypting, key, blockConfigWrapper.GetInitialisationVector());
            return(new BlockCipherWrapper(encrypting, blockCipher, padding));
        }
        // Performance testing resources (not called in this base class, but called from derived classes)

        protected void RunPerformanceTest(CipherConfiguration config, byte[] overrideKey = null)
        {
            MemoryStream msInputPlaintext = LargeBinaryFile;

            byte[] key = overrideKey ?? CreateRandomByteArray(config.KeySizeBits);

            var msCiphertext = new MemoryStream((int)(msInputPlaintext.Length * 1.1));
            var sw           = new Stopwatch();

            // TEST STARTS HERE

            using (var cs = new CipherStream(msCiphertext, true, config, key, false)) {
                sw.Start();
                msInputPlaintext.CopyTo(cs, GetBufferSize());
            }
            sw.Stop();
            TimeSpan encryptionElapsed = sw.Elapsed;

            var msOutputPlaintext = new MemoryStream((int)msInputPlaintext.Length);

            msCiphertext.Seek(0, SeekOrigin.Begin);

            sw.Reset();
            using (var cs = new CipherStream(msCiphertext, false, config, key, false)) {
                sw.Start();
                cs.CopyTo(msOutputPlaintext, GetBufferSize());
            }
            sw.Stop();
            TimeSpan decryptionElapsed = sw.Elapsed;

            // TEST ENDS HERE

            // TEST OUTPUT PLAINTEXT VALIDITY

            msInputPlaintext.Seek(0, SeekOrigin.Begin);
            msOutputPlaintext.Seek(0, SeekOrigin.Begin);
            int failurePosition;

            Assert.IsTrue(StreamsContentMatches(msInputPlaintext, msOutputPlaintext, (int)msInputPlaintext.Length, out failurePosition),
                          "Input and output plaintext does not match. First failure observed at position # " + failurePosition);

            // OUTPUT SUCCESS STATISTICS

            double encSpeed = ((double)msInputPlaintext.Length / 1048576) / encryptionElapsed.TotalSeconds,
                   decSpeed =
                ((double)msInputPlaintext.Length / 1048576) / decryptionElapsed.TotalSeconds;

            Assert.Pass("{0:N0} ms ({1:N2} MB/s) : {2:N0} ms ({3:N2} MB/s)",
                        encryptionElapsed.TotalMilliseconds, encSpeed, decryptionElapsed.TotalMilliseconds, decSpeed);
        }
Exemple #6
0
        /// <summary>
        /// Create a configuration for a block cipher.
        /// </summary>
        /// <param name="cipher">Block cipher to use.</param>
        /// <param name="mode">Mode of operation for the cipher.</param>
        /// <param name="padding">Padding scheme to use with the mode, where necessary (e.g. CBC).</param>
        /// <param name="keySize">Key size to use, in bits.</param>
        /// <param name="blockSize">Cipher block size to use, in bits.</param>
        /// <returns>Block cipher configuration DTO.</returns>
        public static CipherConfiguration CreateBlockCipherConfiguration(BlockCipher cipher,
                                                                         BlockCipherMode mode, BlockCipherPadding padding, int?keySize = null, int?blockSize = null)
        {
            var config = new CipherConfiguration {
                Type = CipherType.Block
            };

            // Set the key size
            int keySizeNonNull = keySize ?? Athena.Cryptography.BlockCiphers[cipher].DefaultKeySizeBits;

            if (keySize == null || Athena.Cryptography.BlockCiphers[cipher].AllowableKeySizesBits.Contains(keySizeNonNull))
            {
                config.KeySizeBits = keySizeNonNull;
            }
            else
            {
                throw new CipherKeySizeException(cipher, keySizeNonNull);
            }

            // Set the block size
            int blockSizeNonNull = blockSize ?? Athena.Cryptography.BlockCiphers[cipher].DefaultBlockSizeBits;

            if (blockSize == null ||
                Athena.Cryptography.BlockCiphers[cipher].AllowableBlockSizesBits.Contains(blockSizeNonNull))
            {
                config.BlockSizeBits = blockSizeNonNull;
            }
            else
            {
                throw new BlockSizeException(cipher, blockSizeNonNull);
            }

            // Set the mode
            if (Athena.Cryptography.BlockCipherModes[mode].PaddingRequirement == PaddingRequirement.Always &&
                padding == BlockCipherPadding.None)
            {
                throw new ArgumentException(mode +
                                            " mode must be used with padding or errors will occur when plaintext length is not equal to or a multiple of the block size.");
            }

            config.ModeName    = mode.ToString();
            config.PaddingName = padding.ToString();
            config.CipherName  = cipher.ToString();

            config.InitialisationVector = new byte[config.BlockSizeBits.Value / 8];
            StratCom.EntropySupplier.NextBytes(config.InitialisationVector);

            return(config);
        }
Exemple #7
0
 public BlockCipherConfigurationWrapper(CipherConfiguration config) : base(config)
 {
     if (config == null)
     {
         throw new ArgumentNullException("config");
     }
     if (config.Type == CipherType.None)
     {
         throw new ConfigurationInvalidException("Cipher configuration specifies Type = None.");
     }
     if (config.Type != CipherType.Block)
     {
         throw new ArgumentException("Configuration is not for a block cipher.");
     }
 }
        protected void RunDiscreteVectorTest(int number, DiscreteVectorTestCase testCase)
        {
            CipherConfiguration config = GetCipherConfiguration(testCase);

            byte[] plaintext = testCase.Plaintext;

            byte[] ciphertext;
            using (var msCiphertext = new MemoryStream()) {
                using (var cs = new CipherStream(msCiphertext, true, config, testCase.Key, false)) {
                    cs.Write(plaintext, 0, plaintext.Length);
                }
                ciphertext = msCiphertext.ToArray();
            }

            Assert.IsTrue(testCase.Ciphertext.SequenceEqualShortCircuiting(ciphertext),
                          "Test #{0} (\"{1}\") failed!", number, testCase.Name);
        }
        public void StreamCipherConfiguration()
        {
            var inputObj = new CipherConfiguration()
            {
                Type                 = CipherType.Stream,
                CipherName           = StreamCipher.Salsa20.ToString(),
                KeySizeBits          = 256,
                InitialisationVector = new byte[] { 0x01, 0x02, 0x03 }
            };

            var stream = SerialiseToMemory(inputObj);

            stream.Seek(0, SeekOrigin.Begin);
            var outputObj = DeserialiseFromMemory <CipherConfiguration>(stream);

            Assert.IsTrue(inputObj.Equals(outputObj));
        }
Exemple #10
0
        private byte[] _opOutBuffer;   // freshly-encrypted or decrypted data


        /// <summary>
        ///     Initialises the stream and its associated cipher for operation automatically from provided configuration
        ///     object.
        /// </summary>
        /// <param name="binding">Stream to be written/read to/from.</param>
        /// <param name="encrypting">Specifies whether the stream is for writing (encrypting) or reading (decryption).</param>
        /// <param name="config">Configuration object describing how to set up the internal cipher and associated services.</param>
        /// <param name="key">Derived cryptographic key for the internal cipher to operate with.</param>
        /// <param name="closeOnDispose">Set to <c>true</c> to also close the base stream when closing, or vice-versa.</param>
        public CipherStream(System.IO.Stream binding, bool encrypting, CipherConfiguration config, byte[] key,
                            bool closeOnDispose)
        {
#if INCLUDE_CONTRACTS
            Contract.Requires(binding != null);
            Contract.Requires(config != null);
            Contract.Requires(key != null);
#endif

            if (key.IsNullOrZeroLength())
            {
                throw new ArgumentException("No key provided.", "key");
            }

            Writing         = encrypting;
            _streamBinding  = binding;
            _closeOnDispose = closeOnDispose;

            switch (config.Type)
            {
            case CipherType.None:
                throw new ConfigurationInvalidException(
                          "Cipher type is never set to None in a valid cipher configuration.");

            case CipherType.Block:
                _cipher = InitBlockCipher(encrypting, config, key, out _maxCipherOutputDelta);
                break;

            case CipherType.Stream:
                _cipher = InitStreamCipher(encrypting, config, key, out _maxCipherOutputDelta);
                break;

            default:
                throw new ArgumentException("Not a valid cipher configuration.");
            }

            _opSize = _cipher.OperationSize;
            // Initialise the buffers
            _opInBuffer  = new byte[_opSize];
            _opOutBuffer = new byte[(_opSize + _maxCipherOutputDelta) * 2];
            _inBuffer    = new ConcurrentRingBuffer(16384);
            _outBuffer   = new ConcurrentRingBuffer(16384);

            // LSH 8 upscales (256x) : 8 (64 bits) to 2048 [2kB], 16 (128) to 4096 [4kB], 32 (256) to 8192 [8kB]
        }
        public void BlockCipherConfiguration()
        {
            var inputObj = new CipherConfiguration()
            {
                Type                 = CipherType.Block,
                CipherName           = BlockCipher.Aes.ToString(),
                KeySizeBits          = 128,
                InitialisationVector = new byte[] { 0x01, 0x02, 0x03 },
                ModeName             = BlockCipherMode.Ctr.ToString(),
                BlockSizeBits        = 128,
                PaddingName          = BlockCipherPadding.None.ToString()
            };

            var stream = SerialiseToMemory(inputObj);

            stream.Seek(0, SeekOrigin.Begin);
            var outputObj = DeserialiseFromMemory <CipherConfiguration>(stream);

            Assert.IsTrue(inputObj.Equals(outputObj));
        }
Exemple #12
0
 public AESCipher(CipherConfiguration configuration)
 {
     aes.Mode      = configuration.CipherMode;
     aes.KeySize   = configuration.KeySize;
     aes.BlockSize = configuration.BlockSize;
 }
 protected CipherConfigurationWrapper(CipherConfiguration config)
 {
     Configuration = config;
 }