Алгоритм шифрования CryptoGear
CryptoGear — это шифровальный шифр, разработанный BreakingSecurity.
Разработан, чтобы быть простым и быстрым, обеспечивая при этом достойный уровень безопасности.
Выпущено бесплатно и с открытым исходным кодом.

 

Основные характеристики:

Тип алгоритма: блочный шифр с симметричным ключом
Режимы работы: ЕЦБСи-би-си
Размер блока: 4 байта
Размер ключа: до 256 байт максимум
Размер ключевого потока: 256 байт.
Заполнение: автоматически обрабатывается

Этот блочный шифр автоматически обрабатывает заполнение:
размер обычного текста и зашифрованного текста всегда будет одинаковым и не обязательно должен быть кратным размеру блока.

 

Проект включает:
  • приложение с графическим интерфейсом (в Delphi) для шифрования/дешифрования файлов
  • Приложение командной строки (на C++) для шифрования/дешифрования файлов
  • Реализация C ++
  • Delphi реализация

 

Описание:

Вы можете представить механизм CryptoGear как вращающуюся шестерню велосипеда:

  • Круговая шестерня - это ключевой поток,
  • Цепь, которая скользит по шестеренке, — это данные, которые нужно зашифровать.

Каждое зубчатое колесо и цепное кольцо представляют собой байт.
Итак, у нас есть круглая шестерня с 256 зубьями (размер ключевого потока 256 байт),
и цепочка данных любой возможной длины.

  1. При инициализации шифра генерируется уникальный ключевой поток на основе предоставленного ключа и вектора инициализации.
  2. Каждый раз, когда зубчатая передача передает данные, данные изменяются.
  3. В режиме CBC соответствующий байт ключевого потока также изменяется каждый раз, когда он шифрует байт.
    Таким образом, в каждом раунде механизм (ключевой поток) будет отличаться от предыдущего и будет шифровать блок по-разному (даже если данные блока идентичны данным предыдущего раунда).
    Кроме того, в режиме CBC каждый блок связывается с предыдущим блоком.

Скачать «CryptoGear Delphi CryptoGear-Delphi.zip — Скачано 3050 раз — 251 КБ

Источник CryptoGear и Delphi полный образец, файловый шифровальщик.
Вы можете зашифровать любой файл, чтобы защитить его, а расшифровать его можно только при использовании того же ключа, режима работы и вектора инициализации. 

Скачать «CryptoGear C++» CryptoGear-C.zip — Скачано 1824 раз — 65 КБ

Полный проект C++, включает инструмент командной строки для шифрования/дешифрования файлов.

Реализация C ++

CryptoGear.h:

/*****************************************************************************\
*
*  CryptoGear Encryption Algorithm
*
*	Author: Viotto
*	Official website: Breaking-Security.Net
*
*	This algorithm and code can be freely used,
*	as long as you keep reference and credit to author and website.
*
******************************************************************************/


// Cipher Modes of operation:
#define MODE_ECB 0  // Electronic Codebook
#define MODE_CBC 1  // Cipher Block Chaining

class CCryptoGear
{
private:
	static const unsigned char m_InitializationVector = 0; // 0-255
	static const unsigned short m_lenKeystream = 256;
	unsigned char m_ModeOfOperation;
	unsigned char m_KeyStream[m_lenKeystream];

public:
	CCryptoGear(unsigned char* pKey, 
		unsigned int lenKey, 
		unsigned char ModeOfOperation = MODE_CBC,
		unsigned char InitializationVector = m_InitializationVector);

	CCryptoGear();

	void Initialize(unsigned char* pKey, unsigned int lenKey, 
		unsigned char ModeOfOperation = MODE_CBC,
		unsigned char InitializationVector = m_InitializationVector);

	void Encrypt(unsigned char pData[], unsigned long lenData);
	void Decrypt(unsigned char pData[], unsigned long lenData);
};

CryptoGear.cpp:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*****************************************************************************\
*
*  CryptoGear Encryption Algorithm
*
*	Author: Viotto
*	Official website: Breaking-Security.Net
*
*	This algorithm and code can be freely used,
*	as long as you keep reference and credit to author and website.
*
******************************************************************************/

