Thursday, May 6, 2010

URL Encoding Decoding In Blackberry or J2ME

URLs often contains characters outside the ASCII set, the URL has to be converted to valid ASCII format using URL encoding which replaces unsafe ASCII characters with "%" followed by two hexadecimal digits corresponding to the character values in the ISO-8859-1 character-set.

Following is the code to achieve just that. It is tested with Blackberry but can be used in J2ME applications too.

class UrlEncoderDecoder
{
static final String HEX_DIGITS = "0123456789ABCDEF";


/**
* @param arrData The string to encode
* @return The URL-encoded string
*/
protected static String fnUrlEncode(byte[] arrData)
{
StringBuffer strResult = new StringBuffer();

for(int i = 0; i < arrData.length; i++)
{
char c = (char)arrData[i];

switch( c )
{
case '_':
case '.':
case '*':
case '-':
case '/':
{
strResult.append(c);
break;
}
case ' ':
{
strResult.append('+');
break;
}
default:
{
if((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9'))
{
strResult.append( c );
}
else
{
strResult.append('%');
strResult.append(HEX_DIGITS.charAt((c & 0xF0) >> 4 ));
strResult.append(HEX_DIGITS.charAt(c & 0x0F ));
}
}
}
} // for

return strResult.toString();
}

/**
* @param arrData The byte array containing the bytes of the string
* @return A decoded String
*/
protected static String fnUrlDecode(byte[] arrData)
{
String strDecodedData = "";

if(null != arrData)
{
byte[] arrDecodeBytes = new byte[arrData.length];

int nDecodedByteCount = 0;

try
{
for(int i = 0; i < arrData.length; i++ )
{
switch(arrData[i])
{
case '+':
{
arrDecodeBytes[nDecodedByteCount++] = (byte) ' ';
break ;
}
case '%':
{
arrDecodeBytes[nDecodedByteCount++] = (byte)((HEX_DIGITS.indexOf(arrData[++i]) << 4) +
(HEX_DIGITS.indexOf(arrData[++i])) );
break ;
}
default:
{
arrDecodeBytes[nDecodedByteCount++] = arrData[i];
}
}
}

strDecodedData = new String(arrDecodeBytes, 0, nDecodedByteCount) ;
}
catch(Exception e)
{
}
}

return strDecodedData;
}
}

Tuesday, May 4, 2010

AES Encryption

AES is a standard private-key or symmetric cryptography. It supports combination of key and block sizes of 128, 192, and 256.

In Blackberry AES encryption can be achieved as follows:

import java.io.*;
import net.rim.device.api.io.*;
import net.rim.device.api.crypto.*;

import net.rim.device.api.util.*;

/**
* This is utility class for doing AES encryption and decryption.
* It uses 'PKCS5' as padding.
*
*/
public class AESUtil
{
/**
* Encrypts data using specified key data using AES algorithm.
*
* @param arrKeyData Key data that will be used for encryption.
* @param arrData Data to be encrypted.
*
* @return Encryped data in byte array.
*/
public static byte[] fnEncrypt(byte[] arrKeyData, byte[] arrData)
throws CryptoException, IOException
{
// Create the AES key to use for encrypting the data.
// This will create an AES key using as much of the keyData as possible.
AESKey oKey = new AESKey(arrKeyData);

AESEncryptorEngine oEngine = new AESEncryptorEngine(oKey);

PKCS5FormatterEngine oPKCS5Engine = new PKCS5FormatterEngine(oEngine);

ByteArrayOutputStream oOutput = new ByteArrayOutputStream();
BlockEncryptor encryptor = new BlockEncryptor(oPKCS5Engine, oOutput);

encryptor.write(arrData);
encryptor.close();
oOutput.close();


return oOutput.toByteArray();
}

/**
* Decrypts encrypted data using specified key data using AES algorithm.
*
* @param arrKeyData Key data that will be used for decryption.
* @param arrEncryptedData Encryped data that is to be decrypted.
*
* @return Decrypted data in byte array.
*/
public static byte[] fnDecrypt(byte[] arrKeyData, byte[] arrEncryptedData)
throws CryptoException, IOException
{
// Create the AES key to use for encrypting the data.
// This will create an AES key using as much of the keyData as possible.
AESKey oKey = new AESKey(arrKeyData);

AESDecryptorEngine oEngine = new AESDecryptorEngine(oKey);

PKCS5UnformatterEngine oUEngine = new PKCS5UnformatterEngine(oEngine);

ByteArrayInputStream oInput = new ByteArrayInputStream(arrEncryptedData);
BlockDecryptor oDecryptor = new BlockDecryptor(oUEngine, oInput);


byte[] arrTemp = new byte[100];
DataBuffer oBuffer = new DataBuffer();

int nBytesRead = -1;

while(-1 < (nBytesRead = oDecryptor.read(arrTemp)))
{
oBuffer.write(arrTemp, 0, nBytesRead );
}

return oBuffer.getArray();
}
}