哈工大密码学原理实验一:古典密码体制的实践与分析
实验项目描述:
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>