#include <windows.h> // For memcpy
#include "CryptoGear.h"


//  Constructor.
CCryptoGear::CCryptoGear(unsigned char* pKey, unsigned int lenKey, unsigned char ModeOfOperation, unsigned char InitializationVector)
{
	Initialize(pKey, lenKey, ModeOfOperation, InitializationVector);
}


//  Overloaded costructor with no arguments.
//  Must manually initialize keystream.
CCryptoGear::CCryptoGear()
{}


//  Cipher Initialization.
//  Generates keystream and set mode of operation.
void CCryptoGear::Initialize(unsigned char* pKey, unsigned int lenKey, unsigned char ModeOfOperation,unsigned char InitializationVector)
{
	m_ModeOfOperation = ModeOfOperation;

	unsigned int i;

	for (i = 0; i < m_lenKeystream; i++)
	{
		m_KeyStream[i] = i + InitializationVector;
	}

	for (i = 0; i < m_lenKeystream; i++)
	{
		// xor initial keystream element value(0 - 255) with corresponding byte from key offset
		m_KeyStream[i] ^= (lenKey + pKey[i % lenKey]) % 256;
	}
}


void CCryptoGear::Encrypt(unsigned char pData[], unsigned long lenData)
{
	unsigned long Offset;
	unsigned char KeyStream[m_lenKeystream];

	//Create a local copy of the original KeyStream.
	memcpy(KeyStream, m_KeyStream, m_lenKeystream * sizeof(unsigned char));

	// Calculate padding
	unsigned char extra = lenData % 4;
	// If plain-text data size is not a multiple of block size,
	// then we must add a temporary padding (will be removed after finishing encrypting)
	if (extra)
	{
		extra = 4 - extra;
		lenData += extra;
		pData = (unsigned char*)realloc(pData, lenData);
	}

	//Encrypt the data.
	for (Offset = 0; Offset < lenData; Offset = Offset + 4)
	{
		pData[Offset]                 ^= KeyStream[Offset % m_lenKeystream];
		pData[(Offset + 1) % lenData] += (pData[Offset]                 + KeyStream[ (Offset + 1) % m_lenKeystream]) % 256;
		pData[(Offset + 2) % lenData] += (pData[(Offset + 1) % lenData] - KeyStream[ (Offset + 2) % m_lenKeystream]) % 256;
		pData[(Offset + 3) % lenData] += (pData[(Offset + 2) % lenData] ^ KeyStream[ (Offset + 3) % m_lenKeystream]) % 256;

		if (m_ModeOfOperation == MODE_CBC)
		{
			if (Offset > 0)
			{
				// xor block with previous block.
				pData[Offset]                 ^= (pData[(Offset - 4) % lenData]) % 256;
				pData[(Offset + 1) % lenData] ^= (pData[(Offset - 3) % lenData]) % 256;
				pData[(Offset + 2) % lenData] ^= (pData[(Offset - 2) % lenData]) % 256;
				pData[(Offset + 3) % lenData] ^= (pData[(Offset - 1) % lenData]) % 256;
			}

			// keystream elements used in this block are shifted. 
			// This way on next key round the corresponding keystream byte will be different.
			for (unsigned char i = 0; i < 4; i++)
			{
				KeyStream[(Offset + i) % m_lenKeystream] += pData[(Offset + i) % lenData] % 256;
			}
		}
	}

	// Remove padding.
	if (extra)
	{
		lenData -= extra;
		pData = (unsigned char*)realloc(pData, lenData);
	}
}


