Этот шифр принимает массив байтов и применяет относительно «случайное» смещение для каждого байта. Чтобы отслеживать смещения, чтобы можно было отменить шифрование, я решил не поддерживать список смещений, как в старых одноразовых блокнотах, и пошел с использованием модуля хеш-кода ключа, а затем перефразировал его. хеш. Чтобы увеличить сложность шифрования, я использовал 9-й бит хеша, чтобы установить направление смещения.
Смещения не являются действительно случайными, но зашифрованные байты текстового файла размером 2 МБ проходят все тесты в наборе тестов NIST.
class Cipher
{
private enum EncryptionMode
{
Encrypt = 1,
Decrypt = -1
}
public static byte[] Encrypt(string key, byte[] data)
{
return DeEncrypt(key, data, EncryptionMode.Encrypt);
}
public static byte[] Decrypt(string key, byte[] data)
{
return DeEncrypt(key, data, EncryptionMode.Decrypt);
}
private static byte[] DeEncrypt(string key, byte[] data, EncryptionMode mode)
{
if(key == null)
{
key = "";
}
if(data == null)
{
data = new byte[] { 0 };
}
ulong temp = HashCode(Encoding.ASCII.GetBytes(key));
var newData = new byte[data.Length];
for (int i = 0; i < data.Length; ++i)
{
newData[i] = GetNewValue(data[i], temp, mode);
temp = HashCode(BitConverter.GetBytes(temp));
}
return newData;
}
private static ulong HashCode(byte[] input)
{
var hash = Sha3.Sha3512().ComputeHash(input);
return BitConverter.ToUInt64(hash);
}
private static byte GetNewValue(byte value, ulong hash, EncryptionMode mode)
{
//This determines the direction of the offset based on the 9th bit in the hash
//and switches it according to the encryption mode.
var direction = (int)((((hash >> 8) & 1) * 2) - 1) * (int)mode;
var offset = (int)(ShiftMod256(hash)) * direction;
return (byte)ShiftMod256((ulong)(value + 256 + offset));
}
//Since only mod 256 is used I figured bit shifting would be better than division.
public static ulong ShiftMod256(ulong num)
{
return (num << 56) >> 56;
}
}
