php实现弗吉尼亚算法加密解密以及重合指数分析

哈工大密码学原理实验一:古典密码体制的实践与分析

实验项目描述:

Z26上的维吉尼亚密码体制:

(1)编写密钥为 (k1,k2,…,kn)维吉尼亚加、解密程序,其中n值由用户输入,密钥随机产生;

(2) (1)实现的加、减密程序对一段英文(其长度应较长 ) 加、密;

(3)针对(2),统计明文和密文中各字符出现的频率。要求给出 n=4,16 两种情况下的频率统计结果;

(4)针对(2),计算明文和密文的重合指数。要求给出 n=1,2,4,8,16,32,64, 128,256 几种情况下的计算结果。


<!-- virginia.php -->
<?php  

/***************  凯撒密码表 *************** 

        ABCDEFGHIJKLMNOPQRSTUVWXYZ 
        BCDEFGHIJKLMNOPQRSTUVWXYZA 
        CDEFGHIJKLMNOPQRSTUVWXYZAB 
        DEFGHIJKLMNOPQRSTUVWXYZABC 
        EFGHIJKLMNOPQRSTUVWXYZABCD 
        FGHIJKLMNOPQRSTUVWXYZABCDE 
        GHIJKLMNOPQRSTUVWXYZABCDEF 
        HIJKLMNOPQRSTUVWXYZABCDEFG 
        IJKLMNOPQRSTUVWXYZABCDEFGH 
        JKLMNOPQRSTUVWXYZABCDEFGHI 
        KLMNOPQRSTUVWXYZABCDEFGHIJ 
        LMNOPQRSTUVWXYZABCDEFGHIJK 
        MNOPQRSTUVWXYZABCDEFGHIJKL 
        NOPQRSTUVWXYZABCDEFGHIJKLM 
        OPQRSTUVWXYZABCDEFGHIJKLMN 
        PQRSTUVWXYZABCDEFGHIJKLMNO 
        QRSTUVWXYZABCDEFGHIJKLMNOP 
        RSTUVWXYZABCDEFGHIJKLMNOPQ 
        STUVWXYZABCDEFGHIJKLMNOPQR 
        TUVWXYZABCDEFGHIJKLMNOPQRS 
        UVWXYZABCDEFGHIJKLMNOPQRST 
        VWXYZABCDEFGHIJKLMNOPQRSTU 
        WXYZABCDEFGHIJKLMNOPQRSTUV 
        XYZABCDEFGHIJKLMNOPQRSTUVW 
        YZABCDEFGHIJKLMNOPQRSTUVWX 
        ZABCDEFGHIJKLMNOPQRSTUVWXY 

******************************************/  

// 生成输入长度的密钥
function makecode($num) { 
    $re = ''; 
    $s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    while(strlen($re)<$num) { 
        $re .= $s[rand(0, strlen($s)-1)]; 			// 从$s中随机产生一个字符 
    } 
    return $re; 
} 

// 弗吉尼亚算法加密
function v_encode($mstr, $mkey) {   
	$nstr = strtoupper($mstr);          			// 将明文转成大写 
	$nstr = str_replace(chr(32),'',$nstr);          // 去空格  
	$key = str_split($mkey);                        // 将密钥由字符串转成数组  
	$str = str_split($nstr);                        
	$keylen = count($key);                          // 计算密钥长度
	$strlen = count($str);                          
	$arr = array();  
	for( $i = 0; $i < $strlen; $i++) {  
    	$arr[$i] = chr(((ord($str[$i])-65) + (ord($key[$i%$keylen])-65))%26+65);      
	}  
	echo '原文加密:'."<br />";  
	echo '原文:'."<br />".$mstr."<br />";
	echo '密钥:'."<br />".$mkey."<br />";  
	echo '明文:'."<br />".$nstr."<br />"; 
	return $arr;
}

