我是黑莓开发新手,完成了使用AES / ECB / NoPadding进行加密和解密的任务。我使用下面的代码来自互联网。
加密方法:
public static byte[] encrypt( byte[] keyData,String message )
throws Exception
{
byte[] data = message.getBytes("UTF-8");
// Create the AES key to use for encrypting the data.
// This will create an AES key using as much of the keyData
// as possible.
if ((data.length % 16) != 0 ) {
StringBuffer buffer = new StringBuffer(message);
int moduleOut = data.length % 16;
int padding = 16 - moduleOut;
for(int i = 0 ; i < padding; i++){
buffer.append(" ");
}
data = buffer.toString().getBytes("UTF-8");
}
AESKey key = new AESKey( keyData);
NoCopyByteArrayOutputStream out = new NoCopyByteArrayOutputStream(data.length);
AESEncryptorEngine engine = new AESEncryptorEngine(key);
BlockEncryptor encryptor = new BlockEncryptor(engine, out);
encryptor.write(data,0,data.length);
int finalLength = out.size();
byte[] cbytes = new byte[finalLength];
System.arraycopy(out.toByteArray(), 0, cbytes, 0, finalLength);
// encryptor.close();
// out.close();
return cbytes;
}
解密方法:
public static byte[] decrypt(byte[] keyData, byte[] base64EncodedData)
throws CryptoException, IOException
{
// String base64EncodedData=new String(base64EncodedData);
byte[] cipherText =Base64ToBytes(new String(base64EncodedData));
// First, create the AESKey again.
AESKey key = new AESKey(keyData);
// Now, create the decryptor engine.
AESDecryptorEngine engine = new AESDecryptorEngine(key);
// Create the BlockDecryptor to hide the decryption details away.
ByteArrayInputStream input = new ByteArrayInputStream(cipherText);
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
// Now, read in the data.
byte[] temp = new byte[100];
DataBuffer buffer = new DataBuffer();
for (;;)
{
int bytesRead = decryptor.read(temp);
buffer.write(temp, 0, bytesRead);
if (bytesRead < 100)
{
// We ran out of data.
break;
}
}
byte[] plaintext = buffer.getArray();
return plaintext;
}
Base64到字节转换方法:
private static byte[] Base64ToBytes(String code) {
byte[] aesString = null;
try
{
aesString = Base64InputStream.decode(code);
}
catch (IOException ioe)
{
}
return aesString;
}
现在的问题是当我用上面的方法加密我的字符串时,我在字符串的末尾得到了填充的unicodes,这在服务器端是不能容忍的。
我知道这是由于PKCS5FormatterEngine及其正常情况,在使用此类时会在字符串末尾附加字符。
但是,如果我想使用AES / ECB方法加密和解密字符串,以及使用NoPadding也是如此。我知道ECB不是一种安全模式,只有服务器使用PHP并准备就绪,在Android和J2ME中运行良好。
请指导。如何绕过PKCS5FormatterEngine或加密而不进行任何填充。
更新
我尝试在Blackberry中使用Cipher类,因为我在Android和J2ME中使用它但在net_rim_api.jar中似乎不可用,即使我尝试下载bouncy castle jar文件和依赖类NoSuchAlogrithmException所以java.security jar(org.osgi.foundation) -1.0.0.jar),编译但是当我尝试运行它时停止说找到重复的类。在我为java.security保留的jar中有一些重复的类有一个问题。
如果你有解决方法,请告诉我。
答案更新: 我已使用完整的加密和解密代码更新我的代码,并检查答案以便更好地理解。
答案 0 :(得分:3)
一般来说不确定这是否真的是一个答案,但在这种特殊情况下它可能会有所帮助,所以我会这样添加它。
如果没有一些填充,你不能真正使用AES,因为AES处理不希望假设你提供的数据是16字节的倍数。但是,如果您实际上总是提供16个字节的倍数的缓冲区,那么您可以使用以下代码加密数据:
AESEncryptorEngine engine = new AESEncryptorEngine( key );
for ( int j = 0; j < ciphertext.length - 15; ) {
engine.encrypt(plainText, j, ciphertext, j);
j = j+16;
}
那你怎么确定这个在另一端好吗?它可能会也可能不会这样做 - 它实际上取决于转移的内容。
但是,例如,如果您传递XML数据,那么您可以附加空格以使数据达到16字节边界,这些将由服务器解密为空格,然后通过解析忽略。您可以将冗余填充字节添加到各种文件格式中,并且将忽略填充,这一切都取决于正在处理的文件格式。
<强>更新强>
鉴于实际数据是JSON并且我认为JSON将忽略尾随空格,我将采用的方法是在加密之前将空格附加到JSON数据。
因此将JSON字符串转换为字节:
byte [] jsonBytes = jsonString.getBytes("UTF-8");
如果您需要,请填写此内容:
if ( (jsonBytes.length % 16) != 0 ) {
// Now pad this with spaces
}
并且您可以加密结果而无需担心填充字节。