Простой алгоритм для смешивания/обфускации строки с заранее заданными символами - программирование
Подтвердить что ты не робот

Простой алгоритм для смешивания/обфускации строки с заранее заданными символами

У меня есть строка следующим образом:

  • Его длина равна 10.
  • Он представляет базу 36 и включает в себя цифры и прописные буквы.
  • Происхождение строки - это последовательность, сгенерированная базой данных (то есть от 1 и вверх), которая преобразуется в базу 36.

Моя проблема заключается в том, что результаты преобразования в базовое 36 преобразования также последовательны/последовательно; например:

    ID: 1402 -> 000000012Y    
    ID: 1403 -> 000000012Z    
    ID: 1404 -> 0000000130   
    ID: 1404 -> 0000000131  
    ID: 1404 -> 0000000132

Я ищу короткий простой алгоритм, который может смешать результат базы 36, где:

  • Я могу использовать только допустимую базовую 36 символов (цифры и прописные буквы).
  • Алгоритм предназначен только для обфускации/смешивания базовой строки 36; Мне не нужно шифрование и т.д.
  • Основная проблема здесь в том, что результат не будет последовательным.
  • Мне нужно иметь возможность deobfuscate/demix результат обфускации.

Я попробовал его с некоторой логикой смещения символов, но я застрял в последовательном результате. Думаю, мне нужно добавить здесь математический аспект.

Я бы оценил любые идеи как можно проще и, если возможно, с помощью примера кода.

4b9b3361

Ответ 1

Вы ищете что-то вроде этого?

import java.util.Locale;

public class Obfuscate {

    //adjust to suit:
    final static int feistelRounds = 4;
    final static int randRounds = 4;
    final static int seed = 12345;

    // modulus for half a string:
    final static int mod = 60466176; //36^5

    private static int f (int x) {
        // http://en.wikipedia.org/wiki/Linear_congruential_generator
        final int a = 12+1;
        final int c = 1361423303;
        x = (x + seed) % mod;
        int r = randRounds;
        while (r-- != 0) {
            x = (a*x+c) % mod;
        }
        return x;
    }

    public static String obfuscate (int i) {
        int a = i / mod;
        int b = i % mod;
        int r = feistelRounds;
        while (r-- != 0) {
            a = (a + f(b)) % mod;
            b = (b + f(a)) % mod;
        }
        return pad5(Integer.toString(a, 36)) + pad5(Integer.toString(b, 36));
    }

    public static int illuminate (String s) {
        int a = Integer.valueOf(s.substring(0,5),36);
        int b = Integer.valueOf(s.substring(5,10),36);
        int r = feistelRounds;
        while (r-- != 0) {
            b = (b - f(a)) % mod;
            a = (a - f(b)) % mod;
        }
        // make the modulus positive:
        a = (a + mod)%mod;
        b = (b + mod)%mod;

        return a*mod+b;
    }

    public static String pad5(String s) {
        return String.format("%5s", s).replace(' ', '0').toUpperCase(Locale.ENGLISH);
    }

    public static String pad10(String s) {
        return String.format("%10s", s).replace(' ', '0').toUpperCase(Locale.ENGLISH);
    }

    // demonstration
    public static void main(String[] args) {
        for (int i = 0; i<20; i++) {
            System.out.printf("%08d -> %s -> %08d\n", i, obfuscate(i), illuminate(obfuscate(i)));
        }
    }
}

выход:

00000000 -> P2TH9ZW2VI -> 00000000
00000001 -> G47GI9ZR9S -> 00000001
00000002 -> 75LFRK3FO2 -> 00000002
00000003 -> Y6ZF0U742C -> 00000003
00000004 -> P8DE94ASGM -> 00000004
00000005 -> G9RDIEEGUW -> 00000005
00000006 -> 7B5CROI596 -> 00000006
00000007 -> YCJC0YLTNG -> 00000007
00000008 -> PDXB98PI1Q -> 00000008
00000009 -> GFBAIIT6G0 -> 00000009
00000010 -> 7GP9RSWUUA -> 00000010
00000011 -> YI39030J8K -> 00000011
00000012 -> PJH89D47MU -> 00000012
00000013 -> GKV7IN7W14 -> 00000013
00000014 -> 7M96RXBKFE -> 00000014
00000015 -> YNN607F8TO -> 00000015
00000016 -> PP159HIX7Y -> 00000016
00000017 -> GQF4IRMLM8 -> 00000017
00000018 -> 7RT3R1QA0I -> 00000018
00000019 -> YT730BTYES -> 00000019

