SSL 替代方案 - 使用 JavaScript 加密密码提交给 PHP 进行解密

发布于 2024-11-02 09:23:29 字数 1055 浏览 2 评论 0原文

我正在建立一个网站,我的付款方式将是 Google Checkout 和 Paypal。将有链接/按钮将用户重定向到安全的 Google/Paypal 网站以处理付款。这意味着我不需要每年 150 美元的额外费用和为我的网站安装 SSL 证书的复杂性。

不过,我想在用户登录时对其密码进行加密,这样,如果他们在网络上,运行 FireSheep 等的恶意人员将无法读取用户的实际密码,因为它被发送到服务器。网站的其余部分不需要加密,因为它不是真正的敏感数据,并且可能会显着降低用户体验。

我的想法是这可以通过公钥加密来实现。假设这个过程是这样的:

  1. 公钥位于 JavaScript 外部文件中,私钥位于服务器上的 PHP 中
  2. 用户在表单中输入用户名和密码,然后单击“提交”
  3. JavaScript 运行并加密密码,将其存储回文本字段
  4. 表单提交到服务器并使用 PHP 解密密码
  5. PHP 中的纯文本密码经过加盐处理然后将哈希值与数据库中的哈希值进行比较。
  6. 注册/更改密码功能可能有类似的过程。

我认为像 RSA 这样的东西可以解决这个问题。但我在网上寻找一个可用的 JavaScript 库来完成此任务,但似乎没有一个与可用的 PHP 库兼容。无论如何,它需要生成一组与 JavaScript 和 PHP 兼容的密钥。

有人知道这个问题的实际工作解决方案吗?如果没有,我们写一个然后开源怎么样?不幸的是,编写加密/解密代码非常复杂,所以我真的不知道现有的库在做什么以及如何修改它们以使其工作。我已经有了针对会话固定/劫持的保护,所以我对此不感兴趣。只是对数据到达网络服务器之前进行加密感兴趣。

注意:请不要发布一堆指向独立 Javascript 或 PHP 加密库的链接,我已经在 Google 上找到了这些链接。这实际上没有用。我需要的是 JavaScript 加密和 PHP 解密的代码,它们实际上可以和谐地协同工作,以产生上面概述的预期结果。

此外,如果您可以避免发表“只使用 SSL”之类的评论。我实际上想要一个解决这个问题的方法,即使这不是最佳实践,但它仍然很有趣。

非常感谢!

I'm building a website and my payment methods will be Google Checkout and Paypal. There will be links/buttons which will redirect the user to the secure Google/Paypal sites for processing the payments. This means I do not need the $150/year added expense and complexity of installing SSL certificates for my site.

However I would like to encrypt user's passwords as they are logging in so that if they are on a network some malicious person running FireSheep etc can't read the user's actual password as it is being sent to the server. The rest of the site doesn't need encryption as it's not really sensitive data and would probably slow the user experience down significantly.

My thoughts are this could be implemented with public key cryptography. Lets say the process goes something like this:

  1. Public key is in the JavaScript external file, private key in PHP on the server
  2. User enters their username and password into the form and clicks submit
  3. The JavaScript runs and encrypts the password, storing it back in the text field
  4. Form is submitted to server and the password is decrypted with PHP
  5. Plain text password in PHP is salted & hashed then compared to hash in database.
  6. Possible similar process for the registration/change password functions.

I'm thinking something like RSA would do the trick. But I've hunted around the net for a working JavaScript library to do it but none seem to be compatible with the PHP libraries available. At any rate it needs to generate a set of keys that are compatible with the JavaScript and PHP.

Anyone know of an actual working solution for this? If not how about we write one then open source it. Unfortunately writing encryption/decryption code is pretty complex so I don't really know exactly what the existing libraries are doing and how to modify them to make it work. I already have protection for session fixation/hijacking so I'm not interested in that. Just interested in encrypting the data before it gets to the web server.

NB: Please don't post a bunch of links to standalone Javascript or PHP encryption libraries, I've found those already on Google. That's not actually useful. What I need is code for JavaScript encryption AND PHP decryption that actually works together harmoniously to produce the intended result outlined above.

Also if you could refrain from posting comments like "just use SSL". I'd actually like a solution to this exact problem even if it's not best practice, it would be interesting none the less.

Many thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

极致的悲 2024-11-09 09:23:29

只有一个问题:攻击者不需要知道实际密码。他需要看到的只是发送到服务器的值。该值允许用户登录。该值是什么并不重要;重要的是。无论是明文、加密文本还是猫的图片。它只是一个验证用户身份的令牌。如果攻击者可以看到此令牌并重复相同的请求,并且该相同的请求允许他登录,那么您将一无所获。

Only one problem: An attacker does not need to know the actual password. All he needs to see is the value that is sent to the server. This value allows the user to log in. It does not matter what that value is; whether it's plaintext, encrypted text or a picture of a cat. It's just a token that authenticates the user. If an attacker can see this token and repeat the same request and that same request allows him to log in, you gained nothing.

黑寡妇 2024-11-09 09:23:29

RSA 杀伤力太大了​​;您可能需要的是一个简单的质询-响应协议。例如:

  • 生成随机nonce值;这有助于防止重放攻击。
  • 将随机数值和密码盐以及登录表单的其余部分一起发送到浏览器。
    • 您以加盐和散列形式存储密码,对吗?
  • 当用户输入密码时,让脚本在表单上计算并发送回 hash(hash(password, salt), nonce)。
  • 当服务器收到表单提交时,让它计算 hash(storedSaltedPassword, nonce) 并验证它是否等于提交的值。
    • 在服务器上保留nonce值;不要相信客户端会将其回显给您,否则您的重播保护就会消失。

该方案的缺点是数据库中的密码散列在某种意义上与密码等效。虽然提取用于生成这些哈希值的原始密码可能不可行,但了解存储的哈希值足以模拟您网站上的用户。

SSL 证书具有完全不同的目的:SSL 证书的目的是使第三方恶意服务器难以声称是您的服务器,因为它没有由某个相互信任的第三方签署的证书属于您的域。另一方面,如果您无法阻止恶意服务器冒充您的服务器,则无论采用加密技术,您都无法保护您的用户免于向该恶意服务器提供密码。

RSA is overkill; what you probably need is a simple challenge-response protocol. For example:

  • Generate a random nonce value; this helps prevent replay attacks.
  • Send that nonce value and the password salt to the browser along with the rest of the login form.
    • You are storing passwords in salted and hashed form, right?
  • When the user enters a password, have the script on the form compute and send back hash(hash(password, salt), nonce) instead.
  • When the server receives the form submission, have it compute hash(storedSaltedPassword, nonce) and verify that it equals the submitted value.
    • Retain the nonce value at the server; don't trust the client to echo it back to you, or your replay protection is gone.

The weakness of this scheme is that the password hashes in the database are in some sense password-equivalent; while it's likely infeasible to extract the original password used to produce those hashes, knowledge of the stored hash is sufficient to impersonate the user on your site.

SSL certificates serve an entirely different purpose: the purpose of an SSL certificate is to make it difficult for a third-party rogue server to claim to be your server, because it doesn't have a certificate signed by some mutually trusted third party that it belongs on your domain. On the other hand, if you can't stop a rogue server from impersonating yours, you can't protect your users from giving their password to that rogue server, cryptography notwithstanding.

埋情葬爱 2024-11-09 09:23:29

首先,我认为这不是一个好主意。我发现一些使用 Google 的示例可能对您有用(但是我还没有测试过这些示例):

GPL JavaScript 公钥加密

JavaScript 中的 RSA 公钥加密测试

JavaScript 中的 PGP 加密

JavaScript 中的 RSA 算法示例

您应该建立一些加盐机制来对每个加密值加盐,否则密钥可能会受到损害。

First, I don't think this is a good idea. I found some examples using Google that may be useful for you (I have not tested these, however):

GPL JavaScript Public Key Encryption

RSA Public Key Encryption Test in JavaScript

PGP Encryption in JavaScript

RSA Algorithm Example in JavaScript

You should establish some salting mechanism to salt every encrypted value otherwise the key could get compromised.

遗忘曾经 2024-11-09 09:23:29

http://www.jcryption.org/ -- 是您正在寻找的组合。

http://www.jcryption.org/ -- Is the combination you are looking for.

捎一片雪花 2024-11-09 09:23:29

您不需要对密码进行加密。您需要对密码进行哈希。您确实不想自己访问明文密码,否则您将失去不可否认性,这会产生严重的法律后果。在继续之前,您需要彻底研究其含义。

You don't need to encrypt the password. You need to hash the password. You really really don't want to have any access to the plaintext password yourself whatsoever, otherwise you lose non-repudiation, which has serious legal consequences. You need to investigate the meaning of this thoroughly before proceeeding.

你的呼吸 2024-11-09 09:23:29

这是获取输入然后通过java脚本加密内容的代码
完整的代码也可以在github上找到,大家可以搜索一下encrypt_js_decrypt_php。这个问题已经运行很久了。我已经想出了解决方案。只需将其导入本地主机即可。

<html>

<input type="text" id="code" name="code"/>
<input type="submit" name="submit" value="submit" onclick="return encryptCode();"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
function rc4(key, str)
{
    var s = [], j = 0, x, res = '';
    for (var i = 0; i < 256; i++) 
    {
        s[i] = i;
    }
    for (i = 0; i < 256; i++) 
    {
        j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
    }
    i = 0;
    j = 0;
    for (var y = 0; y < str.length; y++) 
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
        res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
    }
    return res;
}

function encryptCode()
{
  var value = document.getElementById("code").value;
  var key = "secretKeyToProvide";  /*--Provide Your secret key here--*/
  var codeValue = rc4(key, value);
  var arr = {code:codeValue, Age:25};
  $.ajax({
                url: "response.php",
                type: "POST",
                data: JSON.stringify(arr),
                dataType: 'json',
                async: false,
                contentType: 'application/json; charset=utf-8',
                success: function(data) 
                {
                    alert(data);
                }
            });   
}
</script>
</html>

现在,让我们解密php中的代码

<?php

function mb_chr($char) 
{
    return mb_convert_encoding('&#'.intval($char).';', 'UTF-8', 'HTML-ENTITIES');
}

function mb_ord($char)
{
    $result = unpack('N', mb_convert_encoding($char, 'UCS-4BE', 'UTF-8'));
    if (is_array($result) === true) 
    {
        return $result[1];
    }
        return ord($char);
}

function rc4($key, $str) 
{   
    if (extension_loaded('mbstring') === true) 
    {
        mb_language('Neutral');
        mb_internal_encoding('UTF-8');
        mb_detect_order(array('UTF-8', 'ISO-8859-15', 'ISO-8859-1', 'ASCII'));
    }
    $s = array();
    for ($i = 0; $i < 256; $i++)
    {
        $s[$i] = $i;
    }
    $j = 0;
    for ($i = 0; $i < 256; $i++)
    {
        $j = ($j + $s[$i] + mb_ord(mb_substr($key, $i % mb_strlen($key), 1))) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
    }
    $i = 0;
    $j = 0;
    $res = '';
    for ($y = 0; $y < mb_strlen($str); $y++)
    {
        $i = ($i + 1) % 256;
        $j = ($j + $s[$i]) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
        $res .= mb_chr(mb_ord(mb_substr($str, $y, 1)) ^ $s[($s[$i] + $s[$j]) % 256]);
    }
    return $res;
}

$request_body = file_get_contents('php://input');
$json = json_decode($request_body);
$secretCode =$json->code ;
$age =$json->Age  ;
$key = "secretKeyToProvide";  /*--Provide Your secret key here what you have given in javascript--*/
$decryptedSecretCode  = rc4($key, $secretCode) ;
echo $decryptedSecretCode;
exit;
?>

This is the code to take the input and then encrypt the content by java script
The entire code is also available in github.you guys can search for it encrypt_js_decrypt_php. The problem was running since long.I have come up with the solution.Just import it into localhost.

<html>

<input type="text" id="code" name="code"/>
<input type="submit" name="submit" value="submit" onclick="return encryptCode();"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
function rc4(key, str)
{
    var s = [], j = 0, x, res = '';
    for (var i = 0; i < 256; i++) 
    {
        s[i] = i;
    }
    for (i = 0; i < 256; i++) 
    {
        j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
    }
    i = 0;
    j = 0;
    for (var y = 0; y < str.length; y++) 
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
        res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
    }
    return res;
}

function encryptCode()
{
  var value = document.getElementById("code").value;
  var key = "secretKeyToProvide";  /*--Provide Your secret key here--*/
  var codeValue = rc4(key, value);
  var arr = {code:codeValue, Age:25};
  $.ajax({
                url: "response.php",
                type: "POST",
                data: JSON.stringify(arr),
                dataType: 'json',
                async: false,
                contentType: 'application/json; charset=utf-8',
                success: function(data) 
                {
                    alert(data);
                }
            });   
}
</script>
</html>

Now,lets decrypt the code in php

<?php

function mb_chr($char) 
{
    return mb_convert_encoding('&#'.intval($char).';', 'UTF-8', 'HTML-ENTITIES');
}

function mb_ord($char)
{
    $result = unpack('N', mb_convert_encoding($char, 'UCS-4BE', 'UTF-8'));
    if (is_array($result) === true) 
    {
        return $result[1];
    }
        return ord($char);
}

function rc4($key, $str) 
{   
    if (extension_loaded('mbstring') === true) 
    {
        mb_language('Neutral');
        mb_internal_encoding('UTF-8');
        mb_detect_order(array('UTF-8', 'ISO-8859-15', 'ISO-8859-1', 'ASCII'));
    }
    $s = array();
    for ($i = 0; $i < 256; $i++)
    {
        $s[$i] = $i;
    }
    $j = 0;
    for ($i = 0; $i < 256; $i++)
    {
        $j = ($j + $s[$i] + mb_ord(mb_substr($key, $i % mb_strlen($key), 1))) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
    }
    $i = 0;
    $j = 0;
    $res = '';
    for ($y = 0; $y < mb_strlen($str); $y++)
    {
        $i = ($i + 1) % 256;
        $j = ($j + $s[$i]) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
        $res .= mb_chr(mb_ord(mb_substr($str, $y, 1)) ^ $s[($s[$i] + $s[$j]) % 256]);
    }
    return $res;
}

$request_body = file_get_contents('php://input');
$json = json_decode($request_body);
$secretCode =$json->code ;
$age =$json->Age  ;
$key = "secretKeyToProvide";  /*--Provide Your secret key here what you have given in javascript--*/
$decryptedSecretCode  = rc4($key, $secretCode) ;
echo $decryptedSecretCode;
exit;
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文