シフト暗号の総当たり

まえがき

どうもです。お久しぶりです。

インターンや就職に提出するための技術的な話をする場が欲しいと思い、今日から定期的になんかしら書いていこうと思います。(ついでにMarkdownも慣れたい)

初回はシーザー及びシフト暗号です。(配属された研究室が暗号系だったので)

シーザー暗号

アルファベットで表記されたある文字列(以降平文)を3文字ずらすことで暗号化する。

例)

平文:abcdefg

暗号:DEFGHI

 

有名な奴です。ゲームやアニメなんかでも使われることがありますね。

実装も簡単ですが、有名なだけに突破もされやすいです。

シフト暗号

シーザー暗号の改良版。ずらす値を固定するのではなく、任意の数とする方法。

例)

平文:abcdefg

暗号:BCDEFGH

実装

総当たりでの復号の実装です。

#include <iostream>
#include <bits/stdc++.h>
#include <string>

using namespace std;

int main(void){
    string s;
    cout << "入力文字列:";
    cin >> s;
    cout << "復号文字列:" << endl;
    for(int i=0;i<26;i++){
        for(int j=0;j<s.size();j++){
            cout << char('a'+(s.at(j)-'A'+i)%26);
        }
        cout << endl;
    }
}

実行結果

f:id:Tsunamayomayo:20210430183058j:plain

解説

任意の文字列sについて、i文字ずつずらして表示するプログラムです。

アルファベットが26文字なのでそれを26回for文で回して総当たりします。

多分一番わかりづらいであろう以下の1行についてだけ解説します。

cout << char('a'+(s.at(j) - 'A' + i)%26);

s.at(j) - 'A' + i

暗号化された文字列のj文字目[s.at(j)]が「A」から何文字ずれているかを計算し、ずらす分の数字iを加算します。


'a'+(s.at(j) - 'A' + i)%26

加算した対象文字を26で割り、その余り分を'a'に加算することで、i文字分ずらして表示しています。


文字コードがわからん、って人はAtCoder あたりを見てください。

今回の場合、意味を成した文字列になっているのは「helloworld」、よって暗号化に使われた鍵は、ずれた文字数である「4」ですね。

あとがき

今回書くにあたって参考にした本:暗号技術のすべて

平文を小文字、暗号を大文字で書くとかって決まりがあるの、初めて知りました。そういやLinuxでauthorized_keysみたとき全部大文字だったなーなんてことを思い返しながら読んでました。

あとMarkdown、ちゃんと書くのは初めてだったんですが、正直よくわからんまま書き終えました。

まあこれから慣れていくでしょう。週に1本出せたらいいかなって感じのペースで更新していこうと思います。