gpt4 book ai didi

java - 具有不同字母长度的替换密码

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:29:11 24 4
gpt4 key购买 nike

我想实现一个简单的替换密码来屏蔽 URL 中的私有(private) ID。

我知道我的 ID 会是什么样子(大写 ASCII 字母、数字和下划线的组合),而且它们会相当长,因为它们是组合键。我想使用更长的字母表来缩短生成的代码(我想使用大写和小写的 ASCII 字母、数字,别无其他)。所以我传入的字母表是

[A-Z0-9_] (37 chars)

我即将离任的字母表是

[A-Za-z0-9] (62 chars)

因此 压缩近 50% 合理的压缩量将可用。

假设我的 URL 如下所示:

/my/page/GFZHFFFZFZTFZTF_24_F34

我希望它们看起来像这样:

/my/page/Ft32zfegZFV5

显然,两个数组都将被打乱以带来一些随机顺序。

这不一定是安全的。如果有人弄明白了:很好,但我不希望该方案显而易见。

我想要的解决方案是将字符串转换为基数 37 的整数表示,将基数转换为 62,然后使用第二个字母表写出该数字。有没有可用的示例代码来做类似的事情? Integer.parseInt()具有一些类似的逻辑,但它被硬编码为使用标准数字行为。

有什么想法吗?

我正在使用 Java 来实现它,但是任何其他语言的代码或伪代码当然也有帮助。

最佳答案

莫名其妙的 Character.MAX_RADIX 只有 36,但你总是可以编写自己的基本转换例程。以下实现不是高性能的,但它应该是一个很好的起点:

import java.math.BigInteger;
public class BaseConvert {
static BigInteger fromString(String s, int base, String symbols) {
BigInteger num = BigInteger.ZERO;
BigInteger biBase = BigInteger.valueOf(base);
for (char ch : s.toCharArray()) {
num = num.multiply(biBase)
.add(BigInteger.valueOf(symbols.indexOf(ch)));
}
return num;
}
static String toString(BigInteger num, int base, String symbols) {
StringBuilder sb = new StringBuilder();
BigInteger biBase = BigInteger.valueOf(base);
while (!num.equals(BigInteger.ZERO)) {
sb.append(symbols.charAt(num.mod(biBase).intValue()));
num = num.divide(biBase);
}
return sb.reverse().toString();
}
static String span(char from, char to) {
StringBuilder sb = new StringBuilder();
for (char ch = from; ch <= to; ch++) {
sb.append(ch);
}
return sb.toString();
}
}

然后你可以有一个像下面这样的 main() 测试工具:

public static void main(String[] args) {
final String SYMBOLS_AZ09_ = span('A','Z') + span('0','9') + "_";
final String SYMBOLS_09AZ = span('0','9') + span('A','Z');
final String SYMBOLS_AZaz09 = span('A','Z') + span('a','z') + span('0','9');

BigInteger n = fromString("GFZHFFFZFZTFZTF_24_F34", 37, SYMBOLS_AZ09_);

// let's convert back to base 37 first...
System.out.println(toString(n, 37, SYMBOLS_AZ09_));
// prints "GFZHFFFZFZTFZTF_24_F34"

// now let's see what it looks like in base 62...
System.out.println(toString(n, 62, SYMBOLS_AZaz09));
// prints "ctJvrR5kII1vdHKvjA4"

// now let's test with something we're more familiar with...
System.out.println(fromString("CAFEBABE", 16, SYMBOLS_09AZ));
// prints "3405691582"

n = BigInteger.valueOf(3405691582L);
System.out.println(toString(n, 16, SYMBOLS_09AZ));
// prints "CAFEBABE"
}

一些观察

    如果数字可以超过 long
  • BigInteger 可能是最简单的
  • 您可以在符号 String 中打乱 char,只需坚持一个“ secret ”排列

关于“50% 压缩”的注意事项

您通常不能期望 base 62 字符串的长度大约是 base 36 字符串的一半。这是以 10、20 和 30 为基数的 Long.MAX_VALUE:

    System.out.format("%s%n%s%n%s%n",
Long.toString(Long.MAX_VALUE, 10), // "9223372036854775807"
Long.toString(Long.MAX_VALUE, 20), // "5cbfjia3fh26ja7"
Long.toString(Long.MAX_VALUE, 30) // "hajppbc1fc207"
);

关于java - 具有不同字母长度的替换密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2863954/

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