Mysql:用键异或字符串

问题描述 投票:0回答:2

我想用 KEY 对字符串(实际上是它的二进制表示形式)进行按位异或。

运算结果应以十六进制表示。

我有: 'a' - 要更改的 UTF-8 字符串。 'ACF123456' - 十六进制密钥。

结果显示为 BIGINT:

select CONV(HEX('a'), 16, 10)  ^  CONV('ACF123456', 16, 10);

结果显示为十六进制:

select CONV( CONV(HEX('a'), 16, 10)  ^  CONV('ACF123456', 16, 10), 10, 16);

问题:

  1. 上面的转换是否正确?
  2. 如果字符串太长(即我们用“a veeeeeery long string”代替“a”)会发生什么?似乎 conv() 函数有一个限制(是文档中的 64 位精度)吗?除了 XOR 运算符 ^ 之外,还有一个与 nr 有关的限制。返回结果的位数。有适用于任何字符串的解决方案(允许使用存储过程)吗?

谢谢。

mysql string bit-manipulation xor
2个回答
1
投票

我觉得你的转化效果很好。 正如您所指出的,

CONV()
^
确实具有 64 位精度。

2^64 = 16^16,因此超过 16 个十六进制数字的字符串应该转换为大于 2^64 的整数。然而,当尝试将这些字符串转换为整数时,这些字符串将被残酷地(无声地)从左侧截断。

我的解决方案的要点是对这些字符串进行切片。显然,结果可能不会显示为整数,而只能显示为字符串表示形式。

@input
成为您的“要更改的字符串”,
@key
您的“密钥”。

  1. HEX(@input)
    分配给
    @hex_input
    。这里没问题,因为
    HEX()
    适用于字符串。
  2. @hex_input
    切成 16 个十六进制数字长字符串,从右侧开始
  3. 同样,将
    @key
    切成 16 位长的字符串。
  4. 从右侧开始,用
    X-OR
    的每个 64 位切片计算
    @hex_input
    的每个 64 位切片的
    @key
    。使用
    CONV(@slice, 16, 10)
    。如果
    @hex_input
    @key
    的切片少于另一个字符串,则
    X-OR
    另一个字符串的剩余切片为 0。
  5. 使用
    X-OR
    .
     将第 4 点中的 
    UNHEX()
  6. 产生的每个 64 位数字转换回十六进制字符串。
  7. 重新组装所得切片。这就是你的结果。

三列

TEMPORARY
表可以用作数组来存储
@hex_input
@mask
的切片以及生成的切片。

将所有这些放在一个存储过程中,然后voilà

听起来你对MySQL有一些技能,你应该能够将上面的内容翻译成真正的代码。但如果您需要进一步的指导,我很乐意提供帮助。


0
投票

上面的转换是否正确?

不,操作数的大小不同,如果字符串的大小已知,则您已将密钥的其余部分提供给了可能的攻击者。

select HEX(CONV(HEX('a'), 16, 10)  ^  CONV('ACF123456', 16, 10));

返回:

'ACF123437'

部分密钥清晰地出现在输出中:

'ACF1234'

其余:

HEX(HEX('a') ^ 0x56)

返回:

'37'

如果密钥仅使用一次(一次垫)或数据是固定大小的字符串或(非重复密钥长度等于或大于可能的数据并且知道数据的长度不是问题。)那么这种解决方案就可以了。

但是如果将相同的键应用于具有可变长度数据的整个列,则可以应用统计分析,从而大大减少搜索空间,特别是如果该人之前对数据有任何了解的话。


适用于任何字符串的任何解决方案:

从 MySql 8 开始,但从 11.3 开始不包括 MariaDB,您可以在

&
上使用按位 AND OR XOR NOT(分别为
|
,
^
,
~
,
BINARY()
)运算符。产生大于 64 位结果的数据类型。

操作数的大小必须相同。石膏将 0 垫以填补尺寸差异

必须注意确保数据和密钥的大小相同,因为任何长度差异都将输出原始数据或密钥,因为任何与 0 异或的值都会给出原始数据。上面表达了担忧。

select CAST('a' as BINARY(1)) ^  CAST(0xACF123456 as BINARY(1));

返回包含 0xCD 的

BINARY(1)
:0x61 ^ 0xAC

请注意截断的顺序,

AC
而不是
56
,这可能与其他语言、平台或之前用法(即发布的代码)的预期结果不匹配。如果需要兼容性,请反转字节顺序(0x563412CF0A)。

您可以

HEX
结果:

select HEX(CAST('Hello World!' as BINARY(12)) ^ CAST(0xACF123456ACF123456ACF123 as BINARY(12)));

'E4944F2905EF455B24C09502'

反转(注意上面字符串中添加的

0x
):

select CAST(CAST(0xE4944F2905EF455B24C09502 as BINARY(12)) ^ CAST(0xACF123456ACF123456ACF123 as BINARY(12)) as CHAR(12));

“世界你好!”

限制

BINARY(n)
大小
n
表示为字节数,因此数据和密钥必须对齐为8位。
ACF123456
的非对齐键需要变为
ACF1234560
0ACF123456
才能满足对齐要求。

注意:上述字节反转的实现由“0x563412CF0A”中的“0A”给出。

此解决方案对于已知长度的字符串或动态生成的 SQL 语句有效,因为传递给

size
Binary(size)
不能是函数或参数。

© www.soinside.com 2019 - 2024. All rights reserved.