В данном посте буду вести речь о программной реализации Скремблера. О том что такое Scrambler (читается Скремблер) вы можете ознакомиться по следующим ссылкам:
Если кратко, то Скремблер предназначен для шифрования потока бит при передаче информации с возможностью расшифровать переданные данные зная ключ скремблера и его определение (полином).
Что интересно, в сети я не нашел подробных инструкций по реализации скремблера на каком-нибудь языку программирования
Сразу оговорюсь. Здесь приведу лишь реализацию генератора цикла псевдослучайной последовательности его исследование. Любая последовательность сгенерированная скремблером обладает свойствами цикличность, коррелированность и сбалансированность. Итак начнём.
Для начала объявим переменные и свойства которые нам пригодятся
int shiftRegister;// текущее содержимое скремблера
private int[] summators; // скремблер - массив степеней полинома
Random rnd;
public int key; // ключ скремблера
public int period; // период псевдосучайной последовательности
public int[] Cycles; // Число циклов
public bool IsBalansed; // Сбалансированность
public bool IsCycles; // Цикличность
// для исследования на корреляцию
public bool IsCorrelationed; // Коррелированность
public int CorMatch = 0; // число совпадений
public int CorMissMath = 0; // число несовпадений
public Scrembler(int[] summators)
{
Summator = summators;
}
public int[] Summator
{
get
{
return summators;
}
set {
if (value == null)
{
throw new Exception("Это не похоже на сумматор");
}
value.OrderByDescending(i => i);// Сортируем по убыванию
if (value.Min() < 1)
{
throw new Exception("Такой маленькой степени не может быть!");
}
if (value.Max() > 31)
{
throw new Exception("Такой большой степени не может быть!");
}
summators = value;
regenerateKey();
}
}Заметели незнакомую и странную функцию regenerateKey()? Она нужна для генерации ключа - одной из составляющих для генерации последовательности
private int keyGenerator()
{
int maxStepen = summators[0];
rnd = new Random();
int minKey = (int)Math.Pow(2, maxStepen - 1);
key = (int)(minKey + rnd.NextDouble() * (minKey - 1));
return key;
}
public void regenerateKey()
{
key = keyGenerator();
sequenceGenerator();
}И наконец сам метод генерации и исследования
public void sequenceGenerator()
{
shiftRegister = key;
int i;
int j;
int tmp;
List<int> history = new List<int>();
int min = (int)Math.Pow(2, summators[0] - 1);
int count = (int)Math.Pow(2, summators[0]);
List<bool> sequence = new List<bool>();
int cycleIndexStart = 0; // индекс в истории последовательностей с которого начинается цикл
for (i = 0; i < count; i++)
{
if (history.Contains(shiftRegister))
{
for (j = 0; j < history.Count; j++)
{
if (history[j] == shiftRegister)
{
cycleIndexStart = j;
break;
}
}
break; }
history.Add(shiftRegister);
tmp = shiftRegister << summators[0] - 1;
for (j = 1; j < summators.Length; j++)
{
tmp ^= shiftRegister << summators[j] - 1;
}
shiftRegister = (tmp & min) | (shiftRegister >> 1);
sequence.Add(true ? (shiftRegister & 1) == 1 : (shiftRegister & 1) == 0);
}
sequence.RemoveRange(0, cycleIndexStart);// Удаляем первые элементы последовательности не входящие в цикл
period = sequence.Count;
...Исследование.
// исследуем на сбалансированность
int countOfZero = 0;
int countOfUnion = 0;
for (i = 0; i < sequence.Count; i++)
{
if (sequence[i]) countOfUnion++;
else countOfZero++;
}
if ((countOfUnion - countOfZero) == 0 || (countOfUnion - countOfZero) == 1) IsBalansed = true;
// исследуем на цикличность
List<int> ciclesCounts = new List<int>();
List<bool> cicle = new List<bool>(); // Для хранении подряд идущих последовательностей 0 или 1
bool sign = sequence[0]; // начальный бит
int cycleLength = 0;
// Копируем последовательность
List<bool> csequence = sequence.GetRange(0, sequence.Count);
while (csequence.Count != 0)
{
for (i = 0; i < csequence.Count; i++)
{
if (sign) // в случае подряд идущих 1
{
if (csequence[i]) cicle.Add(csequence[i]);
else break;
}
else // 0
{
if (!csequence[i]) cicle.Add(csequence[i]);
else break;
}
}
// Тоже самое можно было получить используя LINQ
//IEnumerable<bool> cicle;
// в cicle вернется последовательность подряд идущих лог. 0 или лог. 1
//cicle = csequence.TakeWhile(i =>
//{
// if (sign)// в случае подряд идущих 1
// {
// if (i) return true;
// else return false;
// }
// else // 0
// {
// if (!i) return true;
// else return false;
// }
//});
cycleLength = cicle.Count();
//Элемент массива с индексом index соотвествует
// количеству подряд идущих лог. 1 или 0 длиной index+1
while (ciclesCounts.Count < cycleLength)
{
ciclesCounts.Add(0);
}
ciclesCounts[cycleLength - 1]++;
//меняем знак
sign = !sign;
//Удаляем часть последовательности
csequence.RemoveRange(0, cycleLength);
}
Cycles = ciclesCounts.ToArray();
// Проверка на Цикличность
int temp = 2;
IsCycles = false;
for (i = 0; i < Cycles.Length; i++)
{// получаем длину части последовательности: 1/2, 1/4, 1/8, ...
int tempResult = period / temp;
// Если число подряд идущих лог. 1 или 0 длинной i+1 равно длине части
// последовательности +-1, то последовательность обладает свойством цикличностью
if (Cycles[i] == tempResult || Cycles[i] == tempResult + 1 || Cycles[i] == tempResult - 1)
{
IsCycles = true;
}
else
{
IsCycles = false;
}
if (temp < period) temp *= temp;
else temp = period + 1; // сравнивать длину последовательности 1 или 0 с нулём бессмысленно
if (temp == 0) temp = period + 1; // в случае выхода значения temp за границы int
}
// исследуем на корреляцию
int sequenceLength = sequence.Count;
int corr = 0;
List<bool> copy = sequence.GetRange(rnd.Next(sequence.Count - sequenceLength), sequenceLength);
// Получаем копию посл-ти циклично сдвинутую вправо
List<bool> seq = copy.GetRange(0, copy.Count);
copy.Insert(0, copy[copy.Count - 1]);
copy.RemoveAt(copy.Count - 1);
CorMatch = 0;
CorMissMath = 0;
for (i = 0; i < copy.Count; i++)
{
if (seq[i] == copy[i])
{
corr++;
CorMatch++;
}
else
{
corr--;
CorMissMath++;
}
}
IsCorrelationed = corr < 2 && corr > -2 ? true : false;
}