簡體   English   中英

簡短,不區分大小寫的字符串混淆策略

[英]Short, case-insensitive string obfuscation strategy

我正在尋找一種方法來識別(即編碼解碼)一組帶有一個令牌的Java字符串。 標識不應涉及DB持久性。 到目前為止,我已經研究過Base64編碼和DES加密,但就以下要求而言,兩者都不是最佳的:

  • 令牌應盡可能短
  • 令牌應該對套管不敏感
  • 令牌應該在URLEncoder / Decoder往返中存活(即將在URL中使用)

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM