[英]simple symmetric encryption of long to String (and back) in java
我正在寻找一种将long转换为String并以“隐藏” long值的方式转换的简单方法。
我希望避免为此功能在项目中添加另一个.jar。
它不必是难以破解的加密,只是让经验不足的人随意看。
加成:
我的目的是在用户不知道计数器值(类似于tinyURL的哈希值)的情况下,将一个计数器值(类型为long)作为跟踪参数附加到URL上,以便servlet在URL时知道计数器的值。被点击。
谢谢
如果
X * Y = 1 (mod 2^32)
然后
A * (X * Y) = A (mod 2^32)
(A * X) * Y = A (mod 2^32)
因此,您可以通过将某些32位数字乘以X来“加密”,然后再通过乘以Y来“解密”。您所需要做的就是找到一些满足条件的非平凡X和Y。
例如,(X,Y)=(3766475841,1614427073)或(699185821,3766459317)。 我只是用一个简单的蛮力程序发现了它们。
一旦有了A * X,您就可以使用Base-64或十六进制或URL中的某些类似方案对其进行编码。 我建议使用Base64,因为它占用的空间更少,并且看起来相当“随机”。
如果您只是感到困惑,那么一些琐碎的事情
long->字符串->每个字符的char数组,与先前的输出值(第一个字符之前的任意值)进行XOR char数组->字符串
为了揭示每个字符,对与前一个混淆的输入值进行XOR(第一个字符之前具有一些任意值)
嗯……没有更多细节,很难为此找到解决方案。 您可以做很多不同的事情来实现自己的目标……我想。
您可以将其与随机数进行XOR运算并存储两个数字。 当您的算法公开使用时(例如,如果您想将其放在开源中),这显然将无法工作。
或者,您可以使用一些对称加密算法,例如Twofish或Serpent。
如果将数字存储在客户端系统上并由客户端应用程序评估,那么所有这些都将是徒劳的。 分发应用程序后,客户端便可以访问其存储的所有内容。 如果信息有价值,则在您的应用程序发布后不久即可使用解密程序。 如果这不值得,那又何必呢?
我喜欢使用Long.toString(value,36)。 这将在基数为36的情况下打印数字,该数字是紧凑的,尽管是秘密的(假设数字> = 10),可以使用Long.parseLong(text,36)进行解析
带有一次性填充 (OTP)的XOR提供了完美的保密性。 我使用OTP编写了一个加密整数的密码。 我只是为了适应您的要求而对其进行了修改。 它将加长的盐加密成一个长为24字符的十六进制字符串,
-3675525778535888036 => 4fe555ca33021738a3797ab2
-6689673470125604264 => 76092fda5cd67e93b18b4f2f
8956473951386520443 => 0fb25e533be315bdb6356a2a
4899819575233977659 => 7cf17d74d6a2968370fbe149
这是代码,
public class IntegerCipher {
// This is for salt so secure random is not needed
private static Random PRNG = new Random();
private String secret;
public IntegerCipher(String secret) {
if (secret.length() < 4)
throw new IllegalArgumentException("Secret is too short");
this.secret = secret;
}
public String encrypt(long value) {
int salt = PRNG.nextInt();
long otp = generatePad(salt);
long cipher = value ^ otp;
return String.format("%08x%016x", salt, cipher);
}
public long decrypt(String ciphertext) {
if (ciphertext.length() != 24)
throw new IllegalArgumentException("Invalid cipher text");
try {
int salt = (int) Long.parseLong(ciphertext.substring(0, 8), 16);
long cipher = Long.parseLong(ciphertext.substring(8, 16), 16) << 32
| Long.parseLong(ciphertext.substring(16), 16);
long otp = generatePad(salt);
return cipher ^ otp;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid hex value: "
+ e.getMessage());
}
}
private long generatePad(int salt) {
String saltString = Integer.toString(salt);
String lpad = saltString + secret;
String rpad = secret + saltString;
return ((long) lpad.hashCode()) << 32 | (long) rpad.hashCode();
}
public static void main(String[] args) {
IntegerCipher cipher = new IntegerCipher("Top Secret");
Random rand = new Random();
for (int i = 0; i < 100; i++) {
Long n = rand.nextLong();
String ciphertext = cipher.encrypt(n);
Long m = cipher.decrypt(ciphertext);
System.out.printf("%24d => %s\n", n, ciphertext);
assert(m == n);
}
}
}
为了以确定性方式加密短明文,您可能需要看看FFSEM 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.