Beispiel #1
0
        /// <summary>
        /// Add a new file id, and key/iv pair to the VolumeKey
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Key">The key</param>
        /// <param name="Iv">The vector</param>
        ///
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        public static void Add(Stream KeyStream, byte[] Key, byte[] Iv)
        {
            using (MemoryStream keyMem = new MemoryStream())
            {
                // get the header
                VolumeKey vkey   = new VolumeKey(KeyStream);
                int       offset = ID_SEEK + (vkey.Count * ID_SIZE);
                KeyStream.Seek(offset, SeekOrigin.Begin);
                int kmlen = vkey.Count * (vkey.Description.KeySize + vkey.Description.IvSize);

                // adjust the header params
                vkey.Count++;
                ArrayUtils.AddAt(ref vkey.FileId, vkey.FileId[vkey.FileId.Length - 1]++, vkey.Count);
                ArrayUtils.AddAt(ref vkey.State, (byte)0, vkey.Count);
                // copy header to mem
                vkey.ToStream().WriteTo(keyMem);

                byte[] data = new byte[kmlen];
                // copy existing key/iv pairs
                KeyStream.Read(data, 0, data.Length);
                keyMem.Write(data, 0, data.Length);
                // write new
                keyMem.Write(Key, 0, Key.Length);
                keyMem.Write(Iv, 0, Iv.Length);

                // overwrite stream w/ new
                KeyStream.Seek(0, SeekOrigin.Begin);
                keyMem.WriteTo(KeyStream);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Remove a file id, and key/iv pair from the VolumeKey
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        ///
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        ///
        /// <exception cref="CryptoProcessingException">Thrown if the Id does not exist</exception>
        public static void Remove(Stream KeyStream, int Id)
        {
            int index = GetIndex(KeyStream, Id);

            if (index == -1)
            {
                throw new CryptoProcessingException("VolumeKey:Remove", "The id does not exist!", new ArgumentException());
            }

            using (MemoryStream keyMem = new MemoryStream())
            {
                // get the header
                VolumeKey vkey   = new VolumeKey(KeyStream);
                int       offset = ID_SEEK + (vkey.Count * (ID_SIZE + STATE_SIZE));
                KeyStream.Seek(offset, SeekOrigin.Begin);

                // adjust the count
                vkey.Count--;
                // create reduced arrays
                ArrayUtils.RemoveAt(ref vkey.FileId, index);
                ArrayUtils.RemoveAt(ref vkey.State, index);

                // get the key material
                int    klen = vkey.Description.KeySize + vkey.Description.IvSize;
                int    koff = klen * index;
                byte[] data = new byte[klen * vkey.Count];
                KeyStream.Read(data, 0, data.Length);
                ArrayUtils.RemoveRange(ref data, koff, koff + klen);
                keyMem.Write(data, 0, data.Length);

                // overwrite stream w/ new key
                KeyStream.Seek(0, SeekOrigin.Begin);
                keyMem.WriteTo(KeyStream);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Compare this object instance with another
        /// </summary>
        ///
        /// <param name="Obj">Object to compare</param>
        ///
        /// <returns>True if equal, otherwise false</returns>
        public override bool Equals(Object Obj)
        {
            if (!(Obj is VolumeKey))
            {
                return(false);
            }

            VolumeKey other = (VolumeKey)Obj;

            if (!Compare.IsEqual(Tag, other.Tag))
            {
                return(false);
            }
            if (Description.GetHashCode() != other.Description.GetHashCode())
            {
                return(false);
            }
            if (Count != other.Count)
            {
                return(false);
            }
            if (!Compare.IsEqual(FileId, other.FileId))
            {
                return(false);
            }
            if (!Compare.IsEqual(State, other.State))
            {
                return(false);
            }

            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Get the key/iv at a given index
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Index">The index value</param>
        ///
        /// <returns>A populated KeyParams class</returns>
        public static KeyParams AtIndex(Stream KeyStream, int Index)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            byte[] key    = new byte[vkey.Description.KeySize];
            byte[] iv     = new byte[vkey.Description.IvSize];
            int    offset = ID_SEEK + (vkey.Count * (ID_SIZE + STATE_SIZE) + (Index * (vkey.Description.IvSize + vkey.Description.KeySize)));

            KeyStream.Seek(offset, SeekOrigin.Begin);
            KeyStream.Read(key, 0, key.Length);
            KeyStream.Read(iv, 0, iv.Length);

            return(new KeyParams(key, iv));
        }
Beispiel #5
0
        /// <summary>
        /// Test if the VolumeKey contains a file id
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        ///
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        public static bool Contains(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Get the key/iv associated with a file id
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        ///
        /// <returns>A populated KeyParams class, or null if the key is not found</returns>
        public static KeyParams FromId(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                {
                    return(AtIndex(KeyStream, i));
                }
            }

            return(null);
        }
Beispiel #7
0
        /// <summary>
        /// Get the index of the next unused key/iv in the volume key
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        ///
        /// <returns>The index of the next available key pair</returns>
        public static int NextSubKey(Stream KeyStream)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int index = -1;

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.State[i] == (byte)VolumeKeyStates.Unassigned)
                {
                    return(i);
                }
            }

            return(index);
        }
Beispiel #8
0
        /// <summary>
        /// Get the index of the file id in the VolumeKey
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        ///
        /// <returns>Returns the index, or <c>-1</c> if not found</returns>
        public static int GetIndex(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int index = -1;

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                {
                    return(i);
                }
            }

            return(index);
        }