// 弗吉尼亚算法解密
function v_decode($ciphertext, $mkey){
	$key = str_split($mkey);                                           
	$keylen = count($key);                           
	$strlen = count($ciphertext);                          
	$arr = array();  
	for( $i = 0; $i < $strlen; $i++) {
		if(ord($ciphertext[$i]) >= ord($mkey[$i%$keylen])){
			$arr[$i] = chr(ord($ciphertext[$i]) - ord($mkey[$i%$keylen]) + 65);
		}  
		else {
			$arr[$i] = chr(ord($ciphertext[$i]) + 26 - ord($mkey[$i%$keylen]) + 65);
		}
	}  
	echo '<br />'.'<br />'.'密文解密:'.'<br />';
	echo '密文:'."<br />".implode("",$ciphertext).'<br />';    
	echo '密钥:'."<br />".$mkey."<br />";  
	echo '明文:'."<br />".implode("",$arr)."<br />"."<br />"; 
}

// 计算明文,密文重合指数
function computeOneIC($mstr,$flag){
	$strlen = count($mstr);
	$mstr = implode("", $mstr);
	$arr = array();
	$numerator = 0;
	for( $i = 0; $i <= 25; $i++){
		$arr[$i] = substr_count($mstr, chr($i+65));            // 统计每个字母在数组中出现个数
		$numerator += $arr[$i] * ($arr[$i] - 1); 
	}
	$denominator = $strlen * ($strlen - 1);
	$IC = $numerator / $denominator;
	if($flag){
		echo '明文重合指数:'.$IC.'<br />';
	}
	else{
		echo '密文重合指数:'.$IC.'<br />';
	}
}

// 通过计算重合指数算出密钥长度
function computeIC($ciphertext){
	$strlen = count($ciphertext);
	$k = 0;
	$IC = 0;
	$sum = 0;
	$arr = array();
	echo "<br />"."密钥长度    重合指数<br />";
	for( $length = 1; $length <= 256; $length++){                   // 密钥范围:1~256
		for( $i = 0; $i <= 25; $i++){
            $arr[$i] = 0;
		}
		for( $i = 0; $i < $strlen / $length; $i++){
			$narr[$i] = 0;
		}
		for( $head = 0; $head < $strlen; $head += $length){			// 根据密钥长度处理数组
			$arr[ord($ciphertext[$head])-65] += 1;
		}
		$numerator = 0;
		for( $i = 0; $i <= 25 ; $i++){
			$numerator += $arr[$i] * ($arr[$i] - 1);                   // 分子
		}
		$denominator = ($strlen / $length) * (($strlen / $length)-1);    // 分母
		$IC = $numerator / $denominator;
		echo $length.'--------->'.$IC.'<br />';
		if( $IC >= 0.064 && $IC <= 0.071){			
			echo "密钥长度:".$length.'<br />';
			for( $i = 1; $i <= $length; $i++){
				for( $j = 0; $j < $strlen; $j + $i){
					$narr[ord($ciphertext[$j])-65] += 1;	
				}
				$max = $narr[$k];
				for( $k = 0; $k <= 25; $k++){
					if( $narr[$k] > $max ){
						$max = $narr[$k];
					}
				}
				$onekey = cha(ord($max) - 69);
				echo $onekey;                      // 按位得出密钥
			}
			exit();
		}
	}
}

// 主程序
if(isset($_POST["sub"])){  
    $mkey = $_POST["data"]; 
    $mkey = intval($mkey);
    $mkey = makecode($mkey);
    $mstr = 'your input'; 		 //原文
    $ciphertext = v_encode($mstr, $mkey);  			// 加密
	echo '密文:'."<br />".implode("",$ciphertext);     
}

v_decode($ciphertext, $mkey);						// 解密
computeOneIC(str_split($mstr), 0);					// 原文重合指数
computeOneIC($ciphertext, 1);						// 密文重合指数
computeIC($ciphertext);								// 计算重合指数得出密钥长度

?>  

<!-- input.php -->
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Input.php</title>
</head>
<body>
	<form action="virginia.php" method="post" >
		<p>请输入密钥长度:</p>
        <input name="data" type="text" />
    	<input type="submit" name="sub" value="提交"/>
	</form>
</body>
</html>


    原文作者:维吉尼亚加密问题
    原文地址: https://blog.csdn.net/u012769750/article/details/44513035
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