public void PackingAndUnpackingResultsInOriginal() { CryptoHeader header = new CryptoHeader { PackageName = "MyAppName", AlgorithmName = "Twofish", KdfName = "PBKDF2", Cost = "10", Nonce = CommonMocksAndStubs.FilledByteArray(8, 66), Salt = CommonMocksAndStubs.FilledByteArray(8, 77), Compression = "gzip", }; byte[] cipher = CommonMocksAndStubs.FilledByteArray(16, 88); byte[] packedHeader = CryptoHeaderPacker.PackHeaderAndCypher(header, cipher); CryptoHeaderPacker.UnpackHeaderAndCipher(packedHeader, "MyAppName", out CryptoHeader unpackedHeader, out byte[] unpackedCipher); Assert.AreEqual(header.PackageName, unpackedHeader.PackageName); Assert.AreEqual(header.AlgorithmName, unpackedHeader.AlgorithmName); Assert.AreEqual(header.KdfName, unpackedHeader.KdfName); Assert.AreEqual(header.Cost, unpackedHeader.Cost); Assert.AreEqual(header.Nonce, unpackedHeader.Nonce); Assert.AreEqual(header.Salt, unpackedHeader.Salt); Assert.AreEqual(cipher, unpackedCipher); Assert.AreEqual(header.Compression, unpackedHeader.Compression); }
public void PackingAndUnpackingWorksWithKeyOnly() { // If the encryption is started with a key instead of a password, there are not all parametes set. CryptoHeader header = new CryptoHeader { PackageName = "MyAppName", AlgorithmName = "Twofish", KdfName = null, Cost = null, Nonce = CommonMocksAndStubs.FilledByteArray(8, 66), Salt = null, Compression = "gzip", }; byte[] cipher = CommonMocksAndStubs.FilledByteArray(16, 88); byte[] packedHeader = CryptoHeaderPacker.PackHeaderAndCypher(header, cipher); CryptoHeaderPacker.UnpackHeaderAndCipher(packedHeader, "MyAppName", out CryptoHeader unpackedHeader, out byte[] unpackedCipher); Assert.AreEqual(header.PackageName, unpackedHeader.PackageName); Assert.AreEqual(header.AlgorithmName, unpackedHeader.AlgorithmName); Assert.AreEqual(header.KdfName, unpackedHeader.KdfName); Assert.AreEqual(header.Cost, unpackedHeader.Cost); Assert.AreEqual(header.Nonce, unpackedHeader.Nonce); Assert.AreEqual(header.Salt, unpackedHeader.Salt); Assert.AreEqual(cipher, unpackedCipher); Assert.AreEqual(header.Compression, unpackedHeader.Compression); }
public static CryptoHeader ReadHeader(Stream cipherTextStream, bool leaveOpen) { cipherTextStream.Position = 0; var header = new CryptoHeader(); using (var br = new BinaryReader(cipherTextStream, Encoding.UTF8, leaveOpen)) { header.PayloadLength = UnpackInt64(br); header.Magic = UnpackBytes(br); if (header.Magic.SequenceEqual(brPackMagic) == false) { throw new Exception("Unsupported magic."); } header.Signature = UnpackBytes(br); header.EncryptionAlgorithm = UnpackString(br); if (header.EncryptionAlgorithm != EncryptionType.Aes256CbcPkcs7) { throw new Exception("Unsupported encryption algorithm."); } header.CreatedBy = UnpackBytes(br); header.Id = UnpackString(br); header.KeyId = UnpackString(br); header.Purpose = UnpackString(br); header.MimeType = UnpackString(br); header.Created = DateTimeOffset.FromUnixTimeMilliseconds(UnpackInt64(br)); header.Iv = UnpackBytes(br); header.CipherMetadata = UnpackBytes(br); } return(header); }
public static async Task <string> DecryptAndUncompressStreamAsync(byte[] key, Stream cipherTextStream, Stream tempUncompressStream, Stream plainTextStream) { if (key == null || key.Length != 32) { throw new ArgumentNullException("key"); } string metadata = null; cipherTextStream.Position = 0; tempUncompressStream.Position = 0; plainTextStream.Position = 0; var header = new CryptoHeader(); long signaturePosition; using (var br = new BinaryReader(cipherTextStream, Encoding.UTF8, true)) { header.PayloadLength = UnpackInt64(br); header.Magic = UnpackBytes(br); if (header.Magic.SequenceEqual(brPackMagic) == false) { throw new Exception("Unsupported magic."); } signaturePosition = cipherTextStream.Position; header.Signature = UnpackBytes(br); header.EncryptionAlgorithm = UnpackString(br); if (header.EncryptionAlgorithm != EncryptionType.Aes256CbcPkcs7) { throw new Exception("Unsupported encryption algorithm."); } header.CreatedBy = UnpackBytes(br); header.Id = UnpackString(br); header.KeyId = UnpackString(br); header.Purpose = UnpackString(br); header.MimeType = UnpackString(br); header.Created = DateTimeOffset.FromUnixTimeMilliseconds(UnpackInt64(br)); header.Iv = UnpackBytes(br); header.CipherMetadata = UnpackBytes(br); if (header.CipherMetadata != null && header.CipherMetadata.Length > 0) { metadata = Encoding.UTF8.GetString(Aes256Decrypt(key, header.Iv, header.CipherMetadata)); } var cipherTextPosition = cipherTextStream.Position; cipherTextStream.Seek(signaturePosition + 32 + 4, SeekOrigin.Begin); var signingKey = key; var signatureCompare = HmacSha256Hash(signingKey, cipherTextStream); if (signatureCompare.SequenceEqual(header.Signature) == false) { throw new Exception("Signature comparison failed."); } using (var aes = Aes.Create()) { aes.Key = key; aes.IV = header.Iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; cipherTextStream.Seek((int)cipherTextPosition, SeekOrigin.Begin); using (var decryptor = aes.CreateDecryptor(key, header.Iv)) { var cs = new CryptoStream(cipherTextStream, decryptor, CryptoStreamMode.Read); await cs.CopyToAsync(tempUncompressStream); await tempUncompressStream.FlushAsync(); aes.Clear(); tempUncompressStream.Seek(0, SeekOrigin.Begin); await DecompressAsync(tempUncompressStream, plainTextStream, true); } } } return(metadata); }