Beispiel #9
0
        /// <summary>
        /// Returns the number of keys in the volume with the specified state value
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="KeyState">The state to search</param>
        ///
        /// <returns>The number of keys with that state</returns>
        public static int KeyCount(Stream KeyStream, VolumeKeyStates KeyState = VolumeKeyStates.Unassigned)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int count = 0;

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.State[i] == (byte)KeyState)
                {
                    count++;
                }
            }

            return(count);
        }
Beispiel #10
0
        /// <summary>
        /// Test the VolumeCipher class implementation
        /// </summary>
        public static void VolumeCipherTest(string InputDirectory)
        {
            string[] paths = DirectoryTools.GetFiles(InputDirectory);

            // set cipher paramaters
            CipherDescription desc = new CipherDescription(
                SymmetricEngines.RDX, 32,
                IVSizes.V128,
                CipherModes.CTR,
                PaddingModes.X923,
                BlockSizes.B128,
                RoundCounts.R14,
                Digests.Keccak512,
                64,
                Digests.Keccak512);

            // define the volume key
            VolumeKey vkey = new VolumeKey(desc, paths.Length);

            // key will be written to this stream
            MemoryStream keyStream = new MemoryStream();

            // create the volume key stream
            using (VolumeFactory vf = new VolumeFactory(keyStream))
                vf.Create(vkey);

            // encrypt the files in the directory
            using (VolumeCipher vc = new VolumeCipher(true, keyStream))
                vc.Transform(paths);

            // decrypt the files
            using (VolumeCipher vc = new VolumeCipher(false, keyStream))
                vc.Transform(paths);

            // manual inspection of files..
        }
Beispiel #11
0
        /// <summary>
        /// Test if the VolumeKey contains a file id
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        /// 
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        public static bool Contains(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                    return true;
            }

            return false;
        }
Beispiel #12
0
        /// <summary>
        /// Get the index of the file id in the VolumeKey
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        /// 
        /// <returns>Returns the index, or <c>-1</c> if not found</returns>
        public static int GetIndex(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int index = -1;

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                    return i;
            }

            return index;
        }
Beispiel #13
0
        /// <summary>
        /// Get the key/iv associated with a file id
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        /// 
        /// <returns>A populated KeyParams class, or null if the key is not found</returns>
        public static KeyParams FromId(Stream KeyStream, int Id)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.FileId[i] == Id)
                    return AtIndex(KeyStream, i);
            }

            return null;
        }
