Я хотел бы зашифровать в Javascript, а затем расшифровать в PHP. Существуют реализации RSA для Javascript и PHP, но они несовместимы. Я не могу правильно расшифровать в PHP то, что я зашифровал с помощью Javascript.
Кто-нибудь знает библиотеку / код, который будет работать как с Javascript, так и с PHP?
Благодарю.
Вот библиотека шифрования JavaScript RSA: http://www.ohdave.com/rsa/
И я думаю, вы могли бы использовать что-то вроде этого класса для дешифрования сгенерированной зашифрованной строки – http://www.phpclasses.org/browse/package/4121.html
Дайте мне знать, если вам удастся выполнить эту работу вместе, поскольку я сам изучаю эту тему (я действительно нашел этот пост, который сам ищет этот ответ: P).
Edit: Послушайте, я также нашел это – http://www.sematopia.com/?p=275 – похоже, связано и с предыдущими двумя …
Попробуйте следующий простой пример.
Он использует библиотеку javascript с открытым исходным кодом https://github.com/ziyan/javascript-rsa
HTML / JavaScript:
<script language="JavaScript" type="text/javascript" src="jsbn.js"></script> <script language="JavaScript" type="text/javascript" src="rsa.js"></script> <script language="JavaScript"> function encryptData(){ //Don't forget to escape the lines: var pem="-----BEGIN PUBLIC KEY-----\ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfmlc2EgrdhvakQApmLCDOgP0n\ NERInBheMh7J/r5aU8PUAIpGXET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t\ 6rF4sYqV5Lj9t32ELbh2VNbE/7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaA\ U8bTnLEPMNC1h3qcUQIDAQAB\ -----END PUBLIC KEY-----"; var key = RSA.getPublicKey(pem); element=document.getElementById('password'); element.value=RSA.encrypt(element.value, key); } </script> <form method='POST' id='txtAuth' onsubmit='encryptData()'> <input type='text' name='username'/> <input type='password' name='password' id='password' placeholder="password"/> <input name='submit' type='submit' value='Submit'> </form>
PHP:
<?php if (isset($_POST['password'])) { //Load private key: $private = "-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDfmlc2EgrdhvakQApmLCDOgP0nNERInBheMh7J/r5aU8PUAIpG XET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t6rF4sYqV5Lj9t32ELbh2VNbE /7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaAU8bTnLEPMNC1h3qcUQIDAQAB AoGAcbh6UFqewgnpGKIlZ89bpAsANVckv1T8I7QT6qGvyBrABut7Z8t3oEE5r1yX UPGcOtkoRniM1h276ex9VtoGr09sUn7duoLiEsp8aip7p7SB3X6XXWJ9K733co6C dpXotfO0zMnv8l3O9h4pHrrBkmWDBEKbUeuE9Zz7uy6mFAECQQDygylLjzX+2rvm FYd5ejSaLEeK17AiuT29LNPRHWLu6a0zl923299FCyHLasFgbeuLRCW0LMCs2SKE Y+cIWMSRAkEA7AnzWjby8j8efjvUwIWh/L5YJyWlSgYKlR0zdgKxxUy9+i1MGRkn m81NLYza4JLvb8/qjUtvw92Zcppxb7E7wQJAIuQWC+X12c30nLzaOfMIIGpgfKxd jhFivZX2f66frkn2fmbKIorCy7c3TIH2gn4uFmJenlaV/ghbe/q3oa7L0QJAFP19 ipRAXpKGX6tqbAR2N0emBzUt0btfzYrfPKtYq7b7XfgRQFogT5aeOmLARCBM8qCG tzHyKnTWZH6ff9M/AQJBAIToUPachXPhDyOpDBcBliRNsowZcw4Yln8CnLqgS9H5 Ya8iBJilFm2UlcXfpUOk9bhBTbgFp+Bv6BZ2Alag7pY= -----END RSA PRIVATE KEY-----"; if (!$privateKey = openssl_pkey_get_private($private)) die('Loading Private Key failed'); //Decrypt $decrypted_text = ""; if (!openssl_private_decrypt(base64_decode($_POST['password']), $decrypted_text, $privateKey)) die('Failed to decrypt data'); //Decrypted :) var_dump($decrypted_text); //Free key openssl_free_key($privateKey); } ?>
Наслаждайтесь!
Если вы настроили сервер для использования SSL, вы можете зашифровать передачу через ajax с помощью https. Вероятно, это лучший способ шифрования данных между javascript и php. Если вы хотите сделать это самостоятельно, есть большая вероятность, что вы где-нибудь заблудитесь, и система не будет безопасной.
Google о том, как настроить https для вашего сервера.
Я предполагаю, что у вас есть веская причина сделать это иначе, чем делать сами https, поэтому я бы сказал, что если вы придерживаетесь стандартов, вы должны иметь возможность легко расшифровывать любую технологию, поддерживающую эти стандарты: то есть она должна работать
Например, если вы зашифруете свои данные в формате PKCS # 7, убедитесь, что ваша библиотека php знает, что входные данные являются PKCS # 7.
Также убедитесь, что ваш ключ шифрования не скремблирован между сервером и клиентом. Вы пытались расшифровать свои данные с помощью библиотеки javascript?
Надеюсь, это поможет …
Возможно, вы можете помочь, поставив код, который вы используете для js и php.
Кроме того, возможно, вы можете уточнить, почему вам нужно использовать js и php. Возможно, вы могли бы использовать только php и AJAX (для запроса той же функции php), где вы использовали js.
Я не из тех, кто хочет сделать свой собственный рог, но у меня есть проект на github.com, который будет выполнять эту функцию.
На сервере создается закрытый ключ, открытый ключ и сертификат pkcs # 7 также выводятся из закрытого ключа. Открытый ключ отправляется клиенту, и в это время каждый элемент формы, связанный с указанной формой, зашифровывается перед отправкой на сервер.
Он совместим с OpenSSL на 100%, поскольку он использует расширение OpenSSL PHP для генерации, шифрования и дешифрования данных.
https://github.com/jas-/jQuery.pidCrypt/
Этот проект не столь безопасен, как PGP, поскольку JavaScript не будет подписывать и шифровать электронные письма до тех пор, пока данные формы не будут отправлены на сервер, но данные формы, которые должны быть зашифрованы и / или подписаны, зашифрованы с использованием шифрования открытого ключа RSA до отправки к серверу.
Опять же, проект не является полным с точки зрения аутентификации и подписи электронной почты, но для обычного шифрования формы с использованием открытого ключа он работает очень хорошо.
Я нахожу эту библиотеку jsencrypt ( http://travistidwell.com/jsencrypt ), после 2 дней попытки получить свое решение.
Единственная проблема, которую я получил, – это когда я отправляю длинный текст. Это потому, что RSA, по определению, поддерживает строки ограниченной длины.
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»
Затем, если вы хотите зашифровать длинные строки, вы должны сжать и разбить их до шифрования javascript, а после дешифрования присоединиться и разогнать на php, я думаю, что zlib – хорошее решение для split / join, потому что оно поддерживается на javascript и 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/