Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
C++RAD Studio

C++Builderでビットシフトを使用したファイルのエンコード/デコードを行うには?

pexels negative space 97077 2

この記事は、Yılmaz Yörü氏のhttps://blogs.embarcadero.com/encoding-and-decoding-files-in-c-builder-by-using-bit-shifting/の抄訳です

最速のデータ符号化(エンコード)および復号化(デコード)方式とは?データを保護するための最速の方法は何ですか?データやファイルのエンコードやデコードにシフトを使うことはできますか?文字列やバイナリデータにシフトを使うことはできるのか?

このブログでは、それらの疑問にお答えいたします。

ビットとビットワイズ演算

ビットは、コンピュータやデジタル通信における情報の最も基本的な単位です。実際には、すべての演算子は主にビット演算に基づいており、「ビットワイズ演算子」とも呼ばれます。

コンピュータプログラミングでは、ビット文字列、ビット配列、または2進数(ビット文字列とみなす)を、個々のビット、1、0のレベルで操作することをビットワイズ演算と言います。ビット演算は、高レベルの算術演算の基本であり、プロセッサが直接サポートしているため、高速でシンプルな動作を実現しています。ほとんどのビット演算は、結果が入力オペランドの1つを置き換える 2オペランド命令として表されます。

このようなコンピュータのマイクロアーキテクチャの基本的な知識があるからこそ、ビット演算子を知っておくことは非常に重要なのです。C言語は最も古いプログラミング言語の一つで、他のプログラミング言語のオペランドや演算子の多くは、C言語からヒントを得ています。CとC++には同じ演算子があり、ほとんどの演算子は他のプログラミング言語でも同じです。一般的な演算子については、「C++の基礎: 演算子の使い方を学ぶ」をご覧ください。

それでは、ビットシフトとエンコード-デコードの例を見てみましょう。

データのビットシフト

ビット単位のオペランドの1つにビットシフトがあり、左シフトの’<<‘オペランドと右シフトの’>>‘オペランドがあります。ビット演算は、上述のようにコンピュータのマイクロアーキテクチャのため、マシンコードやC++では最も高速な演算です。多くのエンコードおよびデコード方法があり、ハッシュ符号化の方法もあります。最も簡単で高速な符号化(エンコード)方式の一つが「ビットシフトデータ」です。この方法は、データファイルのエンコードおよびデコードに利用できます。

左シフトと右シフト

例えば、cを文字とすると、ビットシフトを利用して以下のように文字のエンコードとデコードを行うことができます。

c = c << 1; // Encoding with Left Bit Shifting
c = c >> 1; // Decoding with Right Bit Shifting

このコード例は、127未満の文字数でうまく機能します。シフトする際に先頭のビットが失われます(左にシフトすると左のビットが、右にシフトすると右のビットが失われる)。これらのビットをすべてバイナリデータに保持するには、循環ビットシフト(Circular Bit Shifting)を行う必要があります。

循環左シフトと循環右シフト

循環ビットシフトを使用すれば、データのエンコードやデコードの際に、ビットを失うことはありません。最大8ビットのうち2ビットをシフトしたい場合は、以下のように左右の循環ビットシフトを行います。

