Caesar Cipher未按预期运行

时间:2015-04-17 14:30:47

标签: php encryption caesar-cipher

我正在和Caesar Cipher一起玩,但似乎没有用。

这是我的代码:

class CaesarCipher {
  const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  protected $encrypt_sequence = array();
  protected $decrypt_sequence = array();

  public function __construct($seed = 1) {
      $total_chars = strlen(self::CHARS);
      $seed = $seed % $total_chars;
      for ($i = 0; $i < $total_chars; $i++) {
          $src = substr(self::CHARS, $i, 1);
          $dst = substr(self::CHARS, ($i + $seed) % $total_chars, 1);
          $this->encrypt_sequence[$src] = $dst;
          $this->decrypt_sequence[$dst] = $src;
      }
      $this->encrypt_sequence[' '] = ' ';
      $this->decrypt_sequence[' '] = ' ';
  }

  public function encrypt($value) {
      $value = strtoupper($value);
      return str_replace($this->encrypt_sequence, $this->decrypt_sequence, $value);
  }

  public function decrypt($value) {
      $value = strtoupper($value);
      return str_replace($this->decrypt_sequence, $this->encrypt_sequence, $value);
  }

  public function getEncryptSequence() {
      return $this->encrypt_sequence;
  }

  public function getDecryptSequence() {
      return $this->decrypt_sequence;
  }
}

运行它:

$seed = mt_rand(1, 35);
$cipher = new CaesarCipher($seed);
$source = 'THIS IS JUST A TEST WITH 123 NUMBERS';
$encrypted = $cipher->encrypt($source);
$decrypted = $cipher->decrypt($encrypted);

这是我的输出:

CAESAR CIPHER (seed=16)

Source:    THIS IS JUST A TEST WITH 123 NUMBERS
Encrypted: X12W 2W 3YWX U XYWX 02X1 567 7Y6VYVW   ENCRYPTED :)
Decrypted: DHIC IC JECD A DECD GIDH LMN NEMBEBC   DOES NOT MATCH SOURCE :(


Encryption: A>Q B>R C>S D>T E>U F>V G>W H>X I>Y J>Z K>0 L>1 M>2 N>3 O>4 P>5 Q>6 R>7 S>8 T>9 U>A V>B W>C X>D Y>E Z>F 0>G 1>H 2>I 3>J 4>K 5>L 6>M 7>N 8>O 9>P
Decryption: Q>A R>B S>C T>D U>E V>F W>G X>H Y>I Z>J 0>K 1>L 2>M 3>N 4>O 5>P 6>Q 7>R 8>S 9>T A>U B>V C>W D>X E>Y F>Z G>0 H>1 I>2 J>3 K>4 L>5 M>6 N>7 O>8 P>9

任何人都可以给我一个暗示,为什么它不起作用?

3 个答案:

答案 0 :(得分:3)

最明显的问题是str_replace手册中的这一部分:

  

<强>注意

     

更换订单

     

因为str_replace()从左到右替换,所以它可能会替换a   多次替换时先前插入的值。也可以看看   本文档中的示例。

您正在多次替换某些字符,这会导致您获得的结果。

这适用于加密和解密,因此您无法使用str_replace()数组来执行您想要执行的操作。

一种可能的解决方案是逐个字符地加密(解密...)你的字符串,这样你只能传递一次。

答案 1 :(得分:2)

知道了!

public function encrypt($value) {
    $value = strtoupper($value);
    return strtr($value, $this->encrypt_sequence);
}

public function decrypt($value) {
    $value = strtoupper($value);
    return strtr($value, $this->decrypt_sequence);
}

将正确地加密和解密该值。感谢jeroen和GoogleHireMe:)

答案 2 :(得分:0)

这是一种非常低效的方法,每个str_replace扫描每对的整个字符串。相反,为什么不扫描输入字符串并在加密/解密时计算替换。你问过提示而不是解决方案......但是这里有一个例子encrypt func(不需要构造,虽然可以存储构造种子而不是作为参数传入):

public function encrypt($value,$seed) {
    $n=strlen($value);
    $nchars=strlen(self::CHARS);
    for($i=0;$i<$n;$i++) {
        //This saves you doing the space-space replace, and allows 
        //  any chars not in your ciper to remain unmolested
        $pos=strpos(self::CHARS,$value[$i]);
        if ($pos>=0) $value[$i]=self::CHARS[($pos+$seed)%$nchars];
    }
}