void CCryptoGear::Decrypt(unsigned char pData[], unsigned long lenData)
{
	unsigned char KeyStream[m_lenKeystream];
	unsigned long Offset;
	unsigned char a, b, c, d;
	unsigned char e, f, g, h;
	unsigned char i, j, k;

	//Create a local copy of the original keystream.
	memcpy(KeyStream, m_KeyStream, m_lenKeystream * sizeof(unsigned char));

	// Calculate padding
	unsigned char extra = lenData % 4;
	// If data size is not a multiple of block size,
	// then we must temporarely add padding (will be removed after finishing decryption)
	if (extra)
	{
		extra = 4 - extra;
		lenData += extra;
		pData = (unsigned char*)realloc(pData, lenData);
	}

	//Decrypt the data.
	for (Offset = 0; Offset < lenData; Offset = Offset + 4)
	{
		if (m_ModeOfOperation == MODE_CBC)
		{
			// Save original encrypted bytes, used for key shifting later
			a = pData[Offset];
			b = pData[(Offset + 1) % lenData];
			c = pData[(Offset + 2) % lenData];
			d = pData[(Offset + 3) % lenData];

			// Do from second cycle
			if (Offset > 0)
			{
				// xor block with previous block
				pData[Offset] ^= e % 256;
				pData[(Offset + 1) % lenData] ^= f % 256;
				pData[(Offset + 2) % lenData] ^= g % 256;
				pData[(Offset + 3) % lenData] ^= h % 256;
			}

			// Store encrypted bytes of this block for next cycle
			e = a;
			f = b;
			g = c;
			h = d;
		}

		// Save xored bytes (or original encrypted bytes if we are using ECB). 
		// With those we can shift back keystream operations and obtain clear-text.
		i = pData[Offset];
		j = pData[(Offset + 1) % lenData];
		k = pData[(Offset + 2) % lenData];

		pData[Offset]                 ^= KeyStream[Offset % m_lenKeystream];
		pData[(Offset + 1) % lenData] -= (i	+ KeyStream[(Offset + 1) % m_lenKeystream]) % 256;
		pData[(Offset + 2) % lenData] -= (j - KeyStream[(Offset + 2) % m_lenKeystream]) % 256;
		pData[(Offset + 3) % lenData] -= (k ^ KeyStream[(Offset + 3) % m_lenKeystream]) % 256;

		if (m_ModeOfOperation == MODE_CBC)
		{
			// Values of KeyStream elements used in this block are modified. 
			// This way on each key round the corresponding key byte will be different.
			KeyStream[Offset % m_lenKeystream]		 += a;
			KeyStream[(Offset + 1) % m_lenKeystream] += b;
			KeyStream[(Offset + 2) % m_lenKeystream] += c;
			KeyStream[(Offset + 3) % m_lenKeystream] += d;
		}
	}

	// Remove padding.
	if (extra)
	{
		lenData -= extra;
		pData = (unsigned char*)realloc(pData, lenData);
	}
}

Как использовать программу командной строки CryptoGear.exe:

cryptogear.exe direction key [mode] [iv] type target

  direction:
	-e to encrypt
	-d to decrypt

  key:
	your password

  mode (optional, default is CBC):
    -ECB
    -CBC

  iv: Initialization Vector. (optional, default is 0):
    -v 0-255
    Value can be a number in the range of 0-255.

  type:
	-s to encrypt string
	-f to encrypt file

  target:
	with -s option: input string
	with -f option: input file
---------------------------------------------------------

Examples:

cryptogear -e pass -f "C:\myfile.exe"                   // Encrypt file with password "pass"
cryptogear -d pass -f "C:\myfile.exe.encrypted"         // Decrypt file with password "pass"
cryptogear -e pass -ECB -v 10 -f "C:\myfile.exe"        // Encrypt with password "pass", using ECB mode and initialization vector 10
cryptogear -e pass -s Hello World                       // Encrypt string with password "pass"
Delphi реализация
unit uCryptoGear;

{*****************************************************************************
*
*  CryptoGear Encryption Algorithm v1.0
*  Delphi version
*
*	 Author: Viotto
*	 Official website: Breaking-Security.Net
*
*	 This algorithm and code can be freely used,
*	 as long as you keep reference and credit to author and website.
*
******************************************************************************}

interface

const
  MODE_ECB = 0;
  MODE_CBC = 1;
  g_lenKeystream = 256;

type
  TByteArray = array of Byte;

  CCryptoGear = class
  private
    m_KeyStream: array[0..g_lenKeystream-1] of Byte;
    m_InitializationVector: Byte;
    m_ModeOfOperation: Byte;
  public
    constructor Initialize(sKey: AnsiString; ModeOfOperation: Byte = MODE_CBC; InitializationVector: Byte = 0);
    procedure Encrypt(var pData: TByteArray); overload;
    procedure Decrypt(var pData: TByteArray); overload;
    function Encrypt(sData: AnsiString): AnsiString; overload;
    function Decrypt(sData: AnsiString): AnsiString; overload;
