private static void DecryptFile(string filePath, int parametersLength, byte[] macBackup, byte[] encryptionKey) { try { string decryptedFilePath = Regex.Replace(filePath, Constants.EncryptedExtension, string.Empty); int headersLength = Constants.SaltLength + parametersLength; using (var plaintext = new FileStream(decryptedFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) using (var ciphertext = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) { // Skip the header bytes ciphertext.Seek(headersLength, SeekOrigin.Begin); byte[] fileBytes = FileHandling.GetBufferSize(ciphertext.Length); // Generate a counter starting at 0 byte[] counter = Generate.Counter(); int bytesRead; MemoryEncryption.DecryptByteArray(ref encryptionKey); while ((bytesRead = ciphertext.Read(fileBytes, 0, fileBytes.Length)) > 0) { byte[] decryptedBytes = StreamEncryption.DecryptXChaCha20(fileBytes, counter, encryptionKey); plaintext.Write(decryptedBytes, 0, bytesRead); counter = Sodium.Utilities.Increment(counter); } Utilities.ZeroArray(encryptionKey); } CompleteDecryption(filePath, decryptedFilePath); } catch (Exception ex) when(ExceptionFilters.FileEncryptionExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to decrypt the file."); Utilities.ZeroArray(encryptionKey); RestoreMAC(filePath, macBackup); } }
public void OpenSecretBoxXChaCha20() { const string EXPECTED = "Adam Caudill"; var actual = Encoding.UTF8.GetString(StreamEncryption.DecryptXChaCha20( Utilities.HexToBinary("b99341769d6d1342541de1ad"), Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWX"), Encoding.UTF8.GetBytes("12345678901234567890123456789012"))); Assert.AreEqual(EXPECTED, actual); }
private static byte[] DecryptFileBytes(byte[] fileBytes, byte[] nonce, byte[] key) { byte[] decryptedBytes = new byte[fileBytes.Length]; if (Globals.EncryptionAlgorithm == (int)Cipher.XChaCha20) { decryptedBytes = StreamEncryption.DecryptXChaCha20(fileBytes, nonce, key); } else if (Globals.EncryptionAlgorithm == (int)Cipher.XSalsa20) { decryptedBytes = StreamEncryption.Decrypt(fileBytes, nonce, key); } return(decryptedBytes); }
/// <summary> /// Decrypt a message using provided key and nonce /// </summary> /// <param name="encrypted">Ciphertext message</param> /// <param name="key">Plaintext/Base64-encoded key</param> /// <param name="nonce">Base64-encoded nonce (generate using GenerateNonce())</param> /// <returns> /// Plaintext UTF-8 message /// </returns> public static string Decrypt(string encrypted, string key, string nonce) { // Validate parameters if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (string.IsNullOrEmpty(encrypted)) { throw new ArgumentNullException(nameof(encrypted)); } if (string.IsNullOrEmpty(nonce)) { throw new ArgumentNullException(nameof(nonce)); } // Check nonce is Base64 if (!Utils.IsBase64(nonce)) { throw new ArgumentException($"{nameof(nonce)} must be base64-encoded string"); } byte[] nonce_bytes = Convert.FromBase64String(nonce); // Convert key to bytes byte[] key_bytes; if (Utils.IsBase64(key)) { // Key is Base64, convert to raw bytes key_bytes = Convert.FromBase64String(key); } else { // Key is plaintext string, fallback to raw ASCII bytes key_bytes = Encoding.ASCII.GetBytes(key); } // Check if encrypted is Base64 if (!Utils.IsBase64(encrypted)) { throw new ArgumentException($"{nameof(encrypted)} must be base64-encoded string"); } byte[] encrypted_bytes = Convert.FromBase64String(encrypted); // Decrypt the message var raw_msg = StreamEncryption.DecryptXChaCha20(encrypted_bytes, nonce_bytes, key_bytes); return(Encoding.UTF8.GetString(raw_msg)); }