2014-02-03 3 views
3

У меня есть конечная точка PHP, которая используется несколькими сайтами. При отправке данных в конечную точку сайты используют зашифрованные заголовки для идентификации различной информации. Сайты используют стандартные функции PHP mcrypt_ecb и конечная точка расшифровывает переменную, как это:Javascript DES шифрование/расшифровка PHP

$var = trim(mcrypt_ecb(MCRYPT_DES, $key, base64_decode($input), MCRYPT_DECRYPT))); 

Я действительно не имею много шансов изменения PHP конечной точки, хотя я, вероятно, могу сделать другую конечную точку, если mcrypt_ecb Безразлично» т хорошо играть.

Теперь у меня есть приложение PhoneGap, которое также необходимо отправить зашифрованным заголовкам. Phonegap может реально использовать javascript для POST на удаленном сервере. Я просмотрел Google CryptoJS, чтобы попытаться добиться этого, наряду с базой библиотеки. Обратите внимание, что ключ совпадает с ключом $ key var.

var encrypted = CryptoJS.DES.encrypt(user.email, key).toString(); 
var base64 = base64.encode(encrypted); 

Проблема заключается в том, что зашифрованная строка (и я попытался без base64 кодирования/декодирования) при прохождении через mcrypt_ecb мусор. По-видимому, существуют разные методы тройного шифрования DES?

Как создать зашифрованную строку, совместимую с , в JavaScript?

+1

Пожалуйста, разместите свое разрешение в качестве ответа, а затем примите его. Благодарю. – deceze

+0

Будущие читатели: 1. DES - устаревшее объявление не защищено, оно было заменено AES, не используется в новой работе. 2. Не используйте режим ECB в новой работе и обновляйте устаревшую работу ASAP, она небезопасна, см. [Режим ECB] (https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29), прокрутите вниз Пингвину. Вместо этого используйте режим CBC со случайным IV, просто префикс зашифрованных данных с IV для использования в расшифровке, он не обязательно должен быть секретным. – zaph

+0

Будущие читатели: Лучше всего не использовать PHP mcrypt, он является отказом, не обновлялся годами и не поддерживает стандартные дополнения PKCS # 7 (née PKCS # 5), только нестандартное нулевое заполнение, которое не может даже использоваться с двоичными данными. В mcrypt много выдающихся [ошибок] (https://sourceforge.net/p/mcrypt/bugs/), начиная с 2003 года. Устаревшее mcrypt-расширение будет удалено в PHP 7.2. Вместо этого рассмотрите использование [defuse] (https://github.com/defuse/php-encryption) или [RNCryptor] (https://github.com/RNCryptor), они предоставляют полное решение и поддерживаются и верны. – zaph

ответ

0

Я использовал ту же библиотеку. Должен был убедиться, что результат des() был обрезан, так как после него появились нечетные символы, и он не соответствовал.

$password = trim(des("12345678", hexToString("1212121121"), 0, 1, null)); 

Надеюсь, что это поможет кому-то.

1

В соответствии с: http://php.net/manual/en/function.mcrypt-decrypt.php

Предупреждение Эта функция (Mcrypt-дешифрования) была устаревшей, так как PHP 7.1.0. Полагаться на эту функцию крайне не рекомендуется.

Затем мне пришлось много исследовать, пока не найду способ шифрования с помощью openssl через javascript и расшифровать с помощью php.

Единственная проблема, с которой я столкнулся, - это когда я отправляю длинный текст. Это потому, что RSA, по определению, поддерживает строки ограниченной длины.

https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security/33445#33445

RSA, как определено в PKCS # 1, шифрует "сообщения" ограниченного размера. С обычно используемым «дополнением v1.5» и 2048-битным RSA-ключом, максимальный размер данных, который может быть зашифрован с помощью RSA, составляет 245 байт. Больше не надо.

т.е. Если я использую private_key_bits из 1024 Я не могу отправить

"José compró en Perú una vieja zampoña. Excusándose, Sofía tiró su whisky al desagüe de la banqueta." 

ничего больше. Если я использую private_key_bits из 512 Я не могу отправить

