gpt4 book ai didi

python - 这里使用什么字符转换/伪加密算法?

转载 作者:行者123 更新时间:2023-12-01 05:36:37 26 4
gpt4 key购买 nike

这是所有密码学家都在寻求帮助的呐喊。

方案:我有一个Windows应用程序(可能是用VC ++或VB构建的,后来移到了.Net),该应用程序将一些密码保存在XML文件中。给定密码A0123456789abcDEFGH,结果“已加密”值为04077040940409304092040910409004089040880408704086040850404504044040430407404073040720407104070

查看字符串,我发现这只是字符移位:'04'界定了实际的字符值,即十进制;如果再从142中减去这些值,则会得到原始的ASCII码。在Jython(2.2)中,我的解密例程如下所示(由于注释中的建议而被编辑):

blocks = [ pwd[i:i+5] for i in range(0, len(pwd), 5) ] 
# now a block looks like '04093'
decrypted = [ chr( 142 - int(block[3:].lstrip('0')) ) for block in blocks ]


这对于ASCII值(总共127个)和少数带重音的字母来说是很好的,但是8位字符集又有128个字符。从十进制角度来看,将接受的值限制为142毫无意义。

编辑:我已经翻遍了我们的系统,发现了三个非ASCII字符:

è 03910
Ø 03926
Õ 03929


从这些值看来,实际上是从4142中减去4号块(仅保留'0'作为分隔符)给了我正确的字符。

所以我的问题是:


Windows世界中有人熟悉这种混淆方案吗?这可能是标准库功能的产物吗?老实说,我对Win32和.Net开发不是很熟悉,所以我可能缺少一些非常简单的东西。
如果它不是库函数,您能想到一种更好的方法来对这些值进行模糊处理而无需求助于神奇的142号吗,即一种可以在不使用特殊字符的情况下实际应用于非ASCII字符的方案?我对移位和所有这些都感到不知所措,所以我可能再次缺少训练有素的眼睛显而易见的东西。

最佳答案

Windows世界中有人熟悉这种混淆方案吗?


一旦正确理解它,它就像ROT13这样简单的旋转密码。

为什么有人会使用这个?

好吧,总的来说,这很常见。假设您有一些需要混淆的数据。但是解密算法和密钥必须嵌入观众所拥有的软件中。使用AES之类的东西是没有意义的,因为有人总是可以挖掘算法并从您的代码中删除密钥,而不用破解AES。比找到隐藏密钥甚至更难破解的加密方案与完美的加密方案一样好-也就是说,足以阻止偶然的观看者,并且对严重的攻击者毫无用处。 (通常,您甚至并不真正担心停止攻击,而是在证明攻击者出于合同/法律原因必须恶意行事之后证明)。因此,您可以使用简单的旋转密码或简单的xor密码—快速,难以出错且易于调试,而且如果情况变得更糟,您甚至可以手动对其进行解密,以恢复损坏的数据。

至于细节:

如果要处理非ASCII字符,则几乎必须使用Unicode。如果使用固定的8位字符集或本地系统的OEM字符集,则将无法处理其他计算机的密码。

Python脚本几乎可以肯定会处理Unicode字符,因为在Python中,您要么在str中处理字节,要么在unicode中处理Unicode字符。但是Windows C或.NET应用程序更有可能使用UTF-16,因为Windows本机API在WCHAR *(也称为16位字符串)中处理UTF-16-LE代码点。

那么,为什么是4142?好吧,关键是什么都没有。我猜有些程序员建议42。然后,他的经理说:“这听起来不太安全。”他叹了口气,说道:“我已经解释了为什么没有比...更安全的密钥了……您知道吗,算了吧,那4142呢?”经理说:“哦,这听起来像是一个非常安全的数字!”这就是为什么4142。




  如果它不是库函数,您能想到一种更好的方法来对这些值进行模糊处理而无需求助于神奇的142号。


您确实需要求助于魔术4142,但是您可以使其变得更简单:

def decrypt(block):
return struct.pack('>H', (4142 - int(block, 10)) % 65536)


因此,每个5个字符的块都是使用C unsigned-short环绕规则从4142中减去的UTF-16代码单元的十进制表示。

这在本机Windows C中实现起来很简单,但是在Python中要难一些。我能想到的最佳转换函数是:

def decrypt_block(block):
return struct.pack('>H', (4142 - int(block, 10)) % 65536)

def decrypt(pwd):
blocks = [pwd[i:i+5] for i in range(0, len(pwd), 5)]
return ''.join(map(decrypt_block, blocks)).decode('utf-16-be')


在C或C#中,这可能要琐碎得多,这很可能是他们在其中实现的东西,所以让我解释一下我在做什么。

您已经知道如何将字符串转换为5个字符的块序列。

我的 int(block, 10)与您的 int(block.lstrip('0'))做相同的事情,请确保 '0'前缀不会使Python将其视为八进制数字而不是十进制,而是更明确地显示。我认为这在Jython 2.2中实际上不是必需的(在更现代的Python / Jython中它绝对不是必需的),但我还是保留了它以防万一。

接下来,在C中,您只需执行 unsigned short x = 4142U - y;,它将自动适当地下溢。 Python没有 unsigned short值,只有 int签名,因此我们必须手动进行下溢。 (由于Python使用底数除法和余数,因此符号始终与除数相同-在C语言中并非如此,至少在C99和大多数平台的C89中并非如此。)

然后,在C语言中,我们将unsigned short强制转换为16位的“宽字符”。 Python没有做到这一点的任何方法,因此我们必须使用 struct.pack。 (请注意,我正在将其转换为big-endian,因为我认为这使调试更容易;在C中,您将转换为native-endian,并且由于这是Windows,因此将是little-endian。)

因此,现在我们有了2个字符的UTF-16-BE代码点的序列。我只是将它们 join变成一个大字符串,然后 decode将其作为UTF-16-BE。



如果您真的想测试我是否正确,则需要查找的字符不仅是非ASCII字符,而且还不是西字符。特别是,您需要:


> U + 4142但 '41006',因为那是4142-0x7000作为未签名的short进行了翻转。
> = U + 10000的字符。这包括不常见的CJK字符,专门的数学字符,古代文字的字符等。例如,旧斜体字符U + 10300(𐌀)编码为代理对(0xd800、0xdf00); 4142-0xd800 = 14382和4142-0xdf00 = 12590,因此您会得到'1438212590'


很难找到第一个-甚至我接触过的大多数中文和日文本地程序员都使用ASCII密码。第二,甚至更多。除了历史语言学教授之外,没有其他人可能甚至会考虑在其密码中使用过时的脚本。根据墨菲定律,如果您编写正确的代码,则永远不会使用它,但如果不编写,则保证在您交付代码后立即显示。

关于python - 这里使用什么字符转换/伪加密算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18838011/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com