MiracleJobLogo
エンジニアのエンジニアによるエンジニアのためのサイト
News 07/19 おすすめ情報に 『 【資格取得者速報】 Aさん 「 Microsoft Security, Compliance, and Identity Fundamentals」 』 を追加しました。
会員登録するとキャリア診断やサイトに参加することができます。
あなたにおすすめな技術情報、資格、仕事などをお知らせします。

無料会員登録


パスワードを忘れた場合
LINEで送る
MiracleJobBanaLeft1
MiracleJobBanaLeft2


PowerShellスクリプトでシーザー暗号を解読する
profile-img
投稿者: muto-sanさん
投稿日:2018/10/26 01:00
更新日:2018/10/26 01:06
like-img
分類
技術
テクノロジー
全般
キャリア
テクニカルサポート
投稿内容

面白そうな問題があったので、PowerShellを使って解いてみました。

練習問題 - プログラミングスレまとめ in VIP
Caesar暗号解読

※ シーザー暗号って何?って方はこちら

■問題
Caesar暗号を解読するプログラムを作り,暗号を解読してください。 暗号鍵(何文字ずらすか)は不明ですが、文字列に"person"が含まれることがわかっています。

■暗号文
"qdq-gi.q-a ziatmxxitmdqibtqi-ustbi ri.qmoqrcxi.qbubu zir -ibtqi-qp-qaai ripmymsqkir -ibtqi-qy dmxi ri.cnxuoi rruoumxakir -ibtqiqzmobyqzbkii-q.qmxi -imyqzpyqzbi rixmeaki -puzmzoqai -i-qscxmbu zaimzpir -i btq-iymbbq-a;iz -iatmxximzgi.q-a zinqiuzimzgiemgipuao-uyuzmbqpimsmuzabir -ia. za -uzsiacotiimi.qbubu zj" (最初と最後のダブルクォートは除く)

■使用される文字列
"abcdefghijklmnopqrstuvwxyz .,-" (ダブルクォートは除く。空白もあります。注意してください。暗号文にセミコロン";"が含まれています。これは置換するべき文字列に含まれていないので、そのままにしてください。)

最小単位の処理から考えてみる。
・入力
 1バイトの文字 a
・処理
 a が辞書に含まれる文字の場合、1つ後ろの文字に置換
・出力
 置換した文字 a

単一の文字に対して辞書順に1つずらす処理を行うスクリプトを作るとこんな感じ
=======<Read-Caesar_char.ps1>========
param(
    $char
)

# 使用する文字列
$dictionary = "abcdefghijklmnopqrstuvwxyz .,-"

if ($char -eq $dictionary[-1]){
    # 入力された文字が使用する文字列の最後の文字だった場合先頭の文字に置換
    $char = $dictionary[0]
}elseif ($dictionary.IndexOf($char) -eq -1){
    # 入力された文字が使用する文字列に含まれない場合処理をしない
}else{
    # それ以外の場合、文字を使用する文字列の1つ後の文字に置換
    $char = $dictionary[($dictionary.IndexOf($char) + 1)]
}

Write-Output $char
=======<Read-Caesar_char.ps1>========


次はforステートメントを使って文字列に対して行う

=======<Read-Caesar_word.ps1>========
param(
    $word
)

# 使用する文字列
$dictionary = "abcdefghijklmnopqrstuvwxyz .,-"

# 入力された文字列を配列に変換
$word = $word.ToCharArray()

for ($i=0; $i -lt $word.Length; $i++){
    if ($word[$i] -eq $dictionary[-1]) {
        # 文字が使用する文字列の最後の文字だった場合先頭の文字に置換
        $word[$i] = $dictionary[0]
    }elseif ($dictionary.IndexOf($word[$i]) -eq -1){
        # 文字が使用する文字列に含まれない場合処理をしない
    }else{
        # それ以外の場合、文字を使用する文字列の1つ後の文字に置換
        $word[$i] = $dictionary[$dictionary.IndexOf($word[$i])+1]
    }
}

# 変換した配列を文字列に戻す
$word = $word -join ""

Write-Output $word
=======<Read-Caesar_word.ps1>========


あとはWhile文で以上の処理を特定のキーワードを含むまで繰り返すようにすればOK
=======<Read-Caesar_text.ps1>========
param(
    $text,
    $key
)

# 使用する文字列
$dictionary = "abcdefghijklmnopqrstuvwxyz .,-"

# 置換した回数カウント用変数
$shiftCount = 0

# whileを使ってキーワードを含むまで繰り返し実行
while ($text.Contains($key) -eq $False){
    # 入力された暗号文を配列に変換
    $text = $text.ToCharArray()
    for ($i=0; $i -lt $text.Length; $i++){
        if ($text[$i] -eq $dictionary[-1]) {
            # 文字が使用する文字列の最後の文字だった場合先頭の文字に置換
            $text[$i] = $dictionary[0]
        }elseif ($dictionary.IndexOf($text[$i]) -eq -1){
            # 文字が使用する文字列に含まれない場合処理をしない
        }else{
            # それ以外の場合、文字を使用する文字列の1つ後の文字に置換
            $text[$i] = $dictionary[$dictionary.IndexOf($text[$i])+1]
        }
    }
    # 変換した配列を文字列に戻す
    $text = $text -join ""
    # 置換した回数カウント
    $shiftCount++
}

Write-Output "暗号文を $shiftCount 回置換しました。"
Write-Output $text
=======<Read-Caesar_text.ps1>========


めでたしめでたし。

■オマケ
出力の方法を調整するとこんなことも。


うーん目がチカチカする


コメント


MiracleJobBanaRight1
MiracleJobBanaRight2
MiracleJobBanaRight3