用于将字符串与预定义字符混合/混淆的简单算法

boo*_*oom 15 java

我有一个字符串如下:

  • 它的长度是10.
  • 它代表基数36,因此包括数字和大写字母.
  • 字符串的起源是由数据库生成的序列(即从1开始向上),其被转换为基数36.

我的问题是转换到base 36转换的结果也是连续的/顺序的; 例如:

    ID: 1402 -> 000000012Y    
    ID: 1403 -> 000000012Z    
    ID: 1404 -> 0000000130   
    ID: 1404 -> 0000000131  
    ID: 1404 -> 0000000132
Run Code Online (Sandbox Code Playgroud)

我正在寻找一个简单的简单算法,可以将基数36的结果混合在一起:

  • 我只能使用允许的36个字符(数字和大写字母).
  • 该算法仅用于混淆/混合基数36串; 我不需要加密等
  • 这里的主要问题是结果不会是连续的.
  • 我需要能够对混淆结果进行反混淆/分离.

我尝试了一些变化的字符逻辑,但我陷入了连续的结果问题.
我想我需要在这里添加一些数学方面.

我将尽可能简单地感谢任何想法,如果可能的话,我会感谢代码示例.

may*_*Van 24

你在找这样的东西吗?

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)));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

基本上,这是一个玩具,完全不安全,虽然编写有趣的加密算法.(加密确实是你要求的 - 输出对别人来说是难以理解的,但你可以逆转.)我使用一个简单的prng 实现了一个Feistel网络(http://en.wikipedia.org/wiki/Feistel_cipher) f功能.

结果很漂亮,对吧?如上所述,DES将更安全.但是,如果你宁愿重新发明轮子(我自己也有点冲动)并且真正的安全性不是问题,这是一个合理的起点.顺便说一下,DES也是基于Feistel网络.

实际上,根据您的要求,可能存在基于非加密的解决方案.如果这是一个需要检查但没有猜到的优惠券代码,我只需在我的数据库中创建一个表,将id与随机生成的10个字符代码相关联(或者将代码列添加到现有的优惠券)并在他们进来时查看它们.这当然要求编码和恢复软件可以访问同一个数据库,或者能够进行通信.


Pab*_*ano 21

那么只有一个随机顺序的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);
}
Run Code Online (Sandbox Code Playgroud)

所以10个字符的字符串就像"HELLO12345"变成了"0ZCCF2MI1K".模糊,但未加密


Ily*_*man 7

这是一个通用的解决方案,这是一种非常快速的算法,可以处理任何编码中的任何字符串.

源代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

String obfuscate = Translator.obfuscate("Hi there");
System.out.println(obfuscate + " - " + Translator.unobfuscate(obfuscate));
Run Code Online (Sandbox Code Playgroud)

输出:

¢áP¢£ - Hi there
Run Code Online (Sandbox Code Playgroud)


Ale*_*exR 2

除非这是一项家庭作业,否则我建议您使用 Base64 编码:new sun.misc.BASE64Encoder().encode(string.getBytes())。

这不会加密字符串,但会使其不可读。

如果你确实想加密字符串,请使用java cryptography API,例如:

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

现在encryptedString已加密并以base64格式存储。

您可以轻松找到如何解密该字符串。祝你好运。

  • argh at string.getBytes() 未指定编码:// (3认同)