Java/Android:SealedObject 抛出 StreamCorruptedException
Java/Android: SealedObject throws StreamCorruptedException
我想加密和解密之前使用生成的 AES 密钥在 SealedObject 中加密的对象,该密钥也在 SealedObject 中保存和加密,但使用 RSA。
代码
Stack 是我的项目库和 Serializable 的一部分。每个名为 xxxStack 的对象都是 Stack 的子类。
摘自chat.protocol.secure.CryptoStack
相关属性
// encrypted Object
private SealedObject stack;
// cache for the Object
private transient Stack stackCache;
// encrypted AES key
private SealedObject key;
// cache for AES key which is used to encrypt and decrypt the Object
private transient SecretKey keyCache;
使用唯一的 AES 密钥加密缓存对象 (stackCache) 然后使用 public RSA 密钥加密并保存在堆栈中的方法
public void encrypt(Cipher c0) throws IllegalBlockSizeException, IOException{
/*
* Creates unique AES key for encrypting the Object
*/
KeyGenerator keyGen = null;
try {
keyGen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
keyGen.init(256);
keyCache = keyGen.generateKey();
/*
* Creating AES Cipher for encryption
*/
Cipher c1 = null;
try {
c1 = Cipher.getInstance("AES");
c1.init(Cipher.ENCRYPT_MODE, keyCache);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* Encrypts Object
*/
stack = new SealedObject(stackCache, c1);
/*
* Encrypts AES key with a Cipher given as argument (intended to be a public RSA key initialized Cipher)
*/
key = new SealedObject(keyCache, c0);
}
解密加密的AES密钥以解密保存的对象的方法。参数 c 旨在成为 RSA 私钥初始化密码。
public void decrypt(Cipher c) throws ClassNotFoundException, IllegalBlockSizeException, BadPaddingException, IOException{
//decrypting the AES key (CryptoStack.java:110)
keyCache = (SecretKey) key.getObject(c);
//generating Cipher for decryption
Cipher c1 = null;
try {
c1 = Cipher.getInstance("AES");
c1.init(Cipher.DECRYPT_MODE, keyCache);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//decrypting Object with previous generated Cipher
stackCache = (Stack) stack.getObject(c1);
}
摘自chat.client.core.Client
相关属性
//Connection to the Server
private Socket socket;
//InputStream
private ObjectInputStream oin;
//Listener for incoming data
private IncomingStackListener l;
//HashMap for caching PublicKeys
private ConcurrentHashMap<String, PublicKey> publicKeyCache = new ConcurrentHashMap<String, PublicKey>();
等待正在解密并提供给侦听器的传入数据的线程。
public void run() {
Stack stack = null;
while (!isInterrupted()) {
try {
stack = (Stack) oin.readObject();
/*Irrelevant code removed*/
// Detect and decrypt encrypted data
if (stack.getType().equals(StackType.ENCRYPTED)) {
Cipher c = Cipher.getInstance("RSA");
c.init(Cipher.DECRYPT_MODE, me.getPrivateKey());
//following: Client.java:75
((CryptoStack) stack).decrypt(c);
stack = ((CryptoStack) stack).getCache();
}
} catch (ClassNotFoundException | IOException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
e.printStackTrace();
}
l.onStackEntry(stack);
}
}
问题
在标准 JVM 环境中一切正常。
但是在 Android 应用程序中使用此代码(它是我的项目库的一部分)对存储在 SealedObject 密钥中的唯一密钥的解密失败,并显示以下 LogCat 输出:
java.io.StreamCorruptedException
java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2070)
java.io.ObjectInputStream.<init>(ObjectInputStream.java:371)
javax.crypto.SealedObject.getObject(SealedObject.java:220)
chat.protocol.secure.CryptoStack.decrypt(CryptoStack.java:110)
chat.client.core.Client.run(Client.java:75)
如何使它在 Android 上也能正常工作?
如果需要解决方案,我准备提供更多代码
所以我终于弄清楚问题出在哪里了。
在 Android 和其他 "PC" 平台之间使用跨平台加密时,请确保指定算法、模式和填充(例如 "AES/CBC/PKCS5Padding"),因为仅指定算法(例如 "AES" ) 好像会引起误解。
我想加密和解密之前使用生成的 AES 密钥在 SealedObject 中加密的对象,该密钥也在 SealedObject 中保存和加密,但使用 RSA。
代码
Stack 是我的项目库和 Serializable 的一部分。每个名为 xxxStack 的对象都是 Stack 的子类。
摘自chat.protocol.secure.CryptoStack
相关属性
// encrypted Object
private SealedObject stack;
// cache for the Object
private transient Stack stackCache;
// encrypted AES key
private SealedObject key;
// cache for AES key which is used to encrypt and decrypt the Object
private transient SecretKey keyCache;
使用唯一的 AES 密钥加密缓存对象 (stackCache) 然后使用 public RSA 密钥加密并保存在堆栈中的方法
public void encrypt(Cipher c0) throws IllegalBlockSizeException, IOException{
/*
* Creates unique AES key for encrypting the Object
*/
KeyGenerator keyGen = null;
try {
keyGen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
keyGen.init(256);
keyCache = keyGen.generateKey();
/*
* Creating AES Cipher for encryption
*/
Cipher c1 = null;
try {
c1 = Cipher.getInstance("AES");
c1.init(Cipher.ENCRYPT_MODE, keyCache);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* Encrypts Object
*/
stack = new SealedObject(stackCache, c1);
/*
* Encrypts AES key with a Cipher given as argument (intended to be a public RSA key initialized Cipher)
*/
key = new SealedObject(keyCache, c0);
}
解密加密的AES密钥以解密保存的对象的方法。参数 c 旨在成为 RSA 私钥初始化密码。
public void decrypt(Cipher c) throws ClassNotFoundException, IllegalBlockSizeException, BadPaddingException, IOException{
//decrypting the AES key (CryptoStack.java:110)
keyCache = (SecretKey) key.getObject(c);
//generating Cipher for decryption
Cipher c1 = null;
try {
c1 = Cipher.getInstance("AES");
c1.init(Cipher.DECRYPT_MODE, keyCache);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//decrypting Object with previous generated Cipher
stackCache = (Stack) stack.getObject(c1);
}
摘自chat.client.core.Client
相关属性
//Connection to the Server
private Socket socket;
//InputStream
private ObjectInputStream oin;
//Listener for incoming data
private IncomingStackListener l;
//HashMap for caching PublicKeys
private ConcurrentHashMap<String, PublicKey> publicKeyCache = new ConcurrentHashMap<String, PublicKey>();
等待正在解密并提供给侦听器的传入数据的线程。
public void run() {
Stack stack = null;
while (!isInterrupted()) {
try {
stack = (Stack) oin.readObject();
/*Irrelevant code removed*/
// Detect and decrypt encrypted data
if (stack.getType().equals(StackType.ENCRYPTED)) {
Cipher c = Cipher.getInstance("RSA");
c.init(Cipher.DECRYPT_MODE, me.getPrivateKey());
//following: Client.java:75
((CryptoStack) stack).decrypt(c);
stack = ((CryptoStack) stack).getCache();
}
} catch (ClassNotFoundException | IOException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
e.printStackTrace();
}
l.onStackEntry(stack);
}
}
问题
在标准 JVM 环境中一切正常。 但是在 Android 应用程序中使用此代码(它是我的项目库的一部分)对存储在 SealedObject 密钥中的唯一密钥的解密失败,并显示以下 LogCat 输出:
java.io.StreamCorruptedException
java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2070)
java.io.ObjectInputStream.<init>(ObjectInputStream.java:371)
javax.crypto.SealedObject.getObject(SealedObject.java:220)
chat.protocol.secure.CryptoStack.decrypt(CryptoStack.java:110)
chat.client.core.Client.run(Client.java:75)
如何使它在 Android 上也能正常工作?
如果需要解决方案,我准备提供更多代码
所以我终于弄清楚问题出在哪里了。 在 Android 和其他 "PC" 平台之间使用跨平台加密时,请确保指定算法、模式和填充(例如 "AES/CBC/PKCS5Padding"),因为仅指定算法(例如 "AES" ) 好像会引起误解。