Extra Systems Block Cipher

новый метод блочного шифрования


На этом сайте вниманию публики представлен новый метод блочного шифрования от компании Extra Systems. Автором этого изобретения является Юрий Павленко.

Размер блока — 8 на 8 байт, то есть — массив из 8-ми 64-битных чисел. То есть, фактически, этот метод разработан именно под нынешние 64-битные реалии.

В отличие от AES (у которого блок имеет размер 4 на 4 байта) сдвиг строк (процедуры «shift_encode» и «shift_decode») выполняется не по байтам, по битам. Причем, и в этом состоит еще одно важное новшество, эта операция производится и до, и после транспонирования матрицы (процедура «transpose_the_matrix»). Таким образом, перетасовка битов производится и по горизонтали, и по вертикали.

В соответствии с общепринятыми в настоящий момент в современной криптографии канонами (принцип Керкгоффса и максима Шеннона), ниже публикуется полный код Extra Systems Block Cipher (сокращенно - ESBC).


#define MATRIX_SIZE 8

#define STEP_LIMIT 32
#define SUB_STEPS 2
#define RC4_SKIP_TRASH 1587
#define XLAT_RANDOMIZE_STEPS 512

uint64_t the_matrix[MATRIX_SIZE];
uint64_t step_key[STEP_LIMIT][SUB_STEPS][MATRIX_SIZE];
unsigned int shift_key[STEP_LIMIT][SUB_STEPS][MATRIX_SIZE];
unsigned char xlat_encode_table[STEP_LIMIT][SUB_STEPS][256]
unsigned char xlat_decode_table[STEP_LIMIT][SUB_STEPS][256];
unsigned char shuffle_key[STEP_LIMIT][SUB_STEPS];

struct {      
     unsigned char state[256];       
     unsigned char x;        
     unsigned char y;
} rc4_key_table;

void swap_byte(unsigned char *a, unsigned char *b)
{
     unsigned char swapByte; 
     swapByte = *a; 
     *a = *b;      
     *b = swapByte;
}

void prepare_rc4_key(unsigned char *key_data_ptr, int key_data_len)
{
     unsigned char index1, index2;
     unsigned char* state;
     int counter;     
     state = rc4_key_table.state;         
     for(counter = 0; counter < 256; counter++) state[counter] = counter;               
     rc4_key_table.x = 0; rc4_key_table.y = 0;     
     index1 = 0; index2 = 0;             
     for(counter = 0; counter < 256; counter++)      
     {               
          index2 = (key_data_ptr[index1] + state[counter] + index2) & 255;                
          swap_byte(&state[counter], &state[index2]);            
          index1 = (index1 + 1) % key_data_len;  
     }       
}

unsigned char get_rc4_data(void)
{ 
	unsigned char x, y;
	unsigned char *state;
	unsigned char xorIndex;
	x = rc4_key_table.x; y = rc4_key_table.y;     
	state = rc4_key_table.state;         
	x = (x + 1) & 255;                      
	y = (state[x] + y) & 255;               
	swap_byte(&state[x], &state[y]);                        
	xorIndex = (state[x] + state[y]) & 255;                 
	rc4_key_table.x = x;     
	rc4_key_table.y = y;
	return state[xorIndex];
}

void reverse_xlat_table(unsigned char *encode_table, unsigned char *decode_table)
{
	int i;
	unsigned char src;
	for(i = 0; i < 256; i++)
	{
		src = encode_table[i];
		decode_table[src] = i;
	}
}

void make_key_data(unsigned char *key_data_ptr, int key_data_len)
{
	int i, j, k;
	unsigned char src, dst, x, y;
	unsigned char *step_key_array = (unsigned char *)step_key;
	prepare_rc4_key(key_data_ptr, key_data_len);
	for (i = 0; i < RC4_SKIP_TRASH; i++) get_rc4_data();
	for (i = 0; i < STEP_LIMIT; i++)
	{
		for (k = 0; k < SUB_STEPS; k++) while((shuffle_key[i][k] = get_rc4_data()) == 0 || shuffle_key[i][k] == 0xFF);
		for (k = 0; k < SUB_STEPS; k++)
			for (j = 0; j < MATRIX_SIZE; j++) while((shift_key[i][k][j] = get_rc4_data() & 63) == 0);
		for (k = 0; k < SUB_STEPS; k++)
			for (j = 0; j < 256; j++) xlat_encode_table[i][k][j] = j;
		for (k = 0; k < SUB_STEPS; k++)
		{
			for (j = 0; j < XLAT_RANDOMIZE_STEPS; j++)
			{
				x = j & 255;
			    while((y = get_rc4_data()) == x);
				src = xlat_encode_table[i][k][x];
				dst = xlat_encode_table[i][k][y];	
				xlat_encode_table[i][k][x] = dst;
				xlat_encode_table[i][k][y] = src;
			}
		}
		for (k = 0; k < SUB_STEPS; k++) reverse_xlat_table(xlat_encode_table[i][k], xlat_decode_table[i][k]);
	}
	for (i = 0; i < sizeof(step_key); i++) step_key_array[i] = get_rc4_data();
}

