アルゴリズムとデータ構造編【その他のアルゴリズム】 第3章 簡易的な暗号化

先頭へ戻る

このエントリーをはてなブックマークに追加

この章の概要

この章の概要です。

暗号化

暗号化とは、データを第三者に解読されないように変換することを言います。 逆に、暗号化されたデータを、元の形式に戻すことは復号化と言います。
また、暗号化されていない元のデータを平文(ひらぶん)と言い、 暗号化されたデータを暗号文と言います。

暗号化は、現代では、インターネットのようにデータ通信を行う際には必須の技術になっています。 また、通信を伴わないとしても、セキュリティ意識の高まりから、やはり必須の技術となっています。

この章では、暗号のアルゴリズムの中でも最も基礎的なものを紹介します。 非常に基礎的なものであって、現実的にはこの程度の暗号では信頼性は皆無に等しいと言えます。 ですから、重要なデータを暗号化する目的では使わないようにして下さい

信頼性のある高度な暗号化が必要ならば、十分な調査を行い、検討を重ねて下さい。 ほとんどの場合、恐らく自力で暗号化するという結論には至らないでしょう。

XOR暗号

XOR暗号は、XOR演算の性質を利用したごく簡単な暗号アルゴリズムです。

XOR演算の性質というのは、同じ演算を2回繰り返すと、元の値に戻るというものです(C言語編第49章参照)。
XOR演算を ^ で表すとすると、「A ^ B」の結果 C に対して、「C ^ B」とすると A に戻るということです。 ここで、A が平文、B が暗号の鍵、C が暗号文になります。
暗号のというのは、暗号アルゴリズムに渡すパラメータだと思えばいいです。 鍵は、暗号分野での一般的な用語です。

では、実際に試してみましょう。

#include <stdio.h>

int main(void)
{
	char buf[256];
	int data, key;


	puts( "元の値を入力して下さい。" );
	fgets( buf, sizeof(buf), stdin );
	sscanf( buf, "%d", &data );

	puts( "鍵となる値を入力して下さい。" );
	fgets( buf, sizeof(buf), stdin );
	sscanf( buf, "%d", &key );

	data ^= key;
	puts( "暗号結果は次のようになりました。" );
	printf( "%d\n", data );

	data ^= key;
	puts( "復号結果は次のようになりました。" );
	printf( "%d\n", data );
	
	return 0;
}

実行結果:

元の値を入力して下さい。
10000
鍵となる値を入力して下さい。
395
暗号結果は次のようになりました。
9883
復号結果は次のようになりました。
10000

XOR暗号の場合、暗号化に使う鍵と、復号化に使う鍵が同一であるという特徴があります。 これは、別の暗号アルゴリズムでは事情が異なる場合があり、両者が異なっているものもあります。

シーザ暗号

シーザ暗号(カエサル暗号)は、 平文の各文字を辞書順に何文字分かずらすことで暗号化を行います

例えば、平文が「ABC」のとき、5文字ずらすという方式でシーザ暗号を適用すると「FGH」になります。 「A」を辞書順(アルファベット順)に 5つずらすと「F」に、「B」は「G」に、「C」は「H」になるということです。
このような暗号化方式は、文字を他の文字置き換えることになるので、換字式暗号に分類されます。

では、実際に試してみましょう。

#include <stdio.h>
#include <string.h>

static void caesar_encryption(char* str, size_t len, int key);

int main(void)
{
	char data[256];
	char buf[32];
	int key;
	size_t len;


	puts( "元の文字列を入力して下さい。" );
	fgets( data, sizeof(data), stdin );

	puts( "鍵となる値を入力して下さい。" );
	fgets( buf, sizeof(buf), stdin );
	sscanf( buf, "%d", &key );

	len = strlen( data );

	caesar_encryption( data, len, key );
	puts( "暗号結果は次のようになりました。" );
	printf( "%s\n", data );

	caesar_encryption( data, len, -key );
	puts( "復号結果は次のようになりました。" );
	printf( "%s\n", data );
	
	return 0;
}

/*
	シーザ暗号

	引数:
		str:	暗号化(または復号化) する文字列。
		len:	引数str の文字列の長さ。
		key:	鍵。ずらす量を指定。

	引数str の内容が直接変更される。
*/
void caesar_encryption(char* str, size_t len, int key)
{
	size_t i;

	for( i = 0; i < len; ++i ){
		str[i] += key;
	}
}

実行結果:

元の文字列を入力して下さい。
acvky
鍵となる値を入力して下さい。
3
暗号結果は次のようになりました。
dfyn|
復号結果は次のようになりました。
acvky

caesar_encryption関数は、暗号化と復号化を兼ねています。 これは、実引数key の符号を反転させれば良いだけだからです。

caesar_encryption関数の第2引数に文字列の長さを渡していますが、ここには平文のときの長さを渡すように注意が必要です。 暗号化によって、平文の途中の文字が '\0' に置き換わる可能性があるため、 C言語では平文と暗号文の長さが不一致になる可能性があるからです。

まとめ

XOR暗号にせよ、シーザ暗号にせよ、非常に簡易的なアルゴリズムです。 最初に書いたように、重要なデータの暗号化に使おうとは思わないで下さい。


練習問題

問題① XOR暗号を、平文が整数でなく、文字列となるように実装して下さい。

問題② シーザ暗号の一種として ROT13 と呼ばれる暗号アルゴリズムがあります。 これは、平文に含まれるアルファベットを、辞書順で 13文字ずらし、「Z (z)」を超えてしまったら「A (a)」に戻ってくるルールになっています。 これを実装して下さい。


解答ページはこちら


参考リンク

更新履歴

'2015/2/21 サンプルプログラムで、ファイルスコープでよい関数に static を付加。

'2012/5/25 新規作成。



前の章へ

次の章へ

アルゴリズムとデータ構造編のトップページへ

Programming Place Plus のトップページへ