簡體   English   中英

Java中長到字符串(和返回)的簡單對稱加密

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

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