"José compró en Perú una vieja zampoña. Excusánd" 

ничего больше.

На длинных строках JavaScript консоли отчеты: «Сообщение слишком долго для RSA»

Затем, если вы хотите, чтобы зашифровать длинные строки необходимо сжать и разделить их перед яваскриптом шифрования и после расшифровки присоединиться и распаковывать на PHP, я думаю, zlib - хорошее решение для split/join, потому что оно поддерживается на javascript и php.

Может быть, лучше использовать библиотеку AES вместо этого один, как https://github.com/brainfoolong/cryptojs-aes-php

Мой рабочий код выглядит следующим образом:

<?php 
    //------------------------------------------------------------ 
    // Global Settings. 
    //------------------------------------------------------------ 
    ini_set('display_errors', 1); 
    error_reporting(E_ALL); 
    $directorio = "/path/to/key/directory/apache/writable/"; 
    $nombre_base = "llaves_php"; 

    //------------------------------------------------------------ 
    // Initialization. 
    //------------------------------------------------------------ 
    $encabezado_html = ""; 
    $cuerpo_html = ""; 

    //------------------------------------------------------------ 
    // Loading keys 
    //------------------------------------------------------------ 
    list($privateKey, $pubKey) = 
     cargar_llaves_RSA($directorio, $nombre_base); 

    //------------------------------------------------------------ 
    // Form that uses javascript to encrypt data. 
    // (it uses only the public key) 
    //------------------------------------------------------------ 
    $librerias_html = " 
     <script type='text/javascript' 
       src='https://ajax.googleapis.com/ajax/libs/". 
        "jquery/3.2.1/jquery.min.js'></script> 
     <script type='text/javascript' 
       src='lib/jsencrypt.js'></script> 
     "; 

    $pubKey_html = htmlentities($pubKey); 
    $datos_html = " 
     <h2>Cifrando con Javascript</h2> 
     <input type='text' id='mensaje' /> 
     <br /> 
     <button id='ENVIAR'>Enviar</button> 
     <br /> 
     <textarea id='pubkey' style='display: none;'>". 
     $pubKey_html. 
     "</textarea> 
     <script type='text/javascript'> 
      $('#ENVIAR').click(function() { 
       var codificador = new JSEncrypt(); 
       codificador.setKey($('#pubkey').val()); 
       var cifrado = codificador.encrypt($('#mensaje').val()); 
       window.open('?mensaje=' + encodeURIComponent(cifrado) 
          , '_top'); 
      }); 
     </script> 
     "; 

    //------------------------------------------------------------ 
    // Decrypting using php (it uses only the privateKey) 
    //------------------------------------------------------------ 
    if (isset($_REQUEST['mensaje'])) { 
     openssl_private_decrypt(base64_decode($_REQUEST['mensaje']) 
           , $descifrado 
           , $privateKey); 
     $datos_html.= " 
      <h2>Descifrando con PHP</h2> 
      ".$descifrado." 
      "; 
    } 

    //------------------------------------------------------------ 
    // HTML DISPLAY 
    //------------------------------------------------------------ 
    $encabezado_html.= "<title>Receptor de mensaje cifrado</title>" 
        . $librerias_html; 

    $cuerpo_html.= $datos_html; 

    $contenido = "<head>$encabezado_html</head><body>$cuerpo_html</body>"; 
    $contenido = "<html>$contenido</html>"; 
    print $contenido; 

