I have a string as follows:
Are you looking for something like this?
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)));
}
}
}
output:
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
Basically, this is a toy, totally non-secure, though fun to write, encryption algorithm. (Encryption really is what you asked for --- output that's unintelligible to others but reversible by you.) I've implemented a Feistel network (http://en.wikipedia.org/wiki/Feistel_cipher) using a simple prng as the f function.
The results are pretty, though, right? DES, as suggested above, would be more secure. But, if you'd rather reinvent the wheel (I struggle with that impulse a bit myself) and real security isn't a concern, this is a reasonable place to start. BTW, DES is also based on a Feistel network.
Actually, a non-encryption-based solution might exist, depending on your requirements. If this is, say, a coupon code that needs to be checked but not guessed, I'd just create a table in my database relating the id to a randomly-generated 10 character code (or add the code column to an existing table of coupons) and look them up as they come in. This would of course require the encoding and recovering software to have access to the same database, or to be able to communicate.
Just reverse the bits on your counter before doing the base36 encoding. Something like this
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);
}
}
Result:
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
This is a generic solution, this a very fast algorithm that can handle any string in any encoding.
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));
Output:
¢áP¢£ - Hi there
What about having just an array with the 36 characters in a random order? Something like a One-time pad encryption but with a fixed pad:
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);
}
So a 10 characters string like "HELLO12345"
becomes "0ZCCF2MI1K"
. Obfuscated, but not encrypted
Unless this is a homework assignment I'd suggest you to use Base64 encoding: new sun.misc.BASE64Encoder().encode(string.getBytes())
.
This does not encrypt string but makes it unreadable.
If you really want to encrypt the string use java cryptography API, e.g:
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, password);
String encrypedStr = base64encoder.encode(cipher.doFinal(cleartext));
Now encryptedString
is encrypted and stored in base64 format.
You can easily find how to decrypt the string back. Good luck.