Я хотел бы зашифровать в JavaScript, расшифровать в PHP, используя криптографию с открытым ключом. Я пытался найти библиотеки, которые могут это сделать, но у меня проблемы.
В настоящее время я смотрю openpgpjs , но мне нужна поддержка во всех браузерах, и даже на тестовой странице есть ошибки в списке только в браузере, поддерживаемом браузером (Google Chrome).
Заметки о конечной цели:
TCP-соединение уже защищено SSL. Основная цель этого уровня защиты – защита от преднамеренного или непреднамеренного ведения журнала веб-сервера, аварийных дампов и т. Д.
На стороне PHP будет создан временный закрытый ключ (он истечет через короткое время). Вызывающий (в Javascript) отвечает за запрос нового открытого ключа, когда он истекает. Причина истечения срока действия закрытого ключа заключается в предотвращении шифрования дешифрованных зашифрованных данных, если сервер, в котором хранится закрытый ключ, впоследствии скомпрометирован.
Сценарий с компрометацией серверов: кто-то получает резервные копии для всех машин, кроме сервера базы данных (и не может получить доступ к базе данных из-за брандмауэра, даже если он узнает пользователя и пароль). Поскольку закрытый ключ, который зашифровал зарегистрированные данные, больше не существует, злоумышленник ничего не может сделать.
Я использовал что-то подобное для моей страницы входа; он шифрует учетные данные для входа с использованием информации открытого ключа (N, e), которая может быть расшифрована в PHP.
Он использует следующие файлы, которые являются частью JSBN
:
jsbn.js
– работать с большими целыми числами rsa.js
– только для шифрования RSA (использует jsbn.js) rng.js
– основной сборщик энтропии prng4.js
– сервер prng4.js
RNG Для шифрования данных:
$pk = '-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----'; $kh = openssl_pkey_get_private($pk); $details = openssl_pkey_get_details($kh); function to_hex($data) { return strtoupper(bin2hex($data)); } ?> <script> var rsa = new RSAKey(); rsa.setPublic('<?php echo to_hex($details['rsa']['n']) ?>', '<?php echo to_hex($details['rsa']['e']) ?>'); // encrypt using RSA var data = rsa.encrypt('hello world'); </script>
Вот как вы могли бы декодировать отправленные данные:
$kh = openssl_pkey_get_private($pk); $details = openssl_pkey_get_details($kh); // convert data from hexadecimal notation $data = pack('H*', $data); if (openssl_private_decrypt($data, $r, $kh)) { echo $r; }
Проверьте узел-rsa .
Это модуль node.js
Этот модуль обеспечивает доступ к открытым ключам RSA из OpenSSL. Поддержка ограничена RSAES-OAEP и шифрование с помощью открытого ключа, дешифрование с помощью закрытого ключа.
Возможно, вы можете отправить его в браузере.
ОБНОВИТЬ
Библиотека клиентской стороны RSA для javascript: (pidcrypt был официально прекращен и домен веб-сайта истек – см. Ответ @ jack, который содержит те же библиотеки, что и pidcrypt) . https://www.pidder.com/pidcrypt/?page=rsa
Компонент на стороне сервера PHP: http://phpseclib.sourceforge.net/
Удачи!
Будьте осторожны с внедрением RSA. Фактически, вы, вероятно, не должны использовать RSA вообще. ( Вместо этого используйте libsodium! )
Даже если вы используете библиотеку (например, расширение OpenSSL на PHP напрямую или, до недавнего времени, Zend\Crypt
), все еще много, что может пойти не так. В частности:
Возможно, вы захотите прочитать криптографию JavaScript, считающуюся вредной, несколько раз, прежде чем идти по этому маршруту. Но это сказало …
crypto_box_seal()
с открытым ключом для шифрования ваших сообщений на стороне клиента. \Sodium\crypto_box_seal_open()
с соответствующим секретным ключом для открытого ключа для дешифрования сообщения. Пожалуйста, не надо . Криптография с эллиптической кривой быстрее, проще и намного проще реализовать без боковых каналов. Большинство библиотек делают это для вас уже. (Libsodium!)
Хорошо, следуйте этим рекомендациям в письме и не плачьте в StackOverflow, когда совершаете ошибку (например, SaltStack ), которая делает вашу криптографию бесполезной.
Один вариант (который не поставляется с дополнительной реализацией JavaScript, и, пожалуйста, не просите об этом), целью которого является обеспечение простого и простого шифрования RSA, является paragonie / easyrsa .
Но, действительно, если вы найдете допустимый вариант использования криптографии с открытым ключом, вместо этого вы хотите использовать libsodium.
Пример использования RSA для pidCrypt (js) и phpseclib (php).
Не используйте повторно закрытый ключ в этом рабочем примере.
Шифрование pidCrypt
//From the pidCrypt example sandbox function certParser(cert) { var lines = cert.split('\n'); var read = false; var b64 = false; var end = false; var flag = ''; var retObj = { }; retObj.info = ''; retObj.salt = ''; retObj.iv; retObj.b64 = ''; retObj.aes = false; retObj.mode = ''; retObj.bits = 0; for (var i = 0; i < lines.length; i++) { flag = lines[i].substr(0, 9); if (i == 1 && flag != 'Proc-Type' && flag.indexOf('M') == 0)//unencrypted cert? b64 = true; switch (flag) { case '-----BEGI': read = true; break; case 'Proc-Type': if (read)retObj.info = lines[i]; break; case 'DEK-Info:': if (read) { var tmp = lines[i].split(','); var dek = tmp[0].split(': '); var aes = dek[1].split('-'); retObj.aes = (aes[0] == 'AES') ? true : false; retObj.mode = aes[2]; retObj.bits = parseInt(aes[1]); retObj.salt = tmp[1].substr(0, 16); retObj.iv = tmp[1]; } break; case '': if (read)b64 = true; break; case '-----END ': if (read) { b64 = false; read = false; } break; default : if (read && b64)retObj.b64 += pidCryptUtil.stripLineFeeds(lines[i]); } } return retObj; } var strCreditCardPublicKey="-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC\/tI7cw+gnUPK2LqWp50XboJ1i\njrLDn+4\/gPOe+pB5kz4VJX2KWwg9iYMG9UJ1M+AeN33qT7xt9ob2dxgtTh7Mug2S\nn1TLz4donuIzxCmW+SZdU1Y+WNDINds194hWsAVhMC1ClMQTfldUGzQnI5sXvZTF\nJWp\/9jheCNLDRIkAnQIDAQAB\n-----END PUBLIC KEY-----\n"; var objParams=certParser(strCreditCardPublicKey); var binaryPrivateKey=pidCryptUtil.decodeBase64(objParams.b64); var rsa=new pidCrypt.RSA(); var asn=pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(key)); var tree=asn.toHexTree(); rsa.setPublicKeyFromASN(tree); var strHexSensitiveDataEncrypted=rsa.encrypt("4111111111111111"); var strBase64SensitiveDataEncrypted=pidCryptUtil.fragment(pidCryptUtil.encodeBase64(pidCryptUtil.convertFromHex(strHexSensitiveDataEncrypted)), 64)) console.log(strBase64SensitiveDataEncrypted);
,//From the pidCrypt example sandbox function certParser(cert) { var lines = cert.split('\n'); var read = false; var b64 = false; var end = false; var flag = ''; var retObj = { }; retObj.info = ''; retObj.salt = ''; retObj.iv; retObj.b64 = ''; retObj.aes = false; retObj.mode = ''; retObj.bits = 0; for (var i = 0; i < lines.length; i++) { flag = lines[i].substr(0, 9); if (i == 1 && flag != 'Proc-Type' && flag.indexOf('M') == 0)//unencrypted cert? b64 = true; switch (flag) { case '-----BEGI': read = true; break; case 'Proc-Type': if (read)retObj.info = lines[i]; break; case 'DEK-Info:': if (read) { var tmp = lines[i].split(','); var dek = tmp[0].split(': '); var aes = dek[1].split('-'); retObj.aes = (aes[0] == 'AES') ? true : false; retObj.mode = aes[2]; retObj.bits = parseInt(aes[1]); retObj.salt = tmp[1].substr(0, 16); retObj.iv = tmp[1]; } break; case '': if (read)b64 = true; break; case '-----END ': if (read) { b64 = false; read = false; } break; default : if (read && b64)retObj.b64 += pidCryptUtil.stripLineFeeds(lines[i]); } } return retObj; } var strCreditCardPublicKey="-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC\/tI7cw+gnUPK2LqWp50XboJ1i\njrLDn+4\/gPOe+pB5kz4VJX2KWwg9iYMG9UJ1M+AeN33qT7xt9ob2dxgtTh7Mug2S\nn1TLz4donuIzxCmW+SZdU1Y+WNDINds194hWsAVhMC1ClMQTfldUGzQnI5sXvZTF\nJWp\/9jheCNLDRIkAnQIDAQAB\n-----END PUBLIC KEY-----\n"; var objParams=certParser(strCreditCardPublicKey); var binaryPrivateKey=pidCryptUtil.decodeBase64(objParams.b64); var rsa=new pidCrypt.RSA(); var asn=pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(key)); var tree=asn.toHexTree(); rsa.setPublicKeyFromASN(tree); var strHexSensitiveDataEncrypted=rsa.encrypt("4111111111111111"); var strBase64SensitiveDataEncrypted=pidCryptUtil.fragment(pidCryptUtil.encodeBase64(pidCryptUtil.convertFromHex(strHexSensitiveDataEncrypted)), 64)) console.log(strBase64SensitiveDataEncrypted);
,
расшифровка phpseclib
require_once("Crypt/RSA.php"); function decrypt($strBase64CipherText) { //CRYPT_RSA_MODE_INTERNAL is slow //CRYPT_RSA_MODE_OPENSSL is fast, but requires openssl to be installed, configured and accessible. define("CRYPT_RSA_MODE", CRYPT_RSA_MODE_INTERNAL); $rsa=new Crypt_RSA(); //$strPrivateKey=file_get_contents("private.pem"); //This private key is for example purposes //DO NOT REUSE $strPrivateKey="-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDBNHK7R2CCYGqljipbPoj3Pwyz4cF4bL5rsm1t8S30gbEbMnKn 1gpzteoPlKp7qp0TnsgKab13Fo1d+Yy8u3m7JUd/sBrUa9knY6dpreZ9VTNul8Bs p2LNnAXOIA5xwT10PU4uoWOo1v/wn8eMeBS7QsDFOzIm+dptHYorB3DOUQIDAQAB AoGBAKgwGyxy702v10b1omO55YuupEU3Yq+NopqoQeCyUnoGKIHvgaYfiwu9sdsM ZPiwxnqc/7Eo6Zlw1XGYWu61GTrOC8MqJKswJvzZ0LrO3oEb8IYRaPxvuRn3rrUz K7WnPJyQ2FPL+/D81NK6SH1eHZjemb1jV9d8uGb7ifvha5j9AkEA+4/dZV+dZebL dRKtyHLfbXaUhJcNmM+04hqN1DUhdLAfnFthoiSDw3i1EFixvPSiBfwuWC6h9mtL CeKgySaOkwJBAMSdBhn3C8NHhsJA8ihQbsPa6DyeZN+oitiU33HfuggO3SVIBN/7 HmnuLibqdxpnDOtJT+9A+1D29TkNENlTWgsCQGjVIC8xtFcV4e2s1gz1ihSE2QmU JU9sJ3YeGMK5TXLiPpobHsnCK8LW16WzQIZ879RMrkeDT21wcvnwno6U6c8CQQCl dsiVvXUmyOE+Rc4F43r0VRwxN9QI7hy7nL5XZUN4WJoAMBX6Maos2Af7NEM78xHK SY59+aAHSW6irr5JR351AkBA+o7OZzHIhvJfaZLUSwTPsRhkdE9mx44rEjXoJsaT e8DYZKr84Cbm+OSmlApt/4d6M4YA581Os1eC8kopewpy -----END RSA PRIVATE KEY----- "; $strPrivateKey=preg_replace("/[ \t]/", "", $strPrivateKey);//this won't be necessary when loading from PEM $rsa->loadKey($strPrivateKey); $binaryCiphertext=base64_decode($strBase64CipherText); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); $strBase64DecryptedData=$rsa->decrypt($binaryCiphertext); return base64_decode($strBase64DecryptedData); } //The pidCrypt example implementation will output a base64 string of an encrypted base64 string which contains the original data, like this one: $strBase64CipherText="JDlK7L/nGodDJodhCj4uMw0/LW329HhO2EvxNXNUuhe+C/PFcJBE7Gp5GWZ835fNekJDbotsUFpLvP187AFAcNEfP7VAH1xLhhlB2a9Uj/z4Hulr4E2EPs6XgvmLBS3MwiHALX2fES5hSKY/sfSUssRH10nBHHO9wBLHw5mRaeg="; $binaryDecrypted=decrypt($strBase64CipherText); //should output '4111111111111111' var_export($binaryDecrypted);
Это основано на алгоритме Tiny Encryption Algorithm , который представляет собой симметричную (закрытый ключ) систему шифрования. Тем не менее он может быть вам полезен из-за его небольшого веса.
Это сейчас: http://babelfish.nl/Projecten/JavascriptPhpEncryption