CryptoGear 暗号化アルゴリズム
CryptoGear は、BreakingSecurity によって開発された暗号化暗号です。
まともなレベルのセキュリティを提供しながら、シンプルで高速になるように設計されています。
無料でオープンソースでリリース。

 

主な特徴:

アルゴリズムの種類: 対称鍵ブロック暗号
操作モード: ECBCBC
ブロックサイズ: 4 バイト
キーサイズ: 最大 256 バイトまで
キーストリームのサイズ: 256 バイト
パディング: 自動処理

このブロック暗号は、パディングを自動的に処理します。
平文と暗号文のサイズは常に同じであり、ブロック サイズの倍数である必要はありません。

 

プロジェクトに含まれるもの:
  • GUI アプリケーション ( Delphi) ファイルの暗号化/復号化
  • ファイルの暗号化/復号化のためのコマンドライン アプリケーション (C++)
  • C ++の実装
  • Delphi 実装

 

説明:

回転する自転車の歯車のような CryptoGear メカニズムを想像できます。

  • 円形のギアがキーストリームであり、
  • 歯車の中を滑る鎖が暗号化されるデータです。

各歯車のコグとチェーン リングは、バイトを表現します。
したがって、256 歯の円形歯車 (キーストリーム サイズは 256 バイト) があります。
可能な長さのデータのチェーン。

  1. 暗号を初期化するとき、提供されたキーと初期化ベクトルに基づいて、一意のキーストリームが生成されます。
  2. 歯車がデータを渡すたびに、データが変更されます。
  3. CBC モードでは、バイトを暗号化するたびに、キーストリームの対応するバイトも変更されます。
    このように、各ラウンドでギア (キーストリーム) は前のものとは異なり、異なる方法でブロックを暗号化します (ブロック データが前のラウンドのものと同一であっても)。
    これに加えて、CBC モードでは、各ブロックは前のブロックと xor されます。

「クリプトギア」をダウンロード Delphi  CryptoGear-Delphi.zip – 2753 回ダウンロード – 251 KB

CryptoGear のソースと Delphi 完全なサンプル、ファイル クリプター。
任意のファイルを暗号化して保護することができ、同じキー、操作モード、および初期化ベクトルを使用している場合にのみ復号化できます。 

「CryptoGear C++」をダウンロード CryptoGear-C.zip – 1672 回ダウンロード – 65 KB

完全な 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.
メニュー