How do encrypt/decrypt a long or int using the Bouncy Castle crypto routines for BlackBerry? I know how to encrypt/decrypt a String. I can encrypt a long but can't get a long to decrypt properly.
Some of this is poorly done, but I'm just trying stuff out at the moment.
I've included my entire crypto engine here:
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
public class CryptoEngine
{
// Global Variables
// Global Objects
private static AESFastEngine engine;
private static BufferedBlockCipher cipher;
private static KeyParameter key;
public static boolean setEncryptionKey(String keyText)
{
// adding in spaces to force a proper key
keyText += " ";
// cutting off at 128 bits (16 characters)
keyText = keyText.substring(0, 16);
keyText = HelperMethods.cleanUpNullString(keyText);
byte[] keyBytes = keyText.getBytes();
key = new KeyParameter(keyBytes);
engine = new AESFastEngine();
cipher = new PaddedBufferedBlockCipher(engine);
// just for now
return true;
}
public static String encryptString(String plainText)
{
try
{
byte[] plainArray = plainText.getBytes();
cipher.init(true, key);
byte[] cipherBytes = new byte[cipher.getOutputSize(plainArray.length)];
int cipherLength = cipher.processBytes(plainArray, 0, plainArray.length, cipherBytes, 0);
cipher.doFinal(cipherBytes, cipherLength);
String cipherString = new String(cipherBytes);
return cipherString;
}
catch (DataLengthException e)
{
Logger.logToConsole(e);
}
catch (IllegalArgumentException e)
{
Logger.logToConsole(e);
}
catch (IllegalStateException e)
{
Logger.logToConsole(e);
}
catch (InvalidCipherTextException e)
{
Logger.logToConsole(e);
}
catch (Exception ex)
{
Logger.logToConsole(ex);
}
// else
return "";// default bad value
}
public static String decryptString(String encryptedText)
{
try
{
byte[] cipherBytes = encryptedText.getBytes();
cipher.init(false, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cipherBytes.length)];
int decryptedLength = cipher.processBytes(cipherBytes, 0, cipherBytes.length, decryptedBytes, 0);
cipher.doFinal(decryptedBytes, decryptedLength);
String decryptedString = new String(decryptedBytes);
// crop accordingly
int index = decryptedString.indexOf("\u0000");
if (index >= 0)
{
decryptedString = decryptedString.substring(0, index);
}
return decryptedString;
}
catch (DataLengthException e)
{
Logger.logToConsole(e);
}
catch (IllegalArgumentException e)
{
Logger.logToConsole(e);
}
catch (IllegalStateException e)
{
Logger.logToConsole(e);
}
catch (InvalidCipherTextException e)
{
Logger.logToConsole(e);
}
catch (Exception ex)
{
Logger.logToConsole(ex);
}
// else
return "";// default bad value
}
private static byte[] convertLongToByteArray(long longToConvert)
{
return new byte[] { (byte) (longToConvert >>> 56), (byte) (longToConvert >>> 48), (byte) (longToConvert >>> 40), (byte) (longToConvert >>> 32), (byte) (longToConvert >>> 24), (byte) (longToConvert >>> 16), (byte) (longToConvert >>> 8), (byte) (longToConvert) };
}
private static long convertByteArrayToLong(byte[] byteArrayToConvert)
{
long returnable = 0;
for (int counter = 0; counter < byteArrayToConvert.length; counter++)
{
returnable += ((byteArrayToConvert[byteArrayToConvert.length - counter - 1] & 0xFF) << counter * 8);
开发者_运维技巧 }
if (returnable < 0)
{
returnable++;
}
return returnable;
}
public static long encryptLong(long plainLong)
{
try
{
String plainString = String.valueOf(plainLong);
String cipherString = encryptString(plainString);
byte[] cipherBytes = cipherString.getBytes();
long returnable = convertByteArrayToLong(cipherBytes);
return returnable;
}
catch (Exception e)
{
Logger.logToConsole(e);
}
// else
return Integer.MIN_VALUE;// default bad value
}
public static long decryptLong(long encryptedLong)
{
byte[] cipherBytes = convertLongToByteArray(encryptedLong);
cipher.init(false, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cipherBytes.length)];
int decryptedLength = cipherBytes.length;
try
{
cipher.doFinal(decryptedBytes, decryptedLength);
}
catch (DataLengthException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalStateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InvalidCipherTextException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
long plainLong = convertByteArrayToLong(decryptedBytes);
return plainLong;
}
public static boolean encryptBoolean(int plainBoolean)
{
return false;
}
public static boolean decryptBoolean(int encryptedBoolean)
{
return false;
}
public static boolean testLongToByteArrayConversion()
{
boolean returnable = true;
// fails out of the bounds of an integer, the conversion to long from byte
// array does not hold, need to figure out a better solution
for (long counter = -1000000; counter < 1000000; counter++)
{
long test = counter;
byte[] bytes = convertLongToByteArray(test);
long result = convertByteArrayToLong(bytes);
if (result != test)
{
returnable = false;
Logger.logToConsole("long conversion failed");
Logger.logToConsole("test = " + test + "\n result = " + result);
}
// regardless
}
// the end
Logger.logToConsole("final returnable result = " + returnable);
return returnable;
}
}
It's probably the conversion from long -> byte[] -> String, in particular the conversion from String back into byte[]. You don't pass in an encoding for String.getBytes() so it's going to be using the default character encoding, which may be altering your data.
My suggestion is to expose encrypt/decrypt methods that take byte[] as an argument, to avoid String/byte[] conversion.
Also, you may want to take a look at the native RIM AES classes, AESEncryptorEngine and AESDecryptorEngine which may be faster than BouncyCastle (since they're native APIs) and require less code.
I just realized that with strong ciphers, the result length is usually/always greater than the length of the original. If it wasn't, a lookup table could be used. As such, its not possible to encrypt a long into a long every time, especially if it uses all 64 bits. If this doesn't make sense, see me for more info:
How do I encrypt a string and get a equal length encrypted string?
精彩评论