private static byte[] Decrypt(byte[] passwordBytes, byte[] privateKey) { byte[] keyAlgorithm = GetKeyAlgorithm(privateKey); byte[] keyVersion = GetKeyVersion(privateKey); byte[] salt = GetSalt(privateKey); byte[] nonce = GetNonce(privateKey); byte[] additionalData = Utilities.ConcatArrays(keyAlgorithm, keyVersion); byte[] encryptedPrivateKey = GetEncryptedPrivateKey(privateKey); byte[] key = Argon2.DeriveKey(passwordBytes, salt); Utilities.ZeroArray(passwordBytes); byte[] decryptedPrivateKey = SecretAeadXChaCha20Poly1305.Decrypt(encryptedPrivateKey, nonce, key, additionalData); Utilities.ZeroArray(key); ChunkHandling.ValidateKeyCommitmentBlock(decryptedPrivateKey); return(ChunkHandling.RemoveKeyCommitmentBlock(decryptedPrivateKey)); }
private static void Decrypt(FileStream inputFile, FileStream outputFile, byte[] nonce, byte[] dataEncryptionKey, byte[] additionalData, int lastChunkLength) { int headersLength = FileHeaders.GetHeadersLength(); inputFile.Seek(headersLength, SeekOrigin.Begin); const int offset = 0; byte[] ciphertextChunk = new byte[Constants.TotalChunkLength]; while (inputFile.Read(ciphertextChunk, offset, ciphertextChunk.Length) > 0) { byte[] plaintextChunk = SecretAeadXChaCha20Poly1305.Decrypt(ciphertextChunk, nonce, dataEncryptionKey, additionalData); ChunkHandling.ValidateKeyCommitmentBlock(plaintextChunk); nonce = Sodium.Utilities.Increment(nonce); additionalData = ChunkHandling.GetPreviousPoly1305Tag(ciphertextChunk); plaintextChunk = ChunkHandling.RemoveKeyCommitmentBlock(plaintextChunk); outputFile.Write(plaintextChunk, offset, plaintextChunk.Length); } outputFile.SetLength((outputFile.Length - Constants.FileChunkSize) + lastChunkLength); Utilities.ZeroArray(dataEncryptionKey); }