end;


implementation


constructor CCryptoGear.Initialize(sKey: AnsiString; ModeOfOperation: Byte = MODE_CBC; InitializationVector: Byte = 0);
var
  pKey: TByteArray;
  i, lenKey: Cardinal;
begin
  m_ModeOfOperation := ModeOfOperation;
  lenKey := Length(sKey);
  SetLength(pKey, lenKey);
  Move(sKey[1], pKey[0], lenKey);

  for i := 0 to g_lenKeystream - 1 do
  begin
    m_KeyStream[i] := (i + InitializationVector) mod 256;
  end;

  for i := 0 to (g_lenKeystream - 1) do
  begin
    // xor initial keystream element value(0 - 255) with corresponding byte from key offset
    m_KeyStream[i] := (m_KeyStream[i] xor (lenKey + pKey[i mod lenKey])) mod 256;
  end;
end;


function CCryptoGear.Encrypt( sData: AnsiString): AnsiString;
var
  pData: TByteArray;
  lenData: Cardinal;
begin
  lenData := Length(sData);
  SetLength(pData, lenData);
  Move(sData[1], pData[0], lenData);
  Encrypt(pData);
  SetString(sData, PAnsiChar(@pData[0]), lenData);
  Result := sData;
end;


function CCryptoGear.Decrypt( sData: AnsiString): AnsiString;
var
  pData: TByteArray;
  lenData: Cardinal;
begin
  lenData := Length(sData);
  SetLength(pData, lenData);
  Move(sData[1], pData[0], lenData);
  Decrypt(pData);
  SetString(sData, PAnsiChar(@pData[0]), lenData);
  Result := sData;
end;


procedure CCryptoGear.Encrypt( var pData: TByteArray);
var
  lenData, Offset: Cardinal;
  i: Cardinal;
  KeyStream: array[0..g_lenKeystream-1] of Byte;
  extra: Byte;
begin
  Offset := 0;
  lenData := Length(pData);

  //Create a local copy of the original KeyStream.
  for i := 0 to g_lenKeystream - 1 do
  begin
    KeyStream[i] := m_KeyStream[i];
  end;

  // Calculate padding
  extra := lenData mod 4;
  // If plain-text data size is not a multiple of block size,
  // then we must add a temporary padding (will be removed after finishing encrypting)
  if (extra > 0) then
  begin
    extra := 4 - extra;
    lenData := lenData + extra;
    SetLength(pData, lenData);
  end;

  //Encrypt the data.
  repeat
    pData[Offset]                   :=  pData[Offset] xor KeyStream[Offset mod g_lenKeystream];
    pData[(Offset + 1) mod lenData] := (pData[(Offset + 1) mod lenData] +  pData[Offset] + KeyStream[ (Offset + 1) mod g_lenKeystream]) mod 256;
    pData[(Offset + 2) mod lenData] := Byte(pData[(Offset + 2) mod lenData] + (pData[(Offset + 1) mod lenData] - KeyStream[ (Offset + 2) mod g_lenKeystream]) mod 256);
    pData[(Offset + 3) mod lenData] := (pData[(Offset + 3) mod lenData] + (pData[(Offset + 2) mod lenData] xor KeyStream[ (Offset + 3) mod g_lenKeystream])) mod 256;

    if (m_ModeOfOperation = MODE_CBC) then
    begin

      if (Offset > 0) then
      begin
      // xor block with previous block.
        pData[Offset]                   := (pData[Offset] xor pData[(Offset - 4) mod lenData]) mod 256;
        pData[(Offset + 1) mod lenData] := (pData[(Offset + 1) mod lenData] xor pData[(Offset - 3) mod lenData]) mod 256;
        pData[(Offset + 2) mod lenData] := (pData[(Offset + 2) mod lenData] xor pData[(Offset - 2) mod lenData]) mod 256;
        pData[(Offset + 3) mod lenData] := (pData[(Offset + 3) mod lenData] xor pData[(Offset - 1) mod lenData]) mod 256;
      end;

      // keystream elements used in this block are shifted.
      // This way on next key round the corresponding keystream byte will be different.
      for i := 0 to 3 do
      begin
        KeyStream[(Offset + i) mod g_lenKeystream] := Byte(KeyStream[(Offset + i) mod g_lenKeystream] + pData[(Offset + i) mod lenData] mod 256);
      end;
    end;
    Inc(Offset, 4);
  until Offset >= lenData;

  // Remove padding.
  if (extra > 0) then
  begin
    lenData := lenData - extra;
    setlength(pData, lenData);
  end;
