PHP实现凯撒加密算法

最近上信息安全的课,老师让写凯撒加密算法的实现,不限制语言于是就想着用PHP代码实现,具体问题描述如下:

问题描述:
     凯撒密码是把字母表中的每个字母用该字母后的某个字母进行代替。
     凯撒密码的通用加密算法是: C=E(P)=(P+k) mod 260<k<26。
     凯撒密码的通用解密算法是: P=D(C)=(P-k) mod 260<k<26。
基本要求:
     实现凯撒密码的加密、解密算法,能够根据用户选择秘钥 ( 移位数 ) 和明文进行加解密
实现提示:
     (1) 用户可以通过命令实现密钥和明文的选择;
    (2) 由于字母表中共有26个字符,因此,移位前应先将移动的位数(key)和26取模。
    (3) 尽管移位前已经将移动的位数和26取模,但是通过这种方式实现的右移和左移仍可能发生超界。因此,移位后仍要判断是否超界。

之前不知道如何判断移位超界的问题所以网上搜了一下,看到了一个Python写的感觉挺好的, 刚好自己也在学Python于是想着学习下就认真的看了看, 下面是网上的代码:
   
   
#License:GPL v3 or higher.
#Copyright (C) 2012 Biergaizi
import sys
times=0
plain=input("Please input your plain text: ")
value=input("Please input your key(included negatives): ")
secret_list=list(plain)
secret_list_len=len(secret_list)
try:
value=int(value)
except ValueError:
print("Please input an integer.")
sys.exit()
#a的ANSI码是97, z的ANSI码是122。
#A的ANSI码是65, Z的ANSI码是90。
print("")
print("secret: ",end='')
while times < secret_list_len:
times=times+1
#ansi_raw即没有经过任何处理的原始ANSI。
ansi_raw=ord(secret_list[0+times-1])
#ansi是经过移位加密的ANSI。
ansi=ansi_raw+int(value)
#word是用户输入的原始字符。
word=(secret_list[0+times-1])
#如果ansi_raw小于65或大于90,而且还不是小写字母,那么则说明它根本就不是字母。不加密,直接输出原始内容。
if (ansi_raw < 65 or ansi_raw > 90) and word.islower() == False :
print(word,end='')
#如果ansi_raw小于97或大于122,而且还不是大写字母,那么则说明它根本不是字母。不加密,直接输出原始内容。
elif (ansi_raw < 97 or ansi_raw > 122) and word.isupper() == False:
print(word,end='')
#否则,它就是字母。
else:
#如果它是大写字母,而且ANSI码大于90,则说明向后出界。那么通过这个公式回到开头,直到不出界为止。
while word.isupper() == True and ansi > 90:
ansi = -26 + ansi
#如果它是大写字母,而且ANSI码小于65,则说明向前出界。那么通过这个公式回到结尾,直到不出界为止。
while word.isupper() == True and ansi < 65:
ansi = 26 + ansi
#如果它是小写字母,而且ANSI码大于122,则说明向后出界。那么通过这个公式回到开头,直到不出界为止。
while word.isupper() == False and ansi > 122:
ansi = -26 + ansi
#如果它是小写字母,而且ANSI码小于97,则说明向前出界。那么通过这个公式回到结尾,直到不出界为止。
while word.isupper() == False and ansi < 97:
ansi = 26 + ansi
#将处理过的ANSI转换为字符,来输出密文。
print(chr(ansi),end='')
print("")
思路:
①加密的整体思路是不是字母的数字不进行加密,若是小写字母,对字母移位(ASCII +  秘钥 )后若ASCII码小于97或大于122则表示字母越界,只需要加26或减26直到移位后的在小写字母的范围内即可;同理大写字母也是相同的过程;
②解密的 整体思路 只需将移位后的的字母还原 (ASCII - 秘钥) ,其他步骤和加密一样。

