[英]Short, case-insensitive string obfuscation strategy
我正在尋找一種方法來識別(即編碼和解碼)一組帶有一個令牌的Java字符串。 標識不應涉及DB持久性。 到目前為止,我已經研究過Base64編碼和DES加密,但就以下要求而言,兩者都不是最佳的:
Base32是我最好的投手還是有更好的選擇? 請注意,我主要對縮短和混淆集合感興趣,加密/安全性並不重要。
什么是文本的結構(即字符串集)? 您可以使用它的知識以縮短的形式對其進行編碼。 例如,如果您有大的基數十進制數“1234567890”,您可以將其轉換為36個基數,這將更短。
否則看起來你正在嘗試發明一個通用歸檔器。
如果您不關心長度,那么是的,基於字母的編碼器(例如Base32)處理是唯一的選擇。
此外,如果文本足夠大,也許你可以通過gzipping來節省一些空間。
Rot13會混淆,但不會縮短。 Zip縮短(通常)但不會在URL往返中存活。 加密不會縮短,也可能會延長。 哈希縮短但是單向。 你沒有一個簡單的問題。 Base32不區分大小寫,但比Base64占用更多空間,而不是。 我懷疑你將不得不放棄或修改你的要求。 哪些要求最重要哪個最不重要?
我花了一些時間在這上面,我有一個很好的解決方案。
編碼為base64,然后編碼為使用0-9a-v的自定義base32。 基本上,你一次布局6位(你的字符是0-9a-zA-Z),然后一次編碼5。 這幾乎不會產生任何額外的空間。 例如, ABCXYZdefxyz123789
編碼為i9crnsuj9ov1h8o4433i14
這是一個有效的實現,包括一些證明它不區分大小寫的測試代碼:
// Note: You can add 1 more char to this if you want to
static String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static String decodeToken(String encoded) {
// Lay out the bits 5 at a time
StringBuilder sb = new StringBuilder();
for (byte b : encoded.toLowerCase().getBytes())
sb.append(asBits(chars.indexOf(b), 5));
sb.setLength(sb.length() - (sb.length() % 6));
// Consume it 6 bits at a time
int length = sb.length();
StringBuilder result = new StringBuilder();
for (int i = 0; i < length; i += 6)
result.append(chars.charAt(Integer.parseInt(sb.substring(i, i + 6), 2)));
return result.toString();
}
private static String generateToken(String x) {
StringBuilder sb = new StringBuilder();
for (byte b : x.getBytes())
sb.append(asBits(chars.indexOf(b), 6));
// Round up to 5 bit multiple
// Consume it 5 bits at a time
int length = sb.length();
sb.append("00000".substring(0, length % 5));
StringBuilder result = new StringBuilder();
for (int i = 0; i < length; i += 5)
result.append(chars.charAt(Integer.parseInt(sb.substring(i, i + 5), 2)));
return result.toString();
}
private static String asBits(int index, int width) {
String bits = "000000" + Integer.toBinaryString(index);
return bits.substring(bits.length() - width);
}
public static void main(String[] args) {
String input = "ABCXYZdefxyz123789";
String token = generateToken(input);
System.out.println(input + " ==> " + token);
Assert.assertEquals("mixed", input, decodeToken(token));
Assert.assertEquals("lower", input, decodeToken(token.toLowerCase()));
Assert.assertEquals("upper", input, decodeToken(token.toUpperCase()));
System.out.println("pass");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.