ヴィジュネル暗号 を PHPで書く

2010年 03月 23日

    アルゴリズムの説明は、
    ヴィジュネル暗号
    ヴィジュネル暗号 を 数式で観る
    暗号解読に必要な計算量
    にも少し書いてあるので、をみてください。(プログラムを観る方が早いと思われ・・・)

    function.php

    <?php
    /**
     *
     * 暗号文の文字26、個A-Zを配列に格納
     *
     * 戻り値 : A-Z半角英小文字配列
    */
    function AsciiUp(){
    	for($i=65; $i<91; $i++){
    		$chr_code_up[] = chr($i);
    	}
    	return $chr_code_up;
    }
    /**
     *
     * 平文の文字26個、a-zを配列に格納
     *
     * 戻り値 : a-z半角英小文字配列
    */
    function AsciiLow(){
    	for($i=97; $i<123; $i++){
    		$chr_code_low[] = chr($i);
    	}
    	return $chr_code_low;
    }
    /**
     * ヴィジュネル暗号化
     *
     * $plain   : 平文
     * $enc     : 暗号化した結果を格納する配列
     * $key     : 鍵
    */
    function vigenere_cipher_encode($plain, $key){
    
    	$plain_len = strlen($plain); //平文の文字数
    	$key_len = strlen($key); //鍵の文字数
    
    	$plain = str_split($plain, 1); //平文を1文字ずつ配列に格納
    	$key = str_split($key, 1);  //鍵を1文字ずつ配列に格納
    
    	$up = AsciiUp();
    	$low = AsciiLow();
    
    	$s = 0;
    
    	for ($i=0; $i<$plain_len; $i++){
    		if(!preg_match("/^[a-zA-Z]+$/", $plain[$i])){
    			$enc.= $plain[$i];
    			$s += 1; //a-zA-Z意外のカウンタ
    		}else{
    			$pcn = array_search($plain[$i], $low);  //$low配列から平文の文字番号決定
    			$pcn = $pcn % 26; //平文の文字判別
    
    			$key_i = ($i - $s) % $key_len;
    			$ccn = array_search($key[$key_i], $up); //$up配列から鍵の文字番号決定
    
    			$p = ($pcn + $ccn) % 26; //暗号化文字の配列番号決定
    
    			$enc.= $up[$p]; //暗号化文字をつないでいく
    		}
    	}
    	return $enc;
    }
    
    /**
     * ヴィジュネル復号化
     *
     * $plain   : 暗号文
     * $enc     : 平文化した結果を格納する配列
     * $key     : 鍵
    */
    function vigenere_cipher_decode($plain, $key){
    
    	$plain_len = strlen($plain);
    	$key_len = strlen($key);
    
    	$plain = str_split($plain, 1);
    	$key = str_split($key, 1);
    
    	$up = AsciiUp();  //Ascii大文字
    	$low = AsciiLow();  //Ascii小文字
    
    	$s = 0;
    
    	for ($i=0; $i<$plain_len; $i++){
    		if(!preg_match("/^[a-zA-Z]+$/", $plain[$i])){
    			$enc.= $plain[$i];
    			$s += 1;
    		}else{
    			$pcn = array_search($plain[$i], $low);
    			$pcn = $pcn % 26; //平文の文字判別
    
    			$key_i = ($i - $s) % $key_len;
    			$ccn = array_search($key[$key_i], $up); //鍵の文字番号決定
    
    			if($pcn > $ccn){
    				$p = ($pcn - $ccn) % 26; //復号化文字の配列番号決定。差がプラスの場合
    			}else{
    				$p = (($pcn - $ccn) + 26) % 26; //復号化文字の配列番号決定。差がマイナスの場合
    			}
    			$enc.= $up[$p]; //暗号化文字をつないでいく
    		}
    	}
    	return $enc;
    }
    

    ここまでが暗号化と復号化のphpソース。(解らないことがあればコメントをplz)

    index.php

    <?php
    include('./function.php');
    
    if (!empty($_POST["plain"]) || !empty($_POST["key"])) {
    
    	$base_plain = $_POST["plain"];
    	$base_cryptogram = $_POST["cryptogram"];
    
    	//平文前処理
    	$plain = stripslashes(htmlspecialchars($_POST["plain"], ENT_QUOTES,"UTF-8"));  //エスケープ解除後HTML特殊文字適応
    	$plain = preg_replace("/(\015\012)|(\015)|(\012)/", "", $plain);  //改行削除
    	$plain = mb_convert_kana($plain, "as");  //全角英数スペースを半角にする
    	$plain = strtolower($plain);  //大文字を小文字に変換
    
    	//鍵前処理
    	$key = stripslashes(htmlspecialchars($_POST["key"], ENT_QUOTES,"UTF-8"));
    	$key = preg_replace("/(\015\012)|(\015)|(\012)/", "", $key);
    	$key = mb_convert_kana($key, "as");  //全角英数スペースを半角にする
    	$key = preg_replace("/\s/", "", $key);  //スペース削除
    	$key = strtoupper($key);  //小文字を大文字に変換
    	$base_key = $key;
    
    	if(!empty($_POST["plain"]) && !empty($_POST["key"])){
    		if(!empty($_POST["encode"])){
    			$base_cryptogram = vigenere_cipher_encode($plain, $key);
    			$cryptogram = $base_cryptogram;
    		}else{
    			$base_decode = vigenere_cipher_decode($plain, $key);
    			$cryptogram = $base_decode;
    		}
    	}
    }
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
    
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <style type="text/css">
    	body{background:#1b1b1b; font:13px Arial; color:#CCCCCC;}
    	a, a:link, a:visited {color:#A1AFFF; text-decoration:none;}
    </style>
    <title>ヴィジュネル暗号</title>
    </head>
    
    <body>
    
    <h1>ビジュネル暗号デモbeta</h1>
    <br />
    <fieldset>
    <legend>平文または暗号文を入力</legend>
    <form action="<?=$_SERVER["PHP_SELF"]?>" method="POST" name="cur">
    <textarea name="plain" cols="100" rows="60" style="width:640px;height:200px;"><?php echo $base_plain; ?></textarea>
    <br />
    鍵<br />
    <input type="text" name="key" size="100" value="<?php echo $base_key; ?>" />
    <br />
    <input type="submit" value="暗号化" name=encode /><input type="submit" value="復号化" name=decode />
    </form>
    </fieldset>
    <br />
    <fieldset>
    <legend>暗号化または復号化</legend>
    <textarea readonly="readonly" name="cryptogram" cols="100" rows="60" style="width:640px;height:200px;"><?php echo $cryptogram; ?></textarea>
    </fieldset>
    

    こんな感じでフォームと検索結果を作っておく。
    復号化に関しては、あくまで鍵が判っている上での復号化なので解読とは勘違いをしないでください。

    以上index.php,function.phpの2ファイルででヴィジュネル暗号(英文字)のみの暗号化ができると思います。

    ★☆★☆★☆ ナウでヤングなレンタルサーバー!ロリポップ! ☆★☆★☆★
    月額105円~容量最大30GB!WordpressやMovable Typeの簡単インストール付★

    Post a Comment