end;


procedure CCryptoGear.Decrypt( var pData: TByteArray);
var
  KeyStream: array[0..g_lenKeystream-1] of Byte;
  lenData, Offset: Cardinal;
  extra     : Byte;
  a, b, c, d: Byte;
  e, f, g, h: Byte;
  i, j, k   : Byte;
begin
  Offset := 0;
  lenData := Length(pData);

  //Create a local copy of the original KeyStream.
  for i := 0 to g_lenKeystream -1 do
  begin
    KeyStream[i] := m_KeyStream[i];
  end;

  // Calculate padding
  extra := lenData mod 4;
  // If plain-text data size is not a multiple of block size,
  // then we must add a temporary padding (will be removed after finishing encrypting)
  if (extra > 0) then
  begin
    extra := 4 - extra;
    lenData := lenData + extra;
    SetLength(pData, lenData);
  end;

  //Decrypt the data.
  repeat

    if m_ModeOfOperation = MODE_CBC then
    begin
      // Save original encrypted bytes, used for key shifting later
      a := pData[Offset];
      b := pData[(Offset + 1) mod lenData];
      c := pData[(Offset + 2) mod lenData];
      d := pData[(Offset + 3) mod lenData];

      // Do from second cycle
      if (Offset > 0) then
      begin
        // xor block with previous block
        pData[Offset] :=  pData[Offset] xor e ;
        pData[(Offset + 1) mod lenData] := pData[(Offset + 1) mod lenData] xor f ;
        pData[(Offset + 2) mod lenData] := pData[(Offset + 2) mod lenData] xor g ;
        pData[(Offset + 3) mod lenData] := pData[(Offset + 3) mod lenData] xor h ;
      end;

      // Store encrypted bytes of this block for next cycle
      e := a;
      f := b;
      g := c;
      h := d;
    end;

    // Save xored bytes (or original encrypted bytes if we are using ECB).
    // With those we can shift back keystream operations and obtain clear-text.
    i := pData[Offset];
    j := pData[(Offset + 1) mod lenData];
    k := pData[(Offset + 2) mod lenData];

    pData[Offset]                   := pData[Offset] xor KeyStream[Offset mod g_lenKeystream];
    pData[(Offset + 1) mod lenData] := Byte(pData[(Offset + 1) mod lenData] - (i  + KeyStream[(Offset + 1) mod g_lenKeystream]) mod 256);
    pData[(Offset + 2) mod lenData] := Byte(pData[(Offset + 2) mod lenData] - (j  - KeyStream[(Offset + 2) mod g_lenKeystream]) mod 256);
    pData[(Offset + 3) mod lenData] := Byte(pData[(Offset + 3) mod lenData] - (k xor KeyStream[(Offset + 3) mod g_lenKeystream]) mod 256);

    if m_ModeOfOperation = MODE_CBC then
    begin
      // Values of KeyStream elements used in this block are modified.
      // This way on each key round the corresponding key byte will be different.
      KeyStream[Offset mod g_lenKeystream]       := Byte(KeyStream[Offset mod g_lenKeystream]       + a);
      KeyStream[(Offset + 1) mod g_lenKeystream] := Byte(KeyStream[(Offset + 1) mod g_lenKeystream] + b);
      KeyStream[(Offset + 2) mod g_lenKeystream] := Byte(KeyStream[(Offset + 2) mod g_lenKeystream] + c);
      KeyStream[(Offset + 3) mod g_lenKeystream] := Byte(KeyStream[(Offset + 3) mod g_lenKeystream] + d);
    end;
    Inc(Offset, 4);
  until Offset >= lenData;

  // Remove padding.
  if (extra > 0) then
  begin
    lenData := lenData - extra;
    setlength(pData, lenData);
  end;
end;


end.