c =(c << 2)|(c >> (8 - 2); // Encoding with Circular Left 2 Bits Shifting
c =(c >> 2)|(c << (8 - 2); // Decoding with Circular Right 2 Bits Shifting

複雑な循環左シフトと循環右シフト

例えば、(1+i%7)を加えることで、シフトするビット数に複雑性を与えることができます。

c =(c << (1+i%7))|(c >> (8 - (1+i%7)); // Encoding by Circular Left Bits Shifting with Complexity
c =(c >> (1+i%7))|(c << (8 - (1+i%7)); // Decoding by Circular Right Bits Shifting with Complexity

C++Builderでデータファイルをビットシフトする

例えば、C++Builderでデータファイルのエンコードとデコードを行うために、この「複雑な循環ビットシフト法」を使用することができます。C++Builderでこの例を実行するには、

1.C++Builder VCLプロジェクトを新規に作成し、すべてのファイルをプロジェクトフォルダに保存します。

2.TButtonコンポーネントを2つフォーム上に配置し、Button1->Caption = “Encode”、Button2->Caption = “Decode “に変更します。

3. TMemoとTOpenDialogコンポーネントをパレットからドラッグしてフォームに配置します。

4. F12を押してコードモードに切り替え、以下の例のようにコードにヘッダーを追加します。

//---------------------------------------------------------------------------
 
#include 
#include 
#include 
#include 
#pragma hdrstop
 
#include "Encoding_and_Decoding_Data_File_VCL_Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)  : TForm(Owner)
{
}

5. Button1の「Encode」ボタンをダブルクリックし、OnClickイベントハンドラに以下のような「エンコードファイルを開き、エンコードし、エンコードされたファイルを保存する」コードを実装します。

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) 
{
   // ENCODING 
   OpenDialog1->Title = "Choose a File to Encode";
   OpenDialog1->DefaultExt = "";
   OpenDialog1->FileName = "";
   OpenDialog1->Execute();
   if(OpenDialog1->FileName.Length()>0)
   {
	   unsigned char c;   // std::bitset<8> x;
	   unsigned int i=0;
 
	   std::ifstream indata;
	   std::ofstream outdata;
 
	   indata.open(OpenDialog1->FileName.w_str(), std::fstream::binary);
	   if(!indata)
	   {
		  Memo1->Lines->Add("Error: Input file could not be opened");
		  exit(1);
	   }
 
	   outdata.open((OpenDialog1->FileName+".enc").w_str(), std::fstream::binary);
	   if(!outdata)
	   {
		  Memo1->Lines->Add("Error: Output file could not be openedn");
		  indata.close();
		  exit(1);
	   }
 
	   Memo1->Lines->Add("nEncoding..n");
 
	   i=0;
	   while ( !indata.eof() )
	   {
		  c=indata.get();  // get the next char of data  or indata.get();
 
 
		  c =(c << (1+i%7))|(c >> (8 - (1+i%7)));  // Encoding by Circular Left Bit Shifting with Complexity
		  outdata.put(c); // out the encoded char
 
		  i++;
	   }
 
	   indata.close();
	   outdata.close();
 
	   Memo1->Lines->Add("Done! '"+OpenDialog1->FileName+".enc' saved!");
   }
}

6. Button2の「Decode」ボタンをダブルクリックし、OnClickイベントハンドラに以下のような「エンコードファイルを開き、デコードし、デコードされたファイルを保存する」コードを実装します。

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   OpenDialog1->Title = "Choose .enc File to Decode";
   OpenDialog1->DefaultExt = "";
   OpenDialog1->FileName ="*.enc";
   OpenDialog1->Execute();
   if(OpenDialog1->FileName.Length()>0)
   {
	   unsigned char c;   // std::bitset<8> x;
	   unsigned int i=0;
 
	   std::ifstream indata;
	   std::ofstream outdata;
 
		  // DECODING mytest.dat to mytest2.txt
	   // ---------------------------------------------------------
	   indata.open(OpenDialog1->FileName.w_str(), std::fstream::binary);
	   if(!indata)
	   {
		  Memo1->Lines->Add("Error: Input file could not be opened");
		  exit(1);
	   }
 
	   outdata.open((OpenDialog1->FileName+".dec").w_str(), std::fstream::binary);
	   if(!outdata)
	   {
		  Memo1->Lines->Add("Error: Output file could not be openedn");
		  indata.close();
		  exit(1);
	   }
 
 
	   i=0;
	   Memo1->Lines->Add("nDecoding..n");
	   while ( !indata.eof() )
	   {
		  c= indata.get();  // get the next char of data
		  //c = c >> 1; // Decoding with Right Bit Shifting
		  c =(c >> (1+i%7))|(c << (8 - (1+i%7)));  // Decoding by Right Bit Shifting with Complexity
		  outdata.put(c); // out the encoded char
 
		  i++;
	   }
 
	   indata.close();
	   outdata.close();
 
	   Memo1->Lines->Add("Done! '"+OpenDialog1->FileName+".dec' saved!");
   }
}

7. F9を押すと、プロジェクトをビルドし、デバッグ実行します。これでエンコードするファイルを選択し、*.encファイルをエンコードして、*.decファイルとしてデコードすることができます。

encodedecode 9801634 2

このビットシフト手法を使用して、データ、ユーザー名、パスワードなどの機密事項を保護することができます。また、このエンコードされたデータを暗号化ハッシュ関数(SHA、SHA2、MD5、BobJenkinsなど)を使ってハッシュ化することもできます。詳しくは「WindowsのモダンC++で強力な暗号化ハッシュ関数を学ぶ (SHA, SHA2, MD5, BobJenkins)」を参照ください。

RAD Studio 13.1 Florence Now Available See What's New in RAD Studio 13.1 Delphi is 31 - Webinar Replay

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES