最新公告
  • 欢迎访问代码工坊,购买产品可享受在线工单服务!
  • 前端登录密码JS加密,后端PHP解密的非对称RSA加解密方案

      前端登录信息一般通过post方式提交,这其中账号密码一般明文传输,在开启了https的情况下安全性没有太大问题。

      但对于一些比较大的平台,或网站经常需要在不安全网络下使用,在传输过程中仍然有被截获数据的可能性,这些信息用来定向攻击或被用来组成彩虹表进行撞库破解。

      比如前些年一些比较著名的bbs平台,会有不法分子大规模攻击控制无线网络,并通过截取相关平台的登录信息,继而登录该平台发布违法信息用于诈骗。

    前端登录密码JS加密,后端PHP解密的非对称RSA加解密方案

      在登录过程中对密码等明文信息加密传输是个比较流行的解决办法,一般采用RSA非对称加密算法,通过RSA密钥对将公钥、私钥分开存储,公钥用于前端加密,私钥用于后端解密。

    前端登录密码JS加密,后端PHP解密的非对称RSA加解密方案

    实施过程:

    1、前端引入加密库jsencrypt.js(https://github.com/travist/jsencrypt)。

    2、生成一份RSA密钥对,公钥放置于前端可访问位置,可以是文件,也可以是页面变量。后端要加密存储严防泄露。

    公钥:

    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhXzH9nldFX03YmKChOtQ
    3L3sEmfBoNQpuLUblZUP/gvgbJNsLvOXbP17jAsNz6hMtAHcU3BZd1ihL8p4al1M
    mg0FH07GPHrpcuaOyYm6DvZi+VmLCE0lOTOTSlB8xlq3E1G8sRNXj3B/PRA2T0Ia
    WgYWke9DNfKO34SfphtRig3rp2GFk+QSPBd4WJvApwIoh8kNQvls+69A1TJPzio6
    F2+dZRF3GxeSuc1YnSli15OYujQZ9t1zTI9h7yhXPfbqayf8y4ktD+bRi8anOR1A
    7U6pawjf51hnWhuts0w6cEHQwu5yvs3PMSasgOM8BQs3yPrn8os7aC8ssGOfDdaI
    twIDAQAB
    -----END PUBLIC KEY-----

    私钥:

    -----BEGIN RSA PRIVATE KEY-----
    MIIEpAIBAAKCAQEAhXzH9nldFX03YmKChOtQ3L3sEmfBoNQpuLUblZUP/gvgbJNs
    LvOXbP17jAsNz6hMtAHcU3BZd1ihL8p4al1Mmg0FH07GPHrpcuaOyYm6DvZi+VmL
    CE0lOTOTSlB8xlq3E1G8sRNXj3B/PRA2T0IaWgYWke9DNfKO34SfphtRig3rp2GF
    k+QSPBd4WJvApwIoh8kNQvls+69A1TJPzio6F2+dZRF3GxeSuc1YnSli15OYujQZ
    9t1zTI9h7yhXPfbqayf8y4ktD+bRi8anOR1A7U6pawjf51hnWhuts0w6cEHQwu5y
    vs3PMSasgOM8BQs3yPrn8os7aC8ssGOfDdaItwIDAQABAoIBABOrKamTA1itvRHl
    kvaz15PW9ihWGm0wpb8eDGTzdEpKBLTq2fdnFApOpTwiytOsqDSjy4uN09jmecWZ
    bzm46pcOURFmYYY61BgGicZ/YSdgPYAhJf/Aojn18/9wsZnmdvBFTGjJAU9U06Kz
    N1VhV5GpMP0qxHv38/5SQ9XNU6vkHdcyoMrxPn04fxrxYRTPKu2pZnrkaghcDWPF
    UvwDyvokbwWU7cQqT/XIiQ0jyC+uZJY8RFbBo7wLt5h6f/OahBCQj698iOkEN9DQ
    1TqfwB7yLS1msT32S9j+a+iJPJKiGDL2YdVd4LlNb5kW727ComCTpZaxLAp3gcXd
    KuK4vkECgYEA8EgC24XB4wfsjBlpRn0xAx0LUfbtSkA7HgzDBiTOi2/PpOjjgwZc
    PFrJfvJQOSbpPl+fTIPw5X2yf5CkkrW7cJDcHYjYEyV/h9+KBZT2yM4cofp1M4Pb
    ua8e4ILPqqRNsh77A6vasVmw/ct9iRJXpTqzd1N7o7MK1/xWPBN6AsECgYEAjjhL
    PtgkxV/N98fVW6GgDi9V2I6a7ImIKHX+hJlWnnH7o9zaE+ry7UfKtgGEGEYJnKCF
    LCu68+isFnG0tUyOx/2eU6rfbmq88reNjc/5EDHncCecGZhZJVsTyfFmkXhmn6PD
    YCDxEqY9C4xU1nDMK7PAT5EcAbTqUblsGj+8gXcCgYEA5mwoUVx0EsQGlFPKIU7t
    MY8oy/GAnTP7fVW/sKSbbhxLhFnR1FTFHxvxH0xAoo4uHyKUIUxmN63S/4I2UHr2
    xXwlmi0hCTtskWBNfAzenLMLwkntGvnYPLkzYxoPDBWEbMxI67xifLEGilwahtiQ
    NGOWt1fXuaR5Qac7C2GiIAECgYAiToAQM9GC7x5fNAxKo01Zvp9lsti6UF7Q682u
    rNKRPAuotoDApz9cb6H9j5YOyO5OowYc5puddLX2YA1oYoRax9omcqSdHRBhOFfk
    KpP5DSC4FEX6gp6WfUbjwuCsHLAcuENL8AZXKlS1cW+RnvoRXLX6O5XW745KkoD6
    P/+39wKBgQCGJsez3LS1sQ7T2CSDe3LKzU3Pk6TeZMdqASXtYpgizPULMYkG5nqQ
    +0dCnEDw3hff2hnsYAOX/7h+GAP/xa7og+I08fRZK6FAxNHTRoBImuLYsk+ku9bd
    f7ervjm1oxVnNDrShtYKH7KApNIoKBW2tMWgJEVfvulPL9SvnAgGkQ==
    -----END RSA PRIVATE KEY-----

    3、在登录信息提交前进行加密:

    var password = $("#password").val();
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey('这里填写公钥');
    var encrypted = encrypt.encrypt(password);
    $("#password").val(encrypted);

    4、后端接收逻辑中先进行解密再进行正确性检验。

    $password = $_POST['password'];//获取密码
    $private_key = "这里填写私钥";
    $pi_key =  openssl_pkey_get_private($private_key);
    $decrypted = "";//解密后的密码存放在这个变量
    openssl_private_decrypt(base64_decode($password),$decrypted,$pi_key);//这里使用base64_decode是因为再前端到后端的传输过程中浏览器会自动对数据进行base64_encode
    $password = $decrypted;//解密后的密码

    改造后的登录提交效果:

    前端登录密码JS加密,后端PHP解密的非对称RSA加解密方案

    前端js的加密和解密使用方式

    var data = 'testData';
     
    //公钥加密
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey('这里填写公钥');
    var data_encrypted = encrypt.encrypt(data);
     
    //私钥解密    
    var decrypt = new JSEncrypt();
    decrypt.setPrivateKey('这里填写私钥');
    var data_decrypted = decrypt.decrypt(data_encrypted);
     
    if (data == data_decrypted) {
        console.log('加密、解密成功');
    }

    后端PHP进行RSA加密、解密过程

    $pi_key =  openssl_pkey_get_private('这里填写私钥');//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
    $pu_key = openssl_pkey_get_public('这里填写公钥');//这个函数可用来判断公钥是否是可用的
     
    $data = "testData";//原始数据
    $data_encrypted = "";//加密后的数据
    $data_decrypted = "";//解密后的数据
     
    //私钥加密
    openssl_private_encrypt($data, $data_encrypted, $pi_key);
    $data_encrypted = base64_encode($data_encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
    //公钥解密
    openssl_public_decrypt(base64_decode($data_encrypted), $data_decrypted, $pu_key);//私钥加密的内容通过公钥可用解密出来
     
    echo $data.'<br/>';
    echo $data_encrypted.'<br/>';
    echo $data_decrypted.'<br/>';
     
     
    $data_encrypted2 = "";//加密后的数据
    $data_decrypted2 = "";//解密后的数据
     
    //公钥加密
    openssl_public_encrypt($data, $data_encrypted2, $pu_key);
    $data_encrypted2 = base64_encode($data_encrypted2);
    openssl_private_decrypt(base64_decode($data_encrypted2), $data_decrypted2, $pi_key);
     
    echo $data.'<br/>';
    echo $data_encrypted2.'<br/>';
    echo $data_decrypted2.'<br/>';
    

    jsencrypt.js生成密钥对的方式:

    var crypt = new JSEncrypt({default_key_size: 1024});
    crypt.getKey();
    crypt.getPrivateKey();
    crypt.getPublicKey();

    发表评论