CryptoGear 加密算法
CryptoGear 是由 BreakingSecurity 开发的加密密码。
设计简单、快速,同时提供相当程度的安全性。
发布免费和开源。

 

主要特点:

算法类型:对称密钥分组密码
运营模式: 欧洲央行加拿大广播公司
块大小:4字节
密钥大小:最大 256 字节
密钥流大小:256 字节
填充:自动处理

这个分组密码会自动处理填充:
纯文本和密文的大小将始终相同,并且不需要是块大小的倍数。

 

项目包括:
  • GUI 应用程序(在 Delphi) 用于文件加密/解密
  • 用于文件加密/解密的命令行应用程序(C++ 中)
  • C ++实现
  • Delphi 履行

 

描述:

你可以把 CryptoGear 机制想象成一个旋转的自行车齿轮:

  • 圆形齿轮是关键流,
  • 穿过齿轮的链条是要加密的数据。

每个齿轮和链环代表一个字节。
所以我们有一个256齿的圆齿轮(密钥流大小为256字节),
以及任何可能长度的数据链。

  1. 初始化密码时,会根据提供的密钥和初始化向量生成唯一的密钥流。
  2. 每次齿轮传递数据时,数据都会发生变化。
  3. 在 CBC 模式下,每次加密一个字节时,密钥流的相应字节也会发生变化。
    这样,在每一轮中,齿轮(密钥流)将与前一轮不同,并且将以不同的方式加密块(即使块数据与前一轮相同)。
    除此之外,在 CBC 模式下,每个块都与前一个块进行异或运算。

下载“加密齿轮 Delphi= CryptoGear-Delphi.zip – 下载 2704 次 – 251 KB

CryptoGear 源和 Delphi 完整示例,文件加密器。
您可以加密任何文件来保护它,只有使用相同的密钥、操作模式和初始化向量才能解密它。 

下载“CryptoGear C++” CryptoGear-C.zip – 下载 1654 次 – 65 KB

完整的 C++ 项目,包括用于加密/解密文件的命令行工具。

C ++实现

加密齿轮.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);
};

加密齿轮.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.
菜单