CryptoGear Encryption Algorithm
CryptoGear is an encryption cipher developed by BreakingSecurity.
Designed to be simple and fast, while providing a decent level of security.
Released free and open source.

 

Main Characteristics:

Algorithm type: symmetric-key block cipher
Modes of Operations: ECBCBC
Block size: 4 bytes
Key size: up to 256 bytes maximum
Keystream size: 256 bytes
Padding: automatically handled

This block cipher does automatically handle padding:
the size of plain-text and cipher-text will be always the same, and doesn’t need to be a multiple of the block size.

 

Project includes:
  • GUI application (in Delphi) for file encryption/decryption
  • Command-Line application (in C++) for file encryption/decryption
  • C++ implementation
  • Delphi implementation

 

Description:

You can imagine CryptoGear mechanism like a rotating bycicle gear:

  • The circular gear is the keystream,
  • The chain that slides though the gear is the data to be crypted.

Each gear cog and chain ring rapresents a byte.
So we have a circular gear with 256 teeth (keystream size is 256 bytes),
and a chain of data of any possible length.

  1. When initializing cipher, a unique keystream is generated, based on provided key and initialization vector.
  2. Each time a gear cog passes on the data, data gets changed.
  3. In CBC mode, the corresponding byte of the keystream gets changed as well each time it encrypts a byte.
    This way, on each round the gear (keystream) will be different from the previous one, and will crypt the block in a different way (even if block data is identical to the one of previous round).
    In addition to this, in CBC mode each block is xored with the previous block.

Download “CryptoGear Delphi” CryptoGear-Delphi.zip – Downloaded 1568 times – 251 KB

CryptoGear source and Delphi full sample, a file crypter.
You can encrypt any file to protect it, and it is possible to decrypt it only if using same key, mode of operation and initialization vector. 

Download “CryptoGear C++” CryptoGear-C.zip – Downloaded 1085 times – 65 KB

Full C++ project, includes command line tool to encrypt/decrypt files.

C++ implementation

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);
	}
}

How to use CryptoGear.exe command-line program:

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 implementation
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.
Menu