package com.vividsolutions.jump.util;
import java.util.*;
/**
* Provides a simple encyrption/decryption mechanism for ASCII string values.
* The algorithm does not provide strong encryption, but serves
* as a way of obfuscating the value of short strings (such as passwords).
* The code symbol set is drawn from the set of printable ASCII symbols.
* The encrypted strings are longer than the clear text (roughly double in length).
* A random element is used, so that different encryptions of the same clear
* text will result in different encodings.
*/
public class SimpleStringEncrypter
{
private static final String INVALID_CODE_STRING_MSG = "Invalid code string";
private static String codeSymbols =
"ABCDEFGHIJKLMNOP"
+ "abcdefghijklmnop"
+ "QRSTUVWXYZ012345"
+ "qrstuvwxyz6789@$";
/**
* Creates a new encrypter
*/
public SimpleStringEncrypter() {
}
/**
* Encrypts a string.
*
* @param clearText the string to encrypt
* @return the encryted code
*/
public String encrypt(String clearText)
{
char[] code = new char[clearText.length() * 2];
for (int i = 0; i < clearText.length(); i++) {
char c = clearText.charAt(i);
setEncryptedSymbol(c, code, 2 * i);
}
return new String(code);
}
public void setEncryptedSymbol(char c, char[] code, int i)
{
int charVal = c;
int nibble0 = charVal & 0xf;
int nibble1 = charVal >> 4;
code[i] = encodeNibble(nibble0);
code[i + 1] = encodeNibble(nibble1);
}
private char encodeNibble(int val)
{
int random4 = (int) (4 * Math.random());
int randomOffset = 16 * random4;
return codeSymbols.charAt(val + randomOffset);
}
/**
* Decrypts a code string.
*
* @param codeText the code to decrypt
* @return the clear text for the code
*
* @throws IllegalArgumentException if the code string is invalid
*/
public String decrypt(String codeText)
{
if (codeText.length() % 2 != 0)
throw new IllegalArgumentException(INVALID_CODE_STRING_MSG);
char[] clear = new char[codeText.length() / 2];
for (int i = 0; i < codeText.length() / 2; i++) {
char symbol0 = codeText.charAt(2 * i);
char symbol1 = codeText.charAt(2 * i + 1);
clear[i] = decryptedChar(symbol0, symbol1);
}
return new String(clear);
}
private char decryptedChar(char symbol0, char symbol1)
{
int nibble0 = decodeNibble(symbol0);
int nibble1 = decodeNibble(symbol1);
int charVal = nibble1 << 4 | nibble0;
return (char) charVal;
}
private int decodeNibble(int symbolValue)
{
int nibbleValue = codeSymbols.indexOf(symbolValue);
if (nibbleValue < 0)
throw new IllegalArgumentException(INVALID_CODE_STRING_MSG);
return nibbleValue % 16;
}
}