有了思路接下来写PHP代码:
   
   
<?php
class Caesar{
 
private $simple;//明文
private $secretKey;//秘钥
private $ciphertext;//密文
private $opResult;//加密或解密后的结果
private $operatorType;//操作类型;0代表加密1:代表解密
 
/**
* __construct 构造函数初始化类属性
* @param String $input 输入字符内容
* @param integer $secretKey 秘钥
* @param integer $operatorType 操作类型;0代表加密1:代表解密
*/
public function __construct($input,$secretKey = 1,$operatorType = 0){
 
$this->operatorType = intval($operatorType);
if($this->operatorType == 0){
$this->simple = $input;
$this->ciphertext = "";
}elseif ($this->operatorType == 1) {
$this->ciphertext = $input;
$this->simple = "";
}else{
echo "please input right operatorType";
exit();
}
$this->opResult = "";
$this->secretKey = intval($secretKey);
}
 
 
/**
* crypto 解密或加密函数
* @return String 加解密后的结果
*/
public function crypto(){
 
//获取加密解密后的字符串
$charArray = ($this->operatorType==0) ? str_split ($this->simple) : str_split ($this->ciphertext);
//遍历整个字符数组进行加密解密操作
foreach ($charArray as $key => $value) {
$asciiOriginal = ord($value);//字符的ASCII值
$asciiTransfrom =($this->operatorType==0) ? $asciiOriginal+$this->secretKey : $asciiOriginal-$this->secretKey;//加解密后的ASCII的值
 
//值得注意的是||的优先级比&&的优先级低,若不加括号会造成问题;
//若不是大写字母并且$asciiOriginal的值小于65或大于90则不加密
if ( ($asciiOriginal<65 || $asciiOriginal > 90 ) && ($this->isLowerCase($value)==false)) {
$this->opResult .= $value;
 
//若不是大写字母并且$asciiOriginal的值小于97或大于122则不加密
}elseif ( ($asciiOriginal<97 || $asciiOriginal > 122) &&($this->isCapital($value)==false)) {
$this->opResult .= $value;
}else{
 
//循环处理越界的问题
while ($asciiTransfrom<65&&$this->isCapital($value)) {
$asciiTransfrom += 26;
}
 
while ($asciiTransfrom>90&&$this->isCapital($value)) {
$asciiTransfrom -= 26;
}
 
while ($asciiTransfrom<97&&$this->isLowerCase($value)) {
$asciiTransfrom += 26;
}
 
while ($asciiTransfrom>122&&$this->isLowerCase($value)) {
$asciiTransfrom -= 26;
}
}
$this->opResult .= chr($asciiTransfrom);
}
return $this->opResult;
}
 
/**
* isLowerCase 判断是否为小写字母
* @param char $char 传入的字符
* @return boolean 返回boolean类型
*/
private function isLowerCase($char){
if(preg_match("/^[a-z]+$/", $char)){
return true;
}else{
return false;
}
}
 
/**
* isCapital 判断是否为小写字母
* @param char $char 传入的字符
* @return boolean 返回boolean类型
*/
private function isCapital($char){
if(preg_match("/^[A-Z]+$/", $char)){
return true;
}else{
return false;
}
}
 
}
 
$string = $_SERVER['argv'][1];
if (!$string) {
echo "please input parameter";
}
$test = new Caesar($string,1,1);
echo $test->crypto();
?>

总结:
写代码的时候遇到了一个语法上的问题导致代码运行时总是有些误差,&&与||运算符优先级的问题,之前一直没有注意到, 这次发现&&的优先级比||高写条件判断的时候一定要小心和注意 ,之前在判断的地方没有加括号造成错误即错误代码如下:
   
   
if ( $asciiOriginal<65 || $asciiOriginal > 90 && ($this->isLowerCase($value)==false))
这句话会先执行&&判断,在执行||判断,容易造成错误。PHP官网关于优先级的描述: http://php.net/manual/zh/language.operators.precedence.php

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值