//============================================================ 
//============================================================ 
// Functions 
//============================================================ 
//============================================================ 

    //------------------------------------------------------------ 
    function cargar_llaves_RSA($directorio, $nombre_base) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: Genera o carga desde archivos las llaves RSA 
    // ENTRADAS: 
    // $directorio: Directorio donde se encuentran los archivos. 
    // $nombre_base: Nombre, sin extensión, de los archivos con 
    //    las llaves. 
    // SALIDAS: 
    //------------------------------------------------------------ 
     if ( !file_exists($directorio.$nombre_base.".crt") 
      || !file_exists($directorio.$nombre_base.".pub")) { 
      list($privateKey, $pubKey) = crear_llaves_RSA($directorio.$nombre_base); 
     } else { 
      //------------------------------------------------------------ 
      // CARGA DE LLAVES RSA ARCHIVADAS 
      //------------------------------------------------------------ 
      $privateKey = file_get_contents($directorio.$nombre_base.".crt"); 
     if (!$privKey = openssl_pkey_get_private($privateKey)) 
      die('Loading Private Key failed'); 
      $pubKey = file_get_contents($directorio.$nombre_base.".pub"); 
     } 

    return array($privateKey, $pubKey); 
    } 

    //------------------------------------------------------------ 
    function crear_llaves_RSA($ruta_base) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: 
    // generacion de llaves RSA en php 
    // ENTRADAS: 
    // $ruta_base: Ruta de los archivos a generar sin extensión. 
    // SALIDAS: 
    // Se generarán dos archivos, uno con la llave privada con 
    // extensión .crt, el otro con llave pública con extensión 
    // .pub; la función retorna tanto la llave pública como la 
    // privada en un arreglo. 
    //------------------------------------------------------------ 
     $config = array(
      "private_key_bits" => 1024, 
      "private_key_type" => OPENSSL_KEYTYPE_RSA, 
     ); 

     $llavePrivadaCruda = openssl_pkey_new($config); 
     openssl_pkey_export_to_file($llavePrivadaCruda, $ruta_base.".crt"); 
     $privateKey = file_get_contents($ruta_base.".crt"); 
     openssl_pkey_export($llavePrivadaCruda, $privKey); 

     $pubKeyData = openssl_pkey_get_details($llavePrivadaCruda); 
     $pubKey = $pubKeyData["key"]; 
     file_put_contents($ruta_base.".pub", $pubKey); 
     openssl_free_key($llavePrivadaCruda); 

    return array($privateKey, $pubKey); 
    } 

    //------------------------------------------------------------ 
    function Mostrar($valor) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: Genera el código HTML para presentar una 
    // variable embebida en la página. 
    // ENTRADAS: 
    // $valor: el valor a presentar. 
    // SALIDAS: código html que permite visualizar la variable. 
    //------------------------------------------------------------ 
     $retorno = htmlentities(stripslashes(var_export($valor, true))); 
     $retorno = "<pre>$retorno</pre>"; 
     return $retorno; 
    } 

?> 

Дерево каталогов сусло выглядит следующим образом:

├── script.php 
└── lib 
    └── jsencrypt.js 

и справочник, доступный для регистрации в php за пределами общественной зоны под названием

/path/to/key/directory/apache/writable/ 
0

Этот ответ был размещен как edit to the question Op. Хотя он запрошен post as an answer, он оставлен как отредактированный исходный вопрос.


Я решил эту проблему, используя другую библиотеку JavaScript шифрования. Вот как:

Я использовал более удобную библиотеку Paul Tero DES для javascript и стандартные функции расшифровки PHP.

Javascript:

var key = '12345678'; 
var encrypted = stringToHex(des(key, 'This is something private', 1)); 

Things отметить:

  • ключ должен (по-видимому) имеют четное число символов. Я использовал 8. Я думаю, что 16 или более было бы лучше, но, как вы, вероятно, можете сказать, я ничего не знаю о криптографии.
  • Функция stringToHex включена в код javascript.

PHP

$key = '12345678' 
$unencrypted = trim(mcrypt_decrypt(MCRYPT_DES 
            , $key 
            , safeHexToString($encrypted) 
            , MCRYPT_MODE_ECB)) 

Используя эту вспомогательную функцию:

/** 
* 
* Convert input HEX encoded string to a suitable format for decode 
* // Note: JS generates strings with a leading 0x 
* 
* @return string 
*/ 
function safeHexToString($input) 
{ 
    if(strpos($input, '0x') === 0) 
    { 
     $input = substr($input, 2); 
    } 
    return hex2bin($input); 
} 

Это сделал это для меня. Строки с шестнадцатеричным кодированием javascript, имеющие ведущее «0x», вызвали некоторые проблемы для меня, поскольку я отлаживался особенно глупо.

Так что я надеюсь, что это поможет.

Смежные вопросы