[英]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.