void shift_encode(uint64_t *the_matrix, unsigned int *key_set)
{
	int i;
	for (i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = (the_matrix[i] << key_set[i]) | (the_matrix[i] >> (64 - key_set[i]));
}

void shift_decode(uint64_t *the_matrix, unsigned int *key_set)
{
	int i;
	for (i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = (the_matrix[i] >> key_set[i]) | (the_matrix[i] << (64 - key_set[i]));
}

void add_step_key(uint64_t *the_matrix, uint64_t *the_key)
{
	int i;
	for (i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = the_matrix[i] + the_key[i];
}

void sub_step_key(uint64_t *the_matrix, uint64_t *the_key)
{
	int i;
	for (i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = the_matrix[i] - the_key[i];
}

void transpose_the_matrix(uint64_t *the_matrix)
{
	int i, j;
	uint64_t x[MATRIX_SIZE], y[MATRIX_SIZE];
	for (i = 0; i < MATRIX_SIZE; i++) y[i] = the_matrix[i];
	for (i = 0; i < MATRIX_SIZE; i++)
	{
		x[i] = 0;
		for (j = 0; j < MATRIX_SIZE; j++)
		{
			x[i] <<= 8;
			x[i] |= y[j] >> 56;
			y[j] <<= 8;
		}
	}
	for (i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = x[i];
}

void xlat_the_matrix(unsigned char *the_matrix, unsigned char *the_xlat_table)
{
	int i;
	for (i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) the_matrix[i] = the_xlat_table[the_matrix[i]];
}

void shuffle_the_matrix(unsigned char *the_matrix, unsigned char the_shuffle_key)
{
	int i, j;
	unsigned char x, y, swap_new;
	swap_new = ~the_shuffle_key;
 	for(i = 0; i < MATRIX_SIZE * MATRIX_SIZE / 2; i++)
	{
		j = MATRIX_SIZE * MATRIX_SIZE - i - 1;
		x = the_matrix[i];
		y = the_matrix[j];
		the_matrix[i] = (x & the_shuffle_key) | (y & swap_new);
		the_matrix[j] = (y & the_shuffle_key) | (x & swap_new);
	}
}

void twist_the_matrix(unsigned char *the_matrix)
{
	int i, j;
	unsigned char x, y;
 	for(i = 0; i < MATRIX_SIZE * MATRIX_SIZE / 2; i++)
	{
		j = MATRIX_SIZE * MATRIX_SIZE / 2 + i;
		x = the_matrix[i];
		y = the_matrix[j];
		the_matrix[i] = (x & 0xF0) | (y >> 4);
		the_matrix[j] = (y & 0xF) | (x << 4);
	}
}

void xor_line_encode(uint64_t *the_matrix)
{
	int i;
	uint64_t x[MATRIX_SIZE];
 	for(i = 0; i < MATRIX_SIZE; i++) x[i] = the_matrix[i];
 	for(i = 0; i < MATRIX_SIZE - 1; i++) x[i] ^= the_matrix[i + 1];
	x[MATRIX_SIZE - 1] ^= the_matrix[0];
 	for(i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = x[i];
}

void xor_line_decode(uint64_t *the_matrix)
{
	int i;
	uint64_t x[MATRIX_SIZE];
 	for(i = 0; i < MATRIX_SIZE; i++) x[i] = the_matrix[i];
	x[MATRIX_SIZE - 1] ^= the_matrix[0];
 	for(i = MATRIX_SIZE - 2; i >= 0; i--) x[i] ^= the_matrix[i + 1];
 	for(i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = x[i];
}

void add_matrix_line(uint64_t *the_matrix)
{
	int i;
	uint64_t x[MATRIX_SIZE];
 	for(i = 0; i < MATRIX_SIZE; i++) x[i] = the_matrix[i];
 	for(i = 0; i < MATRIX_SIZE - 1; i++) x[i] += the_matrix[i + 1];
	x[MATRIX_SIZE - 1] += the_matrix[0];
 	for(i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = x[i];
}

void sub_matrix_line(uint64_t *the_matrix)
{
	int i;
	uint64_t x[MATRIX_SIZE];
 	for(i = 0; i < MATRIX_SIZE; i++) x[i] = the_matrix[i];
	x[MATRIX_SIZE - 1] -= the_matrix[0];
 	for(i = MATRIX_SIZE - 2; i >= 0; i--) x[i] -= the_matrix[i + 1];
 	for(i = 0; i < MATRIX_SIZE; i++) the_matrix[i] = x[i];
}

void add_const(uint64_t *the_matrix, int i, int semi_step)
{
	int j;
	uint64_t c, d;
	c = (uint64_t)(i + semi_step + 1);
	c = c * c * c;
 	for(j = 0; j < MATRIX_SIZE; j++)
	{
		d = (uint64_t)(j + semi_step + 1);
		d = d * d * c;
		d *= d;
		d ^= (~d << 32);
		the_matrix[j] += d;
	}
}

void sub_const(uint64_t *the_matrix, int i, int semi_step)
{
	int j;
	uint64_t c, d;
	c = (uint64_t)(i + semi_step + 1);
	c = c * c * c;
 	for(j = 0; j < MATRIX_SIZE; j++)
	{
		d = (uint64_t)(j + semi_step + 1);
		d = d * d * c;
		d *= d;
		d ^= (~d << 32);
		the_matrix[j] -= d;
	}
}

void encode_matrix(void)
{
	int i;
	for (i = 0; i < STEP_LIMIT; i++)
	{
		add_const(the_matrix, i, 1);
		add_step_key(the_matrix, step_key[i][0]);
		twist_the_matrix((unsigned char *)the_matrix);
		xlat_the_matrix((unsigned char *)the_matrix, xlat_encode_table[i][0]);
		xor_line_encode(the_matrix);
		shift_encode(the_matrix, shift_key[i][0]);
		add_matrix_line(the_matrix);
		twist_the_matrix((unsigned char *)the_matrix);
		shuffle_the_matrix((unsigned char *)the_matrix, shuffle_key[i][0]);
		transpose_the_matrix(the_matrix);
		add_const(the_matrix, i, 2);
		add_step_key(the_matrix, step_key[i][1]);
		twist_the_matrix((unsigned char *)the_matrix);
		xlat_the_matrix((unsigned char *)the_matrix, xlat_encode_table[i][1]);
		xor_line_encode(the_matrix);
		shift_encode(the_matrix, shift_key[i][1]);
		add_matrix_line(the_matrix);
		shuffle_the_matrix((unsigned char *)the_matrix, shuffle_key[i][1]);
	}
}

void decode_matrix(void)
{
	int i;
	for (i = STEP_LIMIT - 1; i >= 0; i--)
	{
		shuffle_the_matrix((unsigned char *)the_matrix, shuffle_key[i][1]);
		sub_matrix_line(the_matrix);
		shift_decode(the_matrix, shift_key[i][1]);
		xor_line_decode(the_matrix);
		xlat_the_matrix((unsigned char *)the_matrix, xlat_decode_table[i][1]);
		twist_the_matrix((unsigned char *)the_matrix);
		sub_step_key(the_matrix, step_key[i][1]);
		sub_const(the_matrix, i, 2);
		transpose_the_matrix(the_matrix);
		shuffle_the_matrix((unsigned char *)the_matrix, shuffle_key[i][0]);
		twist_the_matrix((unsigned char *)the_matrix);
		sub_matrix_line(the_matrix);
		shift_decode(the_matrix, shift_key[i][0]);
		xor_line_decode(the_matrix);
		xlat_the_matrix((unsigned char *)the_matrix, xlat_decode_table[i][0]);
		twist_the_matrix((unsigned char *)the_matrix);
		sub_step_key(the_matrix, step_key[i][0]);
		sub_const(the_matrix, i, 1);
	}
}

© Extra Systems, 2026