Instantly share code, notes, and snippets.

Embed
What would you like to do?
Length-preserving Encryption
static void Main(string[] args)
{
Console.Write("Value: ");
var val = Console.ReadLine();
var b16 = Base16Decode(val);
byte[] key = null, iv = null;
RunAesCounter(ref key, ref iv, b16);
Console.WriteLine(Base16Encode(b16));
RunAesCounter(ref key, ref iv, b16);
Console.WriteLine(Base16Encode(b16));
Console.ReadLine();
}
static void RunAesCounter(ref byte[] key, ref byte[] iv, byte[] value)
{
var aes = new AesManaged();
if (key == null)
{
aes.GenerateKey();
key = aes.Key;
}
else
aes.Key = key;
if (iv == null)
{
aes.GenerateIV();
iv = aes.IV;
}
else
aes.IV = iv;
var enc = aes.CreateEncryptor();
for (var i = 0; i < value.Length; i += aes.BlockSize)
{
// Create and set the block data.
var block = new byte[aes.BlockSize];
Buffer.BlockCopy(BitConverter.GetBytes((long)(i + value.Length)), 0, block, 0, 8);
// Encrypt the block.
block = enc.TransformFinalBlock(block, 0, block.Length);
// value = value ^ block.
Xor(value, block, i);
}
}
static void Xor(byte[] target, byte[] xorWith, int offset)
{
var end = Math.Min(target.Length - offset, xorWith.Length);
for (var i = 0; i < end; i++)
target[i + offset] = (byte)(target[i + offset] ^ xorWith[i]);
}
static string Base16Encode(byte[] value)
{
if (value == null)
return null;
else if (value.Length == 0)
return string.Empty;
var result = new StringBuilder(value.Length * 2);
for (var i = 0; i < value.Length; i++)
result.Append(value[i].ToString("X2"));
return result.ToString();
}
static byte[] Base16Decode(string value)
{
if (value == null)
return null;
if (value.Length == 0)
return new byte[0];
if (value.Length % 2 != 0)
throw new ArgumentOutOfRangeException("value");
var result = new byte[value.Length / 2];
for (var i = 0; i < value.Length; i += 2)
{
var str = value.Substring(i, 2);
result[i / 2] = (byte)int.Parse(str, NumberStyles.HexNumber);
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment