在没有服务器的环境中,如何密码保护文件(html)?

时间:2018-12-20 03:04:20

标签: javascript html

是否可以在不使用.htaccess,php或localhost的情况下对文件进行密码保护。也许使用某种类型的加密或其他方法。

4 个答案:

答案 0 :(得分:3)

是的,借助SubtleCrypto API,您可以实现相当不错的前端加密。
甚至还有js port of openpgp

是的,例如,您最终可以将所需的任何数据编码为pgp消息,然后需要密码来解密和使用它。

如果您需要对邮件进行加密:

(async function() {
  const cleartext = 'alert("an useless message")';
  const msg = openpgp.message.fromText(cleartext);
  const ciphertext = await openpgp.encrypt({
    message: msg,
    passwords: ["mypassword"],
    armor: true
  });
  // you'd be better saving as a text file though,
  // ecnoding and new line characters matter
  console.log(ciphertext.data);
})()
.catch(console.error);
<script src="https://cdn.jsdelivr.net/npm/openpgp@4.3.0/dist/openpgp.min.js"></script>

然后解密:

(async function() {
  const password = prompt('enter password ("mypassword")');
  // one of the results of previous snippet
  const encrypted = `-----BEGIN PGP MESSAGE-----
Version: OpenPGP.js v4.3.0
Comment: https://openpgpjs.org

wy4ECQMI61wIzRzOswzg/j6zhPvasbu97nt+XeD23m3UNnc8J3SqAGiogvn8
zqKD0lMB49BViJ8gQ7E/6If6vaCv9NBojjVgS9P2E7mROtZrbz5Z150ohcKV
kDncF//Io6sb/5L/5AcLXBxCJzhQKIYwtIdHu9paWGpEto1z5EzOGzpZgg==
=hMhM
-----END PGP MESSAGE-----`;
  const decrypted = await openpgp.decrypt({
    message: await openpgp.message.readArmored(encrypted),
    passwords: [password]
  })
  const cleartext = decrypted.data;
  console.log(cleartext);
  new Function(cleartext)();
})()
.catch(console.error);
<script src="https://cdn.jsdelivr.net/npm/openpgp@4.3.0/dist/openpgp.min.js"></script>

答案 1 :(得分:1)

不。好吧,没有提供任何远程安全功能的产品。您可以在javascript中隐藏一个密码,也许将其编码为base64,然后将输入字段的值与存储的base64代码进行比较,但是任何对“查看源代码”或javascript有所了解的人都可以轻松地绕过此密码。 >

密码验证和其他敏感信息必须在服务器端进行处理,否则用户将无法访问!

答案 2 :(得分:0)

受@Kaiido的启发,我开发了一个JavaScript书签。因此,将其添加为浏览器中的新书签,然后单击它以加密当前页面。系统将要求您输入密码并选择保存加密HTML页面的位置。

javascript:(function (doc) {
    var password = prompt('Enter a password to encrypt this page'),
        js = doc.createElement('script');

    js.onload = function () {
        /* Get current page HTML and use a dirty workaround to convert relative paths to full URLs */
        var page = doc.documentElement.cloneNode(true);
        for (var attr of ['src', 'href']) {
            page.querySelectorAll('[' + attr + ']').forEach(function (node) {
                node[attr] = node[attr];
            });
        }

        /* All the magic belongs to openpgpjs.org */
        openpgp.encrypt({
            message: openpgp.message.fromText(page.outerHTML),
            passwords: [password]
        }).then(function (ciphertext) {
            var link = doc.createElement('a'),
                html = [
                    '<!DOCTYPE html>',
                    '<head>',
                    '  <meta charset="utf-8" />',
                    '</head>',
                    '<body>',
                    '  <textarea id="encryptedMessage" style="display:none">' + ciphertext.data + '</textarea>',
                    '  <script src="' + js.src + '"></script>',
                    '  <script>',
                    '    var field=document.getElementById("encryptedMessage");',
                    '    openpgp.message.readArmored(field.value).then(function(message){',
                    '      var decrypter=openpgp.decrypt({message:message,passwords:[prompt("Enter the password to decrypt this page")]});',
                    '      decrypter.then(function(plaintext){document.documentElement.innerHTML=plaintext.data});',
                    '      decrypter.catch(function(e){alert(String(e))});',
                    '    });',
                    '  </script>',
                    '</body>'
                ].join('\n');

            doc.body.appendChild(link);
            link.download = 'protected.html';
            link.href = 'data:text/html;,' + encodeURIComponent(html);
            link.click();
            doc.body.removeChild(link);
        });
    };

    /* This will fail if Content Security Policy prohibits embedded scripts */
    js.src = 'https://cdnjs.cloudflare.com/ajax/libs/openpgp/4.3.0/compat/openpgp.min.js';
    doc.body.appendChild(js);
})(document);

可在此处找到加密页面的示例:http://fiddle.jshell.net/yjLwq0mx/show/light/

答案 3 :(得分:0)

是的,您可以仅使用JS加密任何消息,而无需后端,也无需在JS代码中存储密码。我将描述没有技术细节的简单理论方法:

加密:

  1. 创建密码(但不要将其存储在任何地方)
  2. 根据该密码(例如bcrypt)生成长而复杂的哈希(相同的密码应始终产生相同的哈希,而不是将其存储在任何地方;)
  3. 使用该哈希作为symetric-key algorithm(例如ciphers AES)的密钥来编码您的消息。

解密:

  1. 要求用户输入密码
  2. 从该密码生成哈希(以与加密相同的方式)
  3. 使用该哈希作为symetric-key算法中的键来解码消息。

如您所见,这种方法无需在任何地方存储密码。