2015-04-17 7 views
4

Я играю с Цезарем Шифром, и он, похоже, не работает.Caesar Cipher не работает, как ожидалось

Это мой код:

class CaesarCipher { 
    const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    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 

Может кто-нибудь дать мне подсказку, почему это не работает?

+0

вашего шифрования ISN» Правильно. –

+0

Что в этом плохого? – Cojones

+0

'T' не преобразуется в' 9', а вместо 'X'. –

ответ

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 :)

+0

Ницца, забыл об этом! – jeroen

3

Наиболее очевидной проблемой будет этот раздел из руководства по str_replace:

Внимание

заказ Замена Гоча

Поскольку str_replace() заменяет слева направо, его может заменить ранее вставленное значение при выполнении нескольких замен. См. Также примеры в этом документе.

Вы заменяете несколько символов несколько раз и это приводит к тому, что вы получаете результат.

Это относится как к шифрованию, так и к расшифровке, поэтому вы не можете использовать str_replace() с массивами, чтобы делать то, что вы хотите сделать.

Возможным решением было бы зашифровать (en decrypt ...) ваш строковый символ символом, чтобы вы только передавали каждый символ один раз.

+0

Я вижу, спасибо. Что было бы более подходящим тогда? – Cojones

+0

@Cojones Просто добавил последний абзац. Вы можете получить доступ к отдельному строковому символу, как если бы ваша строка была массивом, поэтому ее цикличность должна быть простой. – jeroen

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]; 
    } 
} 
+0

Это выглядит более эффективным, но также ли оно более эффективным, чем 'strtr'? – Cojones