Beispiel #14
0
        /// <summary>
        /// Extract a KeyParams and CipherDescription
        /// </summary>
        /// 
        /// <param name="Index">The index of the key set to extract</param>
        /// <param name="Description">The <see cref="CipherDescription"/> that receives the cipher description</param>
        /// <param name="KeyParam">The <see cref="KeyParams"/> container that receives the key material from the file</param>
        /// 
        /// <exception cref="CryptoProcessingException">Thrown if the key file could not be found</exception>
        public void Extract(int Index, out CipherDescription Description, out KeyParams KeyParam)
        {
            if (!string.IsNullOrEmpty(_keyPath))
            {
                if (!File.Exists(_keyPath))
                    throw new CryptoProcessingException("VolumeFactory:Extract", "The key file could not be found! Check the path.", new FileNotFoundException());
            }

            if (_keyStream == null)
                _keyStream = new FileStream(_keyPath, FileMode.Open, FileAccess.Read);

            VolumeKey vkey = new VolumeKey(_keyStream);
            Description = vkey.Description;
            KeyParam = VolumeKey.AtIndex(_keyStream, Index);
        }
Beispiel #15
0
        /// <summary>
        /// Returns the number of keys in the volume with the specified state value
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="KeyState">The state to search</param>
        /// 
        /// <returns>The number of keys with that state</returns>
        public static int KeyCount(Stream KeyStream, VolumeKeyStates KeyState = VolumeKeyStates.Unassigned)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int count = 0;
            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.State[i] == (byte)KeyState)
                    count++;
            }

            return count;
        }
Beispiel #16
0
        /// <summary>
        /// Get the key/iv at a given index
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Index">The index value</param>
        /// 
        /// <returns>A populated KeyParams class</returns>
        public static KeyParams AtIndex(Stream KeyStream, int Index)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            byte[] key = new byte[vkey.Description.KeySize];
            byte[] iv = new byte[vkey.Description.IvSize];
            int offset = ID_SEEK + (vkey.Count * (ID_SIZE + STATE_SIZE) + (Index * (vkey.Description.IvSize + vkey.Description.KeySize)));

            KeyStream.Seek(offset, SeekOrigin.Begin);
            KeyStream.Read(key, 0, key.Length);
            KeyStream.Read(iv, 0, iv.Length);

            return new KeyParams(key, iv);
        }
Beispiel #17
0
        /// <summary>
        /// Get the index of the next unused key/iv in the volume key
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// 
        /// <returns>The index of the next available key pair</returns>
        public static int NextSubKey(Stream KeyStream)
        {
            // get the header
            VolumeKey vkey = new VolumeKey(KeyStream);

            int index = -1;
            for (int i = 0; i < vkey.Count; i++)
            {
                if (vkey.State[i] == (byte)VolumeKeyStates.Unassigned)
                    return i;
            }

            return index;
        }