В принципе, это игрушка, совершенно незащищенная, хотя и забавная для написания, алгоритм шифрования. (Шифрование - это то, что вы просили --- вывод, который непонятен для других, но обратимый вами.) Я реализовал сеть Feistel (http://en.wikipedia.org/wiki/Feistel_cipher), используя простую функцию prng как функцию f.

Результаты довольно хороши, правда? DES, как было предложено выше, будет более безопасным. Но, если вы предпочтете изобретать колесо (я немного борюсь с этим импульсом), а реальная безопасность - это не проблема, это разумное место для начала. BTW, DES также базируется на сети Feistel.

На самом деле в зависимости от ваших требований может существовать решение без шифрования. Если это, скажем, код купона, который нужно проверить, но не догадаться, я бы просто создал таблицу в моей базе данных, связывающую идентификатор с случайно генерируемым 10-символьным кодом (или добавить столбец кода в существующую таблицу купоны) и искать их по мере их поступления. Это, конечно же, потребует, чтобы программное обеспечение для кодирования и восстановления имело доступ к одной и той же базе данных или чтобы иметь возможность общаться.

Ответ 2

Как насчет наличия массива с 36 символами в случайном порядке? Что-то вроде одноразового шифрования пэдов, но с фиксированной пэдом:

static String source="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static String target="Q5A8ZWS0XEDC6RFVT9GBY4HNU3J2MI1KO7LP";

public static String obfuscate(String s) {
    char[] result= new char[10];
    for (int i=0;i<s.length();i++) {
        char c=s.charAt(i);
        int index=source.indexOf(c);
        result[i]=target.charAt(index);
    }

    return new String(result);
}

public static String unobfuscate(String s) {
    char[] result= new char[10];
    for (int i=0;i<s.length();i++) {
        char c=s.charAt(i);
        int index=target.indexOf(c);
        result[i]=source.charAt(index);
    }

    return new String(result);
}

Итак, строка из 10 символов, например "HELLO12345", становится "0ZCCF2MI1K". Обфускация, но не зашифрованная

Ответ 3

Просто обратный бит на вашем счетчике, прежде чем делать кодировку base36. Что-то вроде этого

public static void main(String[] args) {
    for (int i = 1400; i < 1420; i++) {
        String base36 = Integer.toString(i, 36);
        String reverse = Integer.toString(Integer.reverse(i << 1), 36);

        System.out.println("i: " + i + "  base36: " + base36 + 
                                       "  reverse: " + reverse);
    }
}

Результат:

i: 1400  base36: 12w  reverse: 48ya68
i: 1401  base36: 12x  reverse: m08ao0
i: 1402  base36: 12y  reverse: d4laf4
i: 1403  base36: 12z  reverse: uvvaww
i: 1404  base36: 130  reverse: 8orsao
i: 1405  base36: 131  reverse: qg1ssg
i: 1406  base36: 132  reverse: hkesjk
i: 1407  base36: 133  reverse: zbot1c
i: 1408  base36: 134  reverse: 8464g
i: 1409  base36: 135  reverse: hze6m8
i: 1410  base36: 136  reverse: 93r6dc
i: 1411  base36: 137  reverse: qv16v4
i: 1412  base36: 138  reverse: 4nxo8w
i: 1413  base36: 139  reverse: mf7oqo
i: 1414  base36: 13a  reverse: djkohs
i: 1415  base36: 13b  reverse: vauozk
i: 1416  base36: 13c  reverse: 2g0x6o
i: 1417  base36: 13d  reverse: k7axog
i: 1418  base36: 13e  reverse: bbnxfk
i: 1419  base36: 13f  reverse: t2xxxc

Ответ 4

Это общее решение, это очень быстрый алгоритм, который может обрабатывать любую строку в любой кодировке.

Исходный код

public class Translator {

    private static final String key = "Zx" + Math.log(2) / 3;

    public static String obfuscate(String s) {
        char[] result = new char[s.length()];
        for (int i = 0; i < s.length(); i++) {
            result[i] = (char) (s.charAt(i) + key.charAt(i % key.length()));
        }

        return new String(result);
    }

    public static String unobfuscate(String s) {
        char[] result = new char[s.length()];
        for (int i = 0; i < s.length(); i++) {
            result[i] = (char) (s.charAt(i) - key.charAt(i % key.length()));
        }

        return new String(result);
    }
}

Использование

String obfuscate = Translator.obfuscate("Hi there");
System.out.println(obfuscate + " - " + Translator.unobfuscate(obfuscate));

Вывод:

¢áP¢£ - Hi there

Ответ 5

Если это не домашнее задание, я бы предложил вам использовать кодировку Base64: new sun.misc.BASE64Encoder().encode(string.getBytes()).

Это не шифрует строку, но делает ее нечитаемой.

Если вы действительно хотите зашифровать строку, используйте java-криптографический API, например:

        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, password);
        String encrypedStr = base64encoder.encode(cipher.doFinal(cleartext));

Теперь encryptedString зашифрован и сохраняется в формате base64.

Вы можете легко найти, как расшифровать строку обратно. Удачи.