private void VolumeKeyTest() { CipherDescription cd1 = new CipherDescription( SymmetricEngines.RHX, 192, IVSizes.V128, CipherModes.CTR, PaddingModes.None, BlockSizes.B128, RoundCounts.R22); MemoryStream mk; using (VolumeCipher vc = new VolumeCipher()) mk = vc.CreateKey(cd1, 100); VolumeKey vk1 = new VolumeKey(mk); CipherDescription cd2 = vk1.Description; if (!cd1.Equals(cd2)) { throw new Exception("KeyFactoryTest: VolumeKey serialization has failed!"); } VolumeKey vk2 = new VolumeKey(mk.ToArray()); if (!vk1.Equals(vk2)) { throw new Exception("KeyFactoryTest: VolumeKey serialization has failed!"); } if (vk1.GetHashCode() != vk2.GetHashCode()) { throw new Exception("KeyFactoryTest: VolumeKey hash code test has failed!"); } }
/// <summary> /// Decrypt the files in the specified directory /// </summary> /// /// <param name="FilePaths">A list of the files to be processed</param> /// /// <exception cref="CryptoProcessingException">Thrown if the VolumeKey does not contain enough keys to encrypt all the files in the directory</exception> public void Decrypt(string[] FilePaths) { if (FilePaths.Length < 1) { throw new CryptoProcessingException("VolumeCipher:Transform", "The file paths list is empty!", new ArgumentException()); } InitializeProgress(FilePaths); if (m_progressTotal < 1) { throw new CryptoProcessingException("VolumeCipher:Initialize", "The files are all zero bytes!", new ArgumentException()); } long prgCtr = 0; for (int i = 0; i < FilePaths.Length; ++i) { FileStream inpStream = GetStream(FilePaths[i], true); VolumeHeader vh = GetHeader(inpStream); KeyParams key = VolumeKey.FromId(m_keyStream, vh.FileId); // user dropped a file in, notify or log if (key == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; has no key assigned", FilePaths[i])); } } else { FileStream outStream = GetStream(FilePaths[i], false); if (inpStream == null || outStream == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; could not be written to", FilePaths[i])); } } else { m_volumeKey.State[m_volumeKey.GetIndex(vh.FileId)] = (byte)VolumeKeyStates.Decrypted; m_cipherStream.Initialize(false, key); m_cipherStream.Write(inpStream, outStream); outStream.SetLength(outStream.Length - VolumeHeader.GetHeaderSize); prgCtr += inpStream.Position; CalculateProgress(prgCtr); inpStream.Dispose(); outStream.Dispose(); UpdateKey(); } } } }
/// <summary> /// Extract a KeyParams and CipherDescription from a VolumeKey stream /// </summary> /// /// <param name="KeyStream">The stream containing the VolumeKey</param> /// <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(Stream KeyStream, int Index, out CipherDescription Description, out KeyParams KeyParam) { if (KeyStream == null || KeyStream.Length < 96) { throw new CryptoProcessingException("VolumeFactory:Extract", "The key file could not be loaded! Check the stream.", new FileNotFoundException()); } VolumeKey vkey = new VolumeKey(KeyStream); Description = vkey.Description; KeyParam = VolumeKey.AtIndex(KeyStream, Index); }
private static bool IsMatchingVolumeKey(string TargetFile, string KeyPath) { using (FileStream fs = new FileStream(TargetFile, FileMode.Open, FileAccess.Read)) { using (FileStream ks = new FileStream(KeyPath, FileMode.Open, FileAccess.Read)) { fs.Seek(fs.Length - VolumeHeader.GetHeaderSize, SeekOrigin.Begin); VolumeHeader vh = new VolumeHeader(fs); VolumeKey vk = new VolumeKey(ks); return(Evaluate.AreEqual(vk.Tag, vh.KeyId)); } } }
/// <summary> /// Encrypt a file with a specific key /// </summary> /// /// <param name="FilePath">The full path to the file</param> /// <param name="FileId">The files key id</param> public void Encrypt(string FilePath, int FileId) { if (m_progressTotal < 1) { throw new CryptoProcessingException("VolumeCipher:Initialize", "The files are all zero bytes!", new ArgumentException()); } KeyParams key = VolumeKey.FromId(m_keyStream, FileId); if (key == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; has no key assigned", FilePath)); } } else { FileStream inpStream = GetStream(FilePath, true); FileStream outStream = GetStream(FilePath, false); if (inpStream == null || outStream == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; could not be written to", FilePath)); } } else { int index = m_volumeKey.GetIndex(FileId); m_volumeKey.State[index] = (byte)VolumeKeyStates.Encrypted; m_cipherStream.Initialize(true, key); m_cipherStream.ProgressPercent += OnCipherProgress; m_cipherStream.Write(inpStream, outStream); m_cipherStream.ProgressPercent -= OnCipherProgress; // write the header VolumeHeader vh = new VolumeHeader(m_volumeKey.Tag, m_volumeKey.FileId[index]); outStream.Write(vh.ToBytes(), 0, VolumeHeader.GetHeaderSize); inpStream.Dispose(); outStream.Dispose(); UpdateKey(); } } }
/// <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="VTDev.Libraries.CEXEngine.Crypto.Common.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="VTDev.Libraries.CEXEngine.Crypto.Processing.Structure.VolumeKey">VolumeKey</see> containing the cipher and key implementation details</param> /// <param name="SeedEngine">The <see cref="VTDev.Libraries.CEXEngine.Crypto.Enumeration.SeedGenerators">Random Generator</see> used to create the stage I seed material during key generation.</param> /// <param name="HashEngine">The <see cref="VTDev.Libraries.CEXEngine.Crypto.Enumeration.Digests">Digest Engine</see> used in the stage II phase of key generation.</param> /// /// <returns>A populated VolumeKey</returns> public MemoryStream Create(VolumeKey Key, SeedGenerators SeedEngine = SeedGenerators.CSPRsg, Digests HashEngine = Digests.SHA512) { int ksize = Key.Count * (Key.Description.KeySize + Key.Description.IvSize); byte[] kdata; using (KeyGenerator keyGen = new KeyGenerator(SeedEngine, HashEngine, null)) kdata = keyGen.GetBytes(ksize); MemoryStream keyStream = new MemoryStream(); byte[] hdr = Key.ToBytes(); keyStream.Write(hdr, 0, hdr.Length); keyStream.Write(kdata, 0, kdata.Length); keyStream.Seek(0, SeekOrigin.Begin); return(keyStream); }
/// <summary> /// Initialize the cipher instance /// </summary> /// /// <param name="KeyStream">A stream containing a volume key</param> public void Initialize(Stream KeyStream) { m_keyStream = KeyStream; m_volumeKey = new VolumeKey(KeyStream); if (!CipherDescription.IsValid(m_volumeKey.Description)) { throw new CryptoProcessingException("VolumeCipher:Initialize", "The key Header is invalid!", new ArgumentException()); } CipherDescription dsc = m_volumeKey.Description; try { m_cipherStream = new CipherStream(dsc); } catch (Exception ex) { throw new CryptoProcessingException("VolumeCipher:Initialize", "The cipher could not be initialized!", ex); } }
/// <summary> /// Decrypt a single file in the volume /// </summary> /// /// <param name="InputPath">The path to the encrypted file</param> /// <param name="OututPath">The path to the new decrypted file</param> public void Decrypt(string InputPath, string OututPath) { FileStream inpStream = GetStream(InputPath, true); VolumeHeader vh = GetHeader(inpStream); KeyParams key = VolumeKey.FromId(m_keyStream, vh.FileId); if (key == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; has no key assigned", InputPath)); } } else { FileStream outStream = GetStream(OututPath, false); if (inpStream == null || outStream == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; could not be written to", OututPath)); } } else { m_volumeKey.State[m_volumeKey.GetIndex(vh.FileId)] = (byte)VolumeKeyStates.Decrypted; m_cipherStream.ProgressPercent += OnCipherProgress; m_cipherStream.Initialize(false, key); m_cipherStream.Write(inpStream, outStream); m_cipherStream.ProgressPercent -= OnCipherProgress; outStream.SetLength(outStream.Length - VolumeHeader.GetHeaderSize); inpStream.Dispose(); outStream.Dispose(); UpdateKey(); } } }
/// <summary> /// Encrypt the files in the specified directory /// </summary> /// /// <param name="FilePaths">A list of the files to be processed</param> /// /// <exception cref="CryptoProcessingException">Thrown if the VolumeKey does not contain enough keys to encrypt all the files in the directory</exception> public void Encrypt(string[] FilePaths) { if (FilePaths.Length < 1) { throw new CryptoProcessingException("VolumeCipher:Transform", "The file paths list is empty!", new ArgumentException()); } if (m_volumeKey.KeyCount() < FilePaths.Length) { throw new CryptoProcessingException("VolumeCipher:Transform", "Not enough keys in the volume key to encrypt this directory!", new ArgumentException()); } InitializeProgress(FilePaths); if (m_progressTotal < 1) { throw new CryptoProcessingException("VolumeCipher:Initialize", "The files are all zero bytes!", new ArgumentException()); } long prgCtr = 0; for (int i = 0; i < FilePaths.Length; ++i) { int index = m_volumeKey.NextSubKey(); KeyParams key = VolumeKey.AtIndex(m_keyStream, index); if (key == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; has no key assigned", FilePaths[i])); } } else { FileStream inpStream = GetStream(FilePaths[i], true); FileStream outStream = GetStream(FilePaths[i], false); if (inpStream == null || outStream == null) { if (ErrorNotification != null) { ErrorNotification(this, string.Format("The file {0}; could not be written to", FilePaths[i])); } } else { m_volumeKey.State[index] = (byte)VolumeKeyStates.Encrypted; m_cipherStream.Initialize(true, key); m_cipherStream.Write(inpStream, outStream); // write the header VolumeHeader vh = new VolumeHeader(m_volumeKey.Tag, m_volumeKey.FileId[index]); outStream.Write(vh.ToBytes(), 0, VolumeHeader.GetHeaderSize); prgCtr += inpStream.Position; CalculateProgress(prgCtr); inpStream.Dispose(); outStream.Dispose(); UpdateKey(); } } } }