Beispiel #18
0
        /// <summary>
        /// Initialize the class with a CipherDescription Structure; containing the cipher implementation details, and a <see cref="KeyParams"/> class containing the Key material.
        /// <para>This constructor creates and configures cryptographic instances based on the cipher description contained in a CipherDescription. 
        /// Cipher modes, padding, and engines are destroyed automatically through this classes Dispose() method.</para>
        /// </summary>
        /// 
        /// <param name="Encryption">Cipher is an encryptor</param>
        /// <param name="KeyStream">A stream containing a <see cref="VolumeKey"/> and the keying material</param>
        /// 
        /// <exception cref="CryptoProcessingException">Thrown if an invalid <see cref="VolumeKey"/> is used</exception>
        public VolumeCipher(bool Encryption, Stream KeyStream)
        {
            _keyStream = KeyStream;
            _volumeKey = new VolumeKey(KeyStream);

            if (!CipherDescription.IsValid(_volumeKey.Description))
                throw new CryptoProcessingException("VolumeCipher:CTor", "The key Header is invalid!", new ArgumentException());

            _disposeEngine = true;
            _isEncryption = Encryption;
            _blockSize = _volumeKey.Description.BlockSize;
            _isParallel = false;
            CipherDescription desc = _volumeKey.Description;

            if (_isStreamCipher = IsStreamCipher((SymmetricEngines)desc.EngineType))
            {
                _streamCipher = GetStreamEngine((SymmetricEngines)desc.EngineType, desc.RoundCount, (Digests)desc.KdfEngine);

                if (_streamCipher.GetType().Equals(typeof(Fusion)))
                {
                    if (_isParallel = ((Fusion)_streamCipher).IsParallel)
                        _blockSize = ((Fusion)_streamCipher).ParallelBlockSize;
                }
            }
            else
            {
                _cipherEngine = GetCipher((CipherModes)desc.CipherType, (SymmetricEngines)desc.EngineType, desc.RoundCount, desc.BlockSize, (Digests)desc.KdfEngine);

                if (_isCounterMode = _cipherEngine.GetType().Equals(typeof(CTR)))
                {
                    if (_isParallel = ((CTR)_cipherEngine).IsParallel)
                        _blockSize = ((CTR)_cipherEngine).ParallelBlockSize;
                }
                else
                {
                    if (_cipherEngine.GetType().Equals(typeof(CBC)))
                    {
                        if (_isParallel = ((CBC)_cipherEngine).IsParallel && !((CBC)_cipherEngine).IsEncryption)
                            _blockSize = ((CBC)_cipherEngine).ParallelBlockSize;
                    }
                    else if (_cipherEngine.GetType().Equals(typeof(CFB)))
                    {
                        if (_isParallel = ((CFB)_cipherEngine).IsParallel && !((CFB)_cipherEngine).IsEncryption)
                            _blockSize = ((CFB)_cipherEngine).ParallelBlockSize;
                    }
                    _cipherPadding = GetPadding((PaddingModes)_volumeKey.Description.PaddingType);
                }
            }
        }
Beispiel #19
0
        /// <summary>
        /// Creates a temporary VolumeKey on disk, extracts and compares the copy
        /// <para>Throws an Exception on failure</</para>
        /// </summary>
        public static void VolumeFactoryTest()
        {
            string path = GetTempPath();

            // cipher paramaters
            CipherDescription desc = new CipherDescription(
                SymmetricEngines.RDX, 32,
                IVSizes.V128,
                CipherModes.CTR,
                PaddingModes.X923,
                BlockSizes.B128,
                RoundCounts.R14,
                Digests.Keccak512,
                64,
                Digests.Keccak512);

            // create the package key
            VolumeKey vkey = new VolumeKey(desc, 10);
            // add id's
            for (int i = 0; i < vkey.FileId.Length; i++)
                vkey.FileId[i] = i;

            // write a key file
            using (VolumeFactory vf = new VolumeFactory(path))
                vf.Create(vkey);

            for (int i = 0; i < vkey.Count; i++)
            {
                CipherDescription desc2;
                KeyParams kp1;
                KeyParams kp2;

                using (FileStream stream = new FileStream(path, FileMode.Open))
                    kp1 = VolumeKey.AtIndex(stream, i);

                int id = vkey.FileId[i];

                // read the package
                using (VolumeFactory vf = new VolumeFactory(path))
                    vf.Extract(id, out desc2, out kp2);

                // compare key material
                if (!Compare.AreEqual(kp1.Key, kp2.Key))
                    throw new Exception();
                if (!Compare.AreEqual(kp1.IV, kp2.IV))
                    throw new Exception();
                if (!desc.Equals(desc2))
                    throw new Exception();
            }
            if (File.Exists(path))
                File.Delete(path);
        }
Beispiel #20
0
        /// <summary>
        /// Remove a file id, and key/iv pair from the VolumeKey
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        /// 
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        /// 
        /// <exception cref="CryptoProcessingException">Thrown if the Id does not exist</exception>
        public static void Remove(Stream KeyStream, int Id)
        {
            int index = GetIndex(KeyStream, Id);
            if (index == -1)
                throw new CryptoProcessingException("VolumeKey:Remove", "The id does not exist!", new ArgumentException());

            using (MemoryStream keyMem = new MemoryStream())
            {
                // get the header
                VolumeKey vkey = new VolumeKey(KeyStream);
                int offset = ID_SEEK + (vkey.Count * (ID_SIZE + STATE_SIZE));
                KeyStream.Seek(offset, SeekOrigin.Begin);

                // adjust the count
                vkey.Count--;
                // create reduced arrays
                ArrayUtils.RemoveAt(ref vkey.FileId, index);
                ArrayUtils.RemoveAt(ref vkey.State, index);

                // get the key material
                int klen = vkey.Description.KeySize + vkey.Description.IvSize;
                int koff = klen * index;
                byte[] data = new byte[klen * vkey.Count];
                KeyStream.Read(data, 0, data.Length);
                ArrayUtils.RemoveRange(ref data, koff, koff + klen);
                keyMem.Write(data, 0, data.Length);

                // overwrite stream w/ new key
                KeyStream.Seek(0, SeekOrigin.Begin);
                keyMem.WriteTo(KeyStream);
            }
        }
