【问题标题】:RSA Ciphering with JavaScript and Deciphering with php openssl使用 JavaScript 进行 RSA 加密和使用 php openssl 进行解密
【发布时间】:2016-02-25 11:58:48
【问题描述】:

我正在做一个登录系统。 我希望客户端加密(使用他的私钥)来自服务器的随机消息并将结果发送到服务器。然后服务器将使用公钥解密消息并进行比较。

我已经尝试过 jsencrypt。我有一个密码结果,但我不能使用 openssl_public_decrypt 解密,但它不工作

请指教或帮助!!!

这是完成 javascript 加密的文件

<?php


//Génération d'un message aleatoires
$i = 4;
global $bytes;
$bytes = openssl_random_pseudo_bytes($i, $cstrong);
$hex = pack('H*', bin2hex($bytes));;
$username = $_POST["username"];
$password = $_POST["password"];


echo '<!DOCTYPE html>
<html>
<head>
    <title>Accueil</title>
    <script language="javascript">
    function controle(form1, n) {
        if(n == 0){
            var pub = document.form1.clepub.value;
            var fso = new ActiveXObject("Scripting.FileSystemObject");
            // 2=overwrite, true=create if not exist, 0 = ASCII
            var varFileObject = fso.OpenTextFile(pub, 1, false, 0);
            //varFileObject.write("File handling in Javascript");
            var s = varFileObject.ReadAll();
            varFileObject.close();
            return s;
        }
        else{
            var priv = document.form1.clepriv.value;
            var fso = new ActiveXObject("Scripting.FileSystemObject");
            // 2=overwrite, true=create if not exist, 0 = ASCII
            var varFileObject = fso.OpenTextFile(priv, 1, false, 0);
            //varFileObject.write("File handling in Javascript");
            var s = varFileObject.ReadAll();
            varFileObject.close();
            return s;
        }
        //alert("La clé privée est : " + s);
    }
</script>
<script src="jquery-1.12.1.min.js"></script>
<script src="jsencrypt-master/bin/jsencrypt.js"></script>
<script language="javascript">
  function chiffrer()  {
        document.getElementById("testme").style.visibility="hidden";
      // Encrypt with the public key...
      var encrypt = new JSEncrypt();
      encrypt.setPublicKey(controle(form1, 1));
      //alert(controle(form1, 1));
      var encrypted = encrypt.encrypt("'.$hex.'");

      document.getElementById("submit").style.visibility="visible";

      document.getElementById("input").value = encrypted;
      //alert(encrypted);
      //document.getElementById("input").value = encryptedb64tohex(encrypted);
  }
</script>';
echo '</head>
<body>
<h1>Bienvenue sur TelGov</h1>
<h2>Engager votre clef privee</h2>
<form  action="compare.php" method="POST" name = "form1">
    <!--<label for="clepub">Engager votre clef publique</label>
    <input name="clepub" id="clepub" type="file"></input>
    <label for="clepriv">Engager votre clef privee</label>-->
    <input name="clepriv" id="clepriv" type="file"></input>
    <br/><br/>
    <input name="hash" id="hash" type="hidden" value="'.$hex.'"></input>
    <br/><br/>
    <input id="input" name="input" type="hidden" ></input><br/>
    <input id="testme" type="button" value="Engager" onclick="chiffrer()" /><br/>
    <input type="hidden" name="username" value="'.$username.'">
    <input type="hidden" name="password" value="'.$password.'">
    <!--<br/><br/>
    <input type="button" name="bouton" value="Controler" onClick="controle(form1)">
    <br/><br/>-->
    <input type="submit" id = "submit" value="Se connecter" style="visibility: hidden;"</input>
</form>
</body>

</html>';

?>

这是对比代码

<?php

try{
        $bdd = new PDO('mysql:host=localhost;dbname=authentification', 'root', '');
    }
    catch (Exception $e){
        die('Erreur : ' . $e->getMessage());
    }

$username = $_POST['username'];
$password = $_POST['password'];

$config = array(
                    "config" => "C:/wamp/bin/apache/apache2.4.9/conf/openssl.cnf",
                    "digest_alg" => "sha512",
                    "private_key_bits" => 1024,
                    "private_key_type" => OPENSSL_KEYTYPE_RSA,
                );

if(isset($_POST['input'])&&isset($_POST['hash'])){
    $crypt = $_POST['input'];
    $bon = $_POST['hash'];

    $cle = $bdd->prepare("SELECT publicKey FROM utilisateurs WHERE username =? AND password=?");
    $cle->execute(array($username, $password));
    $tmp = $cle->fetch();
    var_dump($tmp['publicKey']);
    var_dump($bon);
    //var_dump(openssl_private_decrypt(base64_decode($crypt), $decrypted, $tmp['privateKey']/*openssl_pkey_get_private($tmp['privateKey'], null)*/));
    var_dump(openssl_public_decrypt (base64_decode($crypt)/*$crypt*/, $decryted, $tmp['publicKey']));
    var_dump($decryted);
    var_dump(base64_decode($crypt));
    if($decryted == $bon){
        //header("Location:Accueil.php");
        echo "Bon";
    }
    else{
        //header("Location:index.php");
        echo "Mauvais";
    }

}
else{
    header("Location:index.php");
}

?>

这是比较结果

Image result from IE

【问题讨论】:

  • 你的问题是?
  • 你能给我一些建议吗?
  • 我试过 jsencrypt。我有一个密码结果,但我不能使用 openssl_public_decrypt 解密,但它不工作
  • 什么不起作用?给我们举个例子。
  • 在双方提供您的代码,以及任何错误日志、要加密/解密的数据样本、您使用的密钥、生成的加密数据、生成的解密数据以及任何其他相关细节。 “它不起作用”与您在不提供任何进一步细节的情况下告诉您的医生“它很痛”一样有用。

标签: javascript php


【解决方案1】:

我正在使用 Jsencrypt 库。 我发现无法使用 Jsencrypt 使用私钥加密并使用 php openssl 使用公钥解密。 所以我改变了我的方法,我使用了 Jsencrypt 的公钥加密和 php openssl 的解密。这个效果很好

【讨论】:

  • 按照设计加密是用公钥和私钥解密。考虑一下,如果公钥用于解密,每个人都可以解密消息,因为公钥不是秘密的。但也许您不需要密钥对(通常情况下),只需一个用于加密和解密的密钥,如果需要,请使用具有速度、简单性和无限数据长度优势的对称加密,例如 AES。
【解决方案2】:

我找到了这个 jsencrypt 库 (http://travistidwell.com/jsencrypt),经过 2 天的尝试,我得到了解决方案。

我遇到的唯一问题是发送长文本时。这是因为 RSA 根据定义支持长度有限的字符串。

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

按照 PKCS#1 的定义,RSA 对大小有限的“消息”进行加密。和 常用的“v1.5 padding”和一个 2048 位的 RSA 密钥,最大 可以使用 RSA 加密的数据大小为 245 字节。没有了。

即 如果我使用 1024 的 private_key_bits 我可以发送

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

没有了。 如果我使用 512 的 private_key_bits 我可以发送

"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/

【讨论】:

  • 1.这不是问题的答案。 2. 这不是使用 RSA 发送长消息的方式,RSA 不是为此而设计的,要么使用对称加密,例如 AES,要么如果需要密钥对,则使用加密数据的混合加密使用随机密钥进行对称加密,使用 RSA 加密密钥并将它们打包在一起。见Hybrid cryptosystem。 3. 请不要尝试发明自己的密码学,使用经过严格审查的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 2013-11-06
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 2018-08-17
相关资源
最近更新 更多