【问题标题】:Decryption function gives wrong result with special characters解密函数使用特殊字符给出错误结果
【发布时间】:2020-02-10 13:03:40
【问题描述】:

我正在 VBScript / Classic ASP 中构建一个加密/解密函数。 只要要加密/解密的字符串不包含特殊字符,这一切都可以工作。

' str = "Bayern München"
' key = "ab34ehyd67hy6752daskjh"

Function EncryptString(val, key)

    valLen = Len(val)
    keyLen = Len(key)
    keyPos = 1
    newVal = ""
    revVal = val

    For x = 1 To valLen
        calc = AscW(Mid(revVal, x, 1)) + AscW(Mid(key, keyPos, 1))
        'Response.Write ":" & AscW(Mid(revVal, x, 1)) & " + " & AscW(Mid(key, keyPos, 1)) & " = " & calc & "<br />"
        newVal = newVal & Hex(calc)
        keyPos = keyPos + 1
        If keyPos > keyLen Then keyPos = 1
    Next

    EncryptString = newVal

End Function

Function DecryptString(val, key)

    ' The workaround - start
    For i = 160 To 255
        val = Replace(val, Chr(i), "&#" & i & ";")
    Next
    ' The workaround - end

    valLen = Len(val)
    keyLen = Len(key)
    keyPos = 1
    newVal = ""
    revVal = val
    chrVal = ""

    ' I suspect this to be the error
    For y = 1 To valLen Step 2
        chrVal = chrVal & ChrW("&h" & Mid(revVal, y, 2))
    Next

    For x = 1 To Len(chrVal)
        calc = AscW(Mid(chrVal, x, 1)) - AscW(Mid(key, keyPos, 1))
        'Response.Write "::" & AscW(Mid(chrVal, x, 1)) & " - " & AscW(Mid(key, keyPos, 1)) & " = " & calc & "<br />"
        newVal = newVal & ChrW(calc)
        keyPos = keyPos + 1
        If keyPos > keyLen Then keyPos = 1
    Next

    DecryptString = newVal

End Function

如果我对字符串“Bayern München”进行加密,然后对加密字符串调用 DecryptString 函数,它会返回 Bayern M?À?vU?

如果我输出数据(示例中的 Response.Write's),解密函数会为字符 ü 返回一个负数,所以我做错了什么 - 但是呢?

系统编码为 Windows-1252。

更新:

我在 DecryptString 函数中做了这个变通方法。我不确定它是否涵盖了所有可能的问题,但从我目前的测试来看,它确实:

For i = 160 To 255
    val = Replace(val, Chr(i), "&#" & i & ";")
Next

【问题讨论】:

  • 一般来说,我建议始终使用 UTF-8 编码。在页面顶部的声明中添加 'CODEPAGE="65001"',并且看到字符串“Bayern München”被硬编码到您的页面中,您应该将文件保存为 UTF-8。 (您可以使用记事本执行此操作,从文件菜单中选择“另存为”,然后在必要时使用下拉菜单从 ASCII 更改为 UTF-8)这篇博文是在其他语言中使用经典 ASP/VBS 的必备读物英语。 hanselman.com/blog/InternationalizationAndClassicASP.aspx
  • @john 我希望我能做到这一点,但这是一个基于 Windows-1252 编码的旧系统,因此现在无法进行转换。
  • @Lankymart 这是我自己的问题吗? :)
  • @Mads 完全一样,这是同一个问题。
  • 但是我得到了正确的结果,如果我加密/解密 Bayern M&amp;#252;nchen 所以问题是,我如何在加密/解密之前将原始值 Bayern München 转换为 UTF-8?恐怕不能将整个系统转换为 UTF-8。

标签: vbscript asp-classic


【解决方案1】:

不知道你是否还需要修复它,但以上都是因为hex() 为任何超过 255 的小数返回一个长于 2 的字符串:

(255)10 = (FF)16
(256)10 = (100)16 

即当原始字符串+盐超过255(10)时

("ü" 252) + ("6" 54) = 252+54 = 306(10)=132(16) (3 characters long)

那么"For y=1 To valLen Step 2" 将只取“132”中的“13”,这将导致不正确的解密。

根据需要,可以“固定”,例如检查加密代码是否超过255,为真时不加盐:

Function EncryptString(val, key)

...
'newVal = newVal & Hex(calc) <-- replace this by following code
if calc > 255 then 
   newVal = newVal & "01" & Hex(Asc(Mid(revVal, x, 1))) ' no salt
else
   newVal = newVal & Hex(calc)
end if

其中“01”只是一个“信号”字符,表示下一个字符将不含盐。

分别

Function DecryptString(val, key)
...
'calc = Asc(Mid(chrVal, x, 1)) - Asc(Mid(key, keyPos, 1))
if Asc(Mid(chrVal, x, 1))=1 then 'determine "signal"
   ignorenext = true 'flag that next char has no salt
else
   if ignorenext then
      calc = Asc(Mid(chrVal, x, 1)) 'no salt
      ignorenext = false
   else 
       calc = Asc(Mid(chrVal, x, 1)) - Asc(Mid(key, keyPos, 1))
   end if 

   newVal = newVal & Chr(calc)
   keyPos = keyPos + 1
   If keyPos > keyLen Then keyPos = 1
end if

注意,对于 Windows-1252,无需使用特定于 unicode 的 AscW()/ChrW()。

另一种方法是将十六进制替换为更“稳定”的东西,即 base32。从Classic ASP/VBScript implementation of Crockford's Base32 Encoding 获取示例代码,您的代码可能看起来像

Function EncryptString(val, key)

    valLen = Len(val)
    keyLen = Len(key)
    keyPos = 1
    newVal = ""
    revVal = val

    For x = 1 To valLen
        calc = Asc(Mid(revVal, x, 1)) + Asc(Mid(key, keyPos, 1)) 
        newVal = newVal & ToBase32(calc) 
        keyPos = keyPos + 1
        If keyPos > keyLen Then keyPos = 1
    Next

    EncryptString = ucase(newVal)

End Function

Function DecryptString(val, key)

    valLen = Len(val)
    keyLen = Len(key)
    keyPos = 1
    newVal = ""
    revVal = val
    chrVal = ""

    For y = 1 To valLen Step 2 
        chrVal = chrVal & fromBase32(Mid(revVal, y, 2))  
        calc = fromBase32(Mid(revVal, y, 2)) - Asc(Mid(key, keyPos, 1))   
        newVal = newVal & Chr(calc) 
        keyPos = keyPos + 1
        If keyPos > keyLen Then keyPos = 1  
    Next

    DecryptString = newVal

End Function

【讨论】:

    猜你喜欢
    • 2015-01-28
    • 2015-10-07
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多