Java 不同字母长度的替换密码

Java 不同字母长度的替换密码,java,string,algorithm,encryption,Java,String,Algorithm,Encryption,我想实现一个简单的替换密码来屏蔽URL中的私有ID 我知道我的ID会是什么样子(大写ASCII字母、数字和下划线的组合),而且它们会很长,因为它们是组合键。我希望使用更长的字母表来缩短生成的代码(我希望使用大写和小写ASCII字母、数字和其他任何东西)。所以我输入的字母表是 [A-Z0-9_] (37 chars) 我的输出字母表是 [A-Za-z0-9] (62 chars) 因此,几乎50%的压缩量是合理的 假设我的URL如下所示: /my/page/GFZHFFFZFZTFZTF_24

我想实现一个简单的替换密码来屏蔽URL中的私有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,然后使用第二个字母表写出该数字。有没有类似的示例代码?有一些类似的逻辑,但它是硬编码使用标准的数字行为

有什么想法吗


我正在使用Java来实现这一点,但是任何其他语言中的代码或伪代码当然也很有用。

这根本不是替换密码,但您的问题已经很清楚了

看看Base85:

对于Java(由维基百科文章间接链接):


令人费解的
字符。最大基数只有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();
    }
}
一些观察
  • 如果数字可以超过
    long
  • 您可以在符号
    字符串中洗牌
    字符
    ,只需坚持一个“秘密”排列即可
关于“50%压缩”的注释 通常情况下,不能期望基62字符串的长度大约为基36字符串的一半。以下是以10、20和30为基数的
Long.MAX_值

    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"
    );

我现在有一个有效的解决方案,您可以在这里找到:

问题是a)通过这一部分,我在长代码中丢失了精度:

value = value.add(//
    BigInteger.valueOf((long) Math.pow(alphabet.length, i)) // error here
        .multiply(
            BigInteger.valueOf(ArrayUtils.indexOf(alphabet, c))));
(只是时间不够长)


b)每当我有一个以字母表中偏移量0处的字符开头的文本时,这个字符就会被删除,因此我需要添加一个长度字符(这里一个字符就可以了,因为我的代码永远不会像字母表那么长)

是的,听起来和我目前正在写的代码一模一样。当我完成后,我会发布我自己的答案。这是一个正确的方向,但我希望有一些更适合我自己需要的东西
value = value.add(//
    BigInteger.valueOf((long) Math.pow(alphabet.length, i)) // error here
        .multiply(
            BigInteger.valueOf(ArrayUtils.indexOf(alphabet, c))));