public unsafe void Decrypt(Stream input, Stream output) { if (input == null) throw new ArgumentNullException("input"); if (output == null) throw new ArgumentNullException("output"); /* * All versions of the scrypt format will start with "scrypt" and * have at least 7 bytes of header. */ if (input.Length < 7) { throw new NoValidScryptBlockException("File really too small"); } var header = new byte[96]; input.ReadExactly(header, 0, header.Length); var marker = header.Take(scryptBytes.Length).ToArray(); if (!marker.SequenceEqual(scryptBytes)) { throw new NoValidScryptBlockException("No file marker"); } /* Check the format. */ if (header[6] != 0) { throw new UnrecognizedFormatVersionException(); } /* We must have at least 128 bytes. */ if (input.Length < 128) { throw new NoValidScryptBlockException("File too small"); } var dk = new byte[DERIVED_KEY_SIZE]; // ReSharper disable once UnusedVariable // pDk is useless but C# can't pin without creating a pointer fixed (byte* pDk = &dk[0]) { /* Parse the header and generate derived keys. */ ParseAndCheckHeader(header, dk); /* Decrypt data. */ using (var aesCtr = new ScryptAesCtr(dk.Take(32).ToArray(), 0)) { aesCtr.EncryptOrDectrypt(input, output); } /* Verify signature. */ var hmacKey = new byte[32]; Array.Copy(dk, 32, hmacKey, 0, 32); var hmacSha256 = new HMACSHA256(hmacKey); var inputWithoutSignature = new SubsetStream(input, 0, input.Length - 32); inputWithoutSignature.Position = 0; var computedHmac = hmacSha256.ComputeHash(inputWithoutSignature); input.Position = input.Length - 32; var hmacInFile = new byte[32]; input.ReadExactly(hmacInFile, 0, 32); if (!hmacInFile.SequenceEqual(computedHmac)) { throw new NoValidScryptBlockException("Signature don't verify"); } /* Zero sensitive data. */ for (int i = 0; i < dk.Length; i++) { dk[i] = 0; } } /* Success! */ }
public unsafe void Encrypt(Stream input, Stream output) { if (input == null) throw new ArgumentNullException("input"); if (output == null) throw new ArgumentNullException("output"); var dk = new byte[DERIVED_KEY_SIZE]; // ReSharper disable once UnusedVariable // pDk is useless but C# can't pin without creating a pointer fixed (byte* pDk = &dk[0]) { /* Generate the header and derived key. */ byte[] header; CreateHeader(out header, dk); /* Copy header into output buffer. */ output.Write(header, 0, header.Length); /* Encrypt data. */ var aesCtr = new ScryptAesCtr(dk.Take(32).ToArray(), 0); aesCtr.EncryptOrDectrypt(input, output); /* Add signature. */ var hmacKey = new byte[32]; Array.Copy(dk, 32, hmacKey, 0, 32); var hmacSha256 = new HMACSHA256(hmacKey); output.Position = 0; var headerHmac = hmacSha256.ComputeHash(output); output.Write(headerHmac, 0, 32); /* Zero sensitive data. */ for (int i = 0; i < dk.Length; i++) { dk[i] = 0; } } }