internal static void XorEncryptAndWrite(Stream output, int size, byte[] data, byte[] key1, byte[] iv1, byte[] key2, byte[] iv2) { byte[] rpad = RandomHelper.GenerateBytes(size); byte[] xor = new byte[size]; for (int i = 0; i < size; i++) { xor[i] = (byte)(data[i] ^ rpad[i]); } byte[] d1 = ChaCha20Rfc7539.Encrypt(rpad, key1, iv1); byte[] d2 = AES.EncryptCBC(xor, key2, iv2); BinaryHelper.WriteLV(output, d1); BinaryHelper.WriteLV(output, d2); }
/// <summary> /// Decrypt with RSA key /// </summary> /// <param name="input">Input stream</param> /// <param name="output">Output stream</param> /// <param name="rsa">RSA key</param> /// <param name="notifyProgression">Notify progression method</param> public static void DecryptWithKey(Stream input, Stream output, RSACryptoServiceProvider rsa, Action <int> notifyProgression = null) { input.Seek(5, SeekOrigin.Current); // Header input.Seek(1, SeekOrigin.Current); // Version byte[] keyNameData = BinaryHelper.ReadLV(input); byte[] encKeysData = BinaryHelper.ReadLV(input); if (notifyProgression != null) { notifyProgression(5 + 1 + 2 * 4 + keyNameData.Length + encKeysData.Length); } byte[] keysData = RSA.Decrypt(rsa, encKeysData); byte[] key1, iv1, key2, iv2; using (MemoryStream ms = new MemoryStream(keysData)) { key1 = BinaryHelper.ReadLV(ms); iv1 = BinaryHelper.ReadLV(ms); key2 = BinaryHelper.ReadLV(ms); iv2 = BinaryHelper.ReadLV(ms); } byte[] d1, d2; byte[] backup = null; do { d1 = BinaryHelper.ReadLV(input); if (d1.Length > 0) { if (backup != null) { output.Write(backup, 0, backup.Length); } byte[] rpad = ChaCha20Rfc7539.Decrypt(d1, key1, iv1); d2 = BinaryHelper.ReadLV(input); byte[] xor = AES.DecryptCBC(d2, key2, iv2); if (notifyProgression != null) { notifyProgression(2 * 4 + d1.Length + d2.Length); } byte[] data = new byte[rpad.Length]; for (int i = 0; i < rpad.Length; i++) { data[i] = (byte)(rpad[i] ^ xor[i]); } backup = new byte[data.Length]; Array.Copy(data, 0, backup, 0, data.Length); } else { byte[] unpadData = Padding.Unpad(backup, AES.BLOCK_SIZE, _paddingStyle); output.Write(unpadData, 0, unpadData.Length); } } while (d1.Length > 0); }