public void Initialize(DerivedBytesProvider derivedBytesProvider, Action <Dictionary <string, byte[]> > afterHeaderRead = null) { if (derivedBytesProvider == null) { throw new ArgumentNullException(nameof(derivedBytesProvider)); } //header //FileDesignator (8 bytes) + passwordSalt (32 bytes) + hmac salt (32 bytes) + iv (32 bytes) FileHeader header = new FileHeader(); StreamRead(streamIn, header.fileDesignator); StreamRead(streamIn, header.passwordSalt); StreamRead(streamIn, header.hmacSalt); StreamRead(streamIn, header.iv); StreamRead(streamIn, header.headerAuthnDisk); afterHeaderRead?.Invoke(header.ToDictionary()); FileVersion = HelixFileVersion.GetVersion(header.fileDesignator); if (FileVersion == null) { throw new FileDesignatorException("Invalid file format, file designator not correct"); } DerivedBytes = derivedBytesProvider.GetDerivedBytes(header.passwordSalt, FileVersion.DerivedBytesIterations); byte[] headerBytes = header.GetBytesToHash(); byte[] hmacFullKey = ByteBlock.ConcatenateBytes(header.hmacSalt, DerivedBytes.Key); hmacHash = new HMACSHA256(hmacFullKey); //Validate Header HMAC byte[] headerAuthnComputed = hmacHash.ComputeHash(headerBytes); if (!ByteBlock.Equals(header.headerAuthnDisk, headerAuthnComputed)) { throw new HMACAuthenticationException("Header HMAC Authentication Failed"); } hmacTransform = new HMACDecrypt(headerAuthnComputed, hmacHash); hmacStream = new CryptoStream2(streamIn, hmacTransform, CryptoStreamMode.Read); aesTransform = Aes.Create(); aesTransform.KeySize = 256; aesTransform.BlockSize = 128; aesTransform.Mode = CipherMode.CBC; aesTransform.Padding = PaddingMode.PKCS7; aesTransform.IV = header.iv; aesTransform.Key = DerivedBytes.Key; aesStream = new CryptoStream2(hmacStream, aesTransform.CreateDecryptor(), CryptoStreamMode.Read); gzipStream = new GZipStream(aesStream, CompressionMode.Decompress, true); initialized = true; }
public AuthenticatedEncryptor(Stream streamOut, DerivedBytes derivedBytes, HelixFileVersion hxVersion, byte[] hmacSalt = null, byte[] iv = null) { if (derivedBytes == null) { throw new ArgumentNullException(nameof(derivedBytes)); } if (hxVersion == null) { throw new ArgumentNullException(nameof(hxVersion)); } if (hmacSalt != null && hmacSalt.Length != HelixConsts.HMACSaltSize) { throw new ArgumentOutOfRangeException(nameof(hmacSalt)); } if (iv != null && iv.Length != HelixConsts.IVSize) { throw new ArgumentOutOfRangeException(nameof(iv)); } using (var random = RandomNumberGenerator.Create()) { if (hmacSalt == null) { hmacSalt = new byte[HelixConsts.HMACSaltSize]; random.GetBytes(hmacSalt); } if (iv == null) { iv = new byte[HelixConsts.IVSize]; random.GetBytes(iv); } } FileHeader header = new FileHeader { fileDesignator = hxVersion.FileDesignator, passwordSalt = derivedBytes.Salt, hmacSalt = hmacSalt, iv = iv, }; byte[] hmacFullKey = ByteBlock.ConcatenateBytes(hmacSalt, derivedBytes.Key); this.streamOut = streamOut ?? throw new ArgumentNullException(nameof(streamOut)); byte[] bytesToHash = header.GetBytesToHash(); streamOut.Write(bytesToHash, 0, bytesToHash.Length); hmacHash = new HMACSHA256(hmacFullKey); header.headerAuthnDisk = hmacHash.ComputeHash(header.GetBytesToHash()); streamOut.Write(header.headerAuthnDisk, 0, header.headerAuthnDisk.Length); hmacTransform = new HMACEncrypt(header.headerAuthnDisk, hmacHash); hmacStream = new CryptoStream(streamOut, hmacTransform, CryptoStreamMode.Write); aesTransform = Aes.Create(); aesTransform.KeySize = 256; aesTransform.BlockSize = 128; aesTransform.Mode = CipherMode.CBC; aesTransform.Padding = PaddingMode.PKCS7; aesTransform.IV = iv; aesTransform.Key = derivedBytes.Key; aesStream = new CryptoStream(hmacStream, aesTransform.CreateEncryptor(), CryptoStreamMode.Write); gzipStream = new GZipStream(aesStream, CompressionMode.Compress, true); }
public byte[] GetBytesToHash() { return(ByteBlock.ConcatenateBytes(fileDesignator, passwordSalt, hmacSalt, iv)); }