【问题标题】:Trying to send encrypted text via URI - /uDDBA causing "URIError: URI Malformed"尝试通过 URI 发送加密文本 - /uDDBA 导致“URIError: URI Malformed”
【发布时间】:2013-04-06 02:18:27
【问题描述】:

简单代码:

encodeURIComponent("\uDDBA")

结果:

URIError: URI malformed

我正在尝试做一个简单的加密,它需要一些用户输入的文本和密码,然后它将加密该文本并将其保存到服务器。

基本上我正在尝试对字母“t”进行编码 - 算法已确定应该是 56762 或十六进制的 DDBA。

但如果我尝试使用 encodeURIComponent 对该字符进行编码,某些十六进制值似乎会导致错误。

我该如何解决这个问题?

我基本上需要知道可以在javascript中正确通过encodeURIComponent的可用字符范围。

目前我正在做这样的事情:

var xor = 0xDDCE;

var plainText = "t".charCodeAt(0);
var encoded = plainText ^ xor;
var encodedChar = String.fromCharCode(encoded);
var uri = "/someuri?character=" + encodeURIComponent(encodedChar);

// This is how i would get the plain text back
var decoded = encodedChar.charCodeAt(0) ^ xor;
var decodedChar = String.fromCharCode(decoded);

这是一个非常简化的版本,其中的异或值是静态的。在实际情况下,xor 值将基于一堆变量来计算。

假设“/someuri”不是由我构建的,并且最初并不是为了接收加密数据而构建的,我只是想使用这个 URI。

另外,我的加密算法可以更改。 xor 值将使用相当简单的算法生成,该算法使用用户输入的密码和字符的位置。

我正在考虑使这项工作的一种方法是减少可能的输出字符的总数并执行某种映射......但我无法真正想象出它的代码。

编辑:

感谢您对我选择的加密的安全性发表评论;然而,实际的数据安全方面并不那么重要。我只是想防止“普通”人能够阅读输出的加密文本(假设可能有很多)

【问题讨论】:

    标签: javascript unicode uri encryption-symmetric


    【解决方案1】:

    如果您不希望普通人看到文本,只需使用 POST 请求或 Base64。

    至于实际的安全性,这完全没用。攻击者不需要知道明文是什么,他只需要知道什么 用户发送到您的站点并自己发回相同的数据。防止这种情况的唯一方法是在您网站的任何地方都使用 SSL。 如果他们愿意,他们可以使用您在页面源代码中找到的算法来解密它。


    Javascript 字符串不能立即验证它们的状态有点可怕,因为它基本上可以免费完成。 Javascript 字符串与UTF-16* encoding 相关联,其中并非所有序列都有效。单位值在 0xD800 - 0xDBFF 之间是无效的 当它没有立即被跟随时是 0xDC00 - 0xDFFF。如果之前的单位值不是 0xDC00 - 0xDFFF 是无效的 0xD800 - 0xDBFF。

    很多事情都可能导致字符串违反这一点,并且由于字符串不会自我验证,您只会在很久以后才会看到错误。

    您总是可以一次执行 8 位,它会起作用。

    var xor = 0xDDCE;
    
    var input = "t",
        output = "",
        i = 0,
        ch;
    
    while( isFinite( ch = input.charCodeAt(i++) ) {
        var xored = ch ^ xor;
        output += String.fromCharCode(
            (xored & 0xFF00) >> 8,
            xored & 0xFF
        );
    }
    
    //output is "ݺ", or 0x00DD 0x00BA, each char is always 0x00XX
    

    *规范也允许使用 UCS-2,但我从未见过。如果您想确定:

    function areStringsUTF16() {
        try {
            var str = decodeURIComponent("%F0%A0%80%80");
            return str.charCodeAt(0) === 0xd840 &&
                   str.charCodeAt(1) === 0xdc00;
        }
        catch(e) {
            return false;
        }
    }
    

    【讨论】:

    • 谢谢,我会稍微研究一下你的答案。但是对于数据安全无用,我想提一件事——我不在乎攻击者是否试图假装知道明文,我真的只在乎攻击者不能阅读明文。加密数据显示在我不拥有的公共网站上,我希望只有我和我提供密码的人能够阅读它。当然有人可以破坏安全性,我只是想要对普通人来说足够的东西。
    【解决方案2】:

    对不起,

    我将尝试回答我自己的问题

    运行此代码:

     (function() {
        var last = null;
        for ( var idx = 0; idx < 0xffff; idx++) {
            try {
                encodeURIComponent(String.fromCharCode(idx));
            } catch (e) {
                if (idx != last + 1) {
                    console.log(idx);
                }
                last = idx;
            }
        }
        console.log(last);
     })();
    

    这会导致

    55296
    57343
    

    这意味着 \uD800 和 \uDFFF 之间的任何值都是不允许的。

    当我写这篇文章的时候,我想到我应该只写一个 for 循环并测试所有内容。

    【讨论】:

      猜你喜欢
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多