我想以以下格式加密/保护输入字符串“AB123456789000”(两个字母和 12 位数字),以便安全的“版本”可以在数据库中存储为长(数字)。
我尝试过 RC2 加密,但它给了我 128 位,不适合 64 位长。
我想以以下格式加密/保护输入字符串“AB123456789000”(两个字母和 12 位数字),以便安全的“版本”可以在数据库中存储为长(数字)。
我尝试过 RC2 加密,但它给了我 128 位,不适合 64 位长。
首先,我必须有一点咆哮。
byte[]
,无需将其表示为一个long
。每个数据库系统也应该能够保存二进制 blob。回到将输入大小降至 64 位以下。
使用 ASCII,您的 14 个字母长字符串将是 14 字节(= 112)位,如果不压缩,它的加密将不适合 64 位。您可以通过说格式必须是2 个字母,然后是 12 个数字来作弊。对于编码,您将在其 ASCII 表示中逐字获取前两个字母。那将是 2*8 位 = 16 位。然后将 12 位数字作为一个整数,例如123456789000 = 0x1cbe991a08
5 个字节(= 40 位,它适合 a long
)。这里可能的最大数字9999999999
是0xe8d4a50fff
,所以仍然可以将所有内容保存在 5 个字节中。
总之,我们将有 2*8 位 + 5*8 位 = 56 位,它小到足以适合 RC2 加密的一个块,即 64 位。您可以将最后一个字节设置为0x00
.
因此,简而言之,明文的编码版本的 2 个字节将代表这两个字母的 ASCII 值,然后接下来的 5 个字节将是数字作为long
.
例如,
AB123456789000
将被编码为0x41421cbe991a08
( 'A' = 0x41, B = 0x42
, then 123456789000 = 0x1cbe991a08
)。您可以在 Java 和 C# 中编写编码和解码函数来实现这一点。
编码为 64 位可以非常简单:
public static long toId(String id) {
long numPart = Long.parseLong(id.substring(2));
long letterPart = Long.parseLong(id.substring(0, 2), 36);
long res = (letterPart << 40) | numPart;
System.out.println("Ids: " + id + " -> " + res);
return res;
}
public static void main(String[] args) {
toId("AB123456789000");
toId("AA000000000000");
toId("AA999999999999");
toId("ZZ000000000000");
toId("ZZ999999999999");
}
结果
Ids: AB123456789000 -> 408042270693896
Ids: AA000000000000 -> 406819302277120
Ids: AA999999999999 -> 407819302277119
Ids: ZZ000000000000 -> 1423867557969920
Ids: ZZ999999999999 -> 1424867557969919