Beispiel #21
0
        /// <summary>
        /// Create a volume key file using automatic key material generation.
        /// <para>The Key, and IV sets are generated automatically using the cipher description contained in the <see cref="CipherDescription"/>.
        /// This overload creates keying material using the seed and digest engines specified with the <see cref="KeyGenerator"/> class</para>
        /// </summary>
        /// 
        /// <param name="Key">The <see cref="VolumeKey">VolumeKey</see> containing the cipher and key implementation details</param>
        /// <param name="SeedEngine">The <see cref="Prngs">Random Generator</see> used to create the stage I seed material during key generation.</param>
        /// <param name="HashEngine">The <see cref="Digests">Digest Engine</see> used in the stage II phase of key generation.</param>
        /// 
        /// <exception cref="System.IO.FileLoadException">A key file exists at the path specified</exception>
        /// <exception cref="System.UnauthorizedAccessException">The key file path is read only</exception>
        public void Create(VolumeKey Key, Prngs SeedEngine = Prngs.CSPRng, Digests HashEngine = Digests.SHA512)
        {
            int ksize = Key.Count * (Key.Description.KeySize + Key.Description.IvSize);
            byte[] kdata;

            using (KeyGenerator keyGen = new KeyGenerator(SeedEngine, HashEngine))
                kdata = keyGen.GetBytes(ksize);

            if (_keyStream == null)
                _keyStream = new FileStream(_keyPath, FileMode.Create, FileAccess.Write);

            byte[] hdr = Key.ToBytes();
            _keyStream.Write(hdr, 0, hdr.Length);
            _keyStream.Write(kdata, 0, kdata.Length);
        }
Beispiel #22
0
        /// <summary>
        /// Add a new file id, and key/iv pair to the VolumeKey
        /// </summary>
        /// 
        /// <param name="KeyStream">The stream containing the VolumeKey</param>
        /// <param name="Id">The file id</param>
        /// <param name="Key">The key</param>
        /// <param name="Iv">The vector</param>
        /// 
        /// <returns>Returns true if the file id is known, otherwizse false</returns>
        public static void Add(Stream KeyStream, int Id, byte[] Key, byte[] Iv)
        {
            using (MemoryStream keyMem = new MemoryStream())
            {
                // get the header
                VolumeKey vkey = new VolumeKey(KeyStream);
                int offset = ID_SEEK + (vkey.Count * ID_SIZE);
                KeyStream.Seek(offset, SeekOrigin.Begin);
                int kmlen = vkey.Count * (vkey.Description.KeySize + vkey.Description.IvSize);

                // adjust the header params
                vkey.Count++;
                ArrayUtils.AddAt(ref vkey.FileId, Id, vkey.Count);
                ArrayUtils.AddAt(ref vkey.State, (byte)0, vkey.Count);
                // copy header to mem
                vkey.ToStream().WriteTo(keyMem);

                byte[] data = new byte[kmlen];
                // copy existing key/iv pairs
                KeyStream.Read(data, 0, data.Length);
                keyMem.Write(data, 0, data.Length);
                // write new
                keyMem.Write(Key, 0, Key.Length);
                keyMem.Write(Iv, 0, Iv.Length);

                // overwrite stream w/ new
                KeyStream.Seek(0, SeekOrigin.Begin);
                keyMem.WriteTo(KeyStream);
            }
        }