2017-04-12 09:10:39 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace Teknik.Utilities.Cryptography
|
|
|
|
|
{
|
|
|
|
|
|
2017-04-15 08:28:34 +02:00
|
|
|
|
public class AesCounterManaged
|
2017-04-12 09:10:39 +02:00
|
|
|
|
{
|
|
|
|
|
public static byte[] Decrypt(byte[] data, string key, string iv)
|
|
|
|
|
{
|
|
|
|
|
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
|
|
|
|
|
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
|
|
|
|
|
return Decrypt(data, keyBytes, ivBytes);
|
|
|
|
|
}
|
|
|
|
|
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
|
|
|
|
|
{
|
|
|
|
|
using (MemoryStream stream = new MemoryStream(data))
|
|
|
|
|
{
|
|
|
|
|
return ProcessCipher(false, stream, 1024, key, iv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] Encrypt(byte[] data, string key, string iv)
|
|
|
|
|
{
|
|
|
|
|
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
|
|
|
|
|
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
|
|
|
|
|
return Encrypt(data, keyBytes, ivBytes);
|
|
|
|
|
}
|
|
|
|
|
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
|
|
|
|
|
{
|
|
|
|
|
using (MemoryStream stream = new MemoryStream(data))
|
|
|
|
|
{
|
|
|
|
|
return ProcessCipher(true, stream, 1024, key, iv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] ProcessCipher(bool encrypt, Stream input, int chunkSize, byte[] key, byte[] iv)
|
|
|
|
|
{
|
|
|
|
|
// Make sure the input stream is at the beginning
|
|
|
|
|
input.Seek(0, SeekOrigin.Begin);
|
|
|
|
|
|
2017-04-15 08:28:34 +02:00
|
|
|
|
AesCounterStream cryptoStream = new AesCounterStream(input, encrypt, key, iv);
|
2017-04-12 09:10:39 +02:00
|
|
|
|
|
|
|
|
|
// Initialize variables
|
|
|
|
|
byte[] output = new byte[input.Length];
|
|
|
|
|
|
|
|
|
|
// Process the stream and save the bytes to the output
|
|
|
|
|
int curByte = 0;
|
|
|
|
|
int processedBytes = 0;
|
|
|
|
|
byte[] buffer = new byte[chunkSize];
|
|
|
|
|
int bytesRemaining = (int)input.Length;
|
|
|
|
|
int bytesToRead = chunkSize;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (chunkSize > bytesRemaining)
|
|
|
|
|
{
|
|
|
|
|
bytesToRead = bytesRemaining;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
processedBytes = cryptoStream.Read(buffer, 0, bytesToRead);
|
|
|
|
|
if (processedBytes > 0)
|
|
|
|
|
{
|
|
|
|
|
buffer.Take(processedBytes).ToArray().CopyTo(output, curByte);
|
|
|
|
|
|
|
|
|
|
// Clear the buffer
|
|
|
|
|
Array.Clear(buffer, 0, chunkSize);
|
|
|
|
|
}
|
|
|
|
|
curByte += processedBytes;
|
|
|
|
|
bytesRemaining -= processedBytes;
|
|
|
|
|
}
|
|
|
|
|
while (processedBytes > 0 && bytesRemaining > 0);
|
|
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-07 08:21:24 +02:00
|
|
|
|
public static void EncryptToFile(Stream input, string filePath, int chunkSize, byte[] key, byte[] iv)
|
2021-08-07 07:26:09 +02:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
|
|
|
|
{
|
|
|
|
|
EncryptToStream(input, fileStream, chunkSize, key, iv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void EncryptToStream(Stream input, Stream output, int chunkSize, byte[] key, byte[] iv)
|
2017-04-12 09:10:39 +02:00
|
|
|
|
{
|
|
|
|
|
// Make sure the input stream is at the beginning
|
|
|
|
|
input.Seek(0, SeekOrigin.Begin);
|
|
|
|
|
|
2017-04-15 08:28:34 +02:00
|
|
|
|
AesCounterStream cryptoStream = new AesCounterStream(input, true, key, iv);
|
2017-04-12 09:10:39 +02:00
|
|
|
|
|
2021-08-07 07:26:09 +02:00
|
|
|
|
int curByte = 0;
|
|
|
|
|
int processedBytes = 0;
|
|
|
|
|
byte[] buffer = new byte[chunkSize];
|
|
|
|
|
int bytesRemaining = (int)input.Length;
|
|
|
|
|
int bytesToRead = chunkSize;
|
|
|
|
|
do
|
2017-04-12 09:10:39 +02:00
|
|
|
|
{
|
2021-08-07 07:26:09 +02:00
|
|
|
|
if (chunkSize > bytesRemaining)
|
2017-04-12 09:10:39 +02:00
|
|
|
|
{
|
2021-08-07 07:26:09 +02:00
|
|
|
|
bytesToRead = bytesRemaining;
|
2017-04-12 09:10:39 +02:00
|
|
|
|
}
|
2021-08-07 07:26:09 +02:00
|
|
|
|
|
|
|
|
|
processedBytes = cryptoStream.Read(buffer, 0, bytesToRead);
|
|
|
|
|
if (processedBytes > 0)
|
|
|
|
|
{
|
|
|
|
|
output.Write(buffer, 0, processedBytes);
|
|
|
|
|
|
|
|
|
|
// Clear the buffer
|
|
|
|
|
Array.Clear(buffer, 0, chunkSize);
|
|
|
|
|
}
|
|
|
|
|
curByte += processedBytes;
|
|
|
|
|
bytesRemaining -= processedBytes;
|
2017-04-12 09:10:39 +02:00
|
|
|
|
}
|
2021-08-07 07:26:09 +02:00
|
|
|
|
while (processedBytes > 0 && bytesRemaining > 0);
|
2017-04-12 09:10:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] CreateKey(string password, string iv, int keySize = 256)
|
|
|
|
|
{
|
|
|
|
|
byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
|
|
|
|
|
return CreateKey(password, ivBytes, keySize);
|
|
|
|
|
}
|
|
|
|
|
public static byte[] CreateKey(string password, byte[] iv, int keySize = 256)
|
|
|
|
|
{
|
2017-06-09 19:41:00 +02:00
|
|
|
|
const int Iterations = 5000;
|
2017-04-12 09:10:39 +02:00
|
|
|
|
var keyGenerator = new Rfc2898DeriveBytes(password, iv, Iterations);
|
|
|
|
|
return keyGenerator.GetBytes(keySize / 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|