Java / Android:SealedObject抛出StreamCorruptedException

时间:2015-03-01 12:09:04

标签: java android encryption cryptography

我想加密和解密先前使用生成的AES密钥在SealedObject中加密的对象,这些对象在SealedObject中使用RSA进行持久化和加密。

代码

Stack是我的项目库和Serializable的一部分。名为xxxStack的每个Object都是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)的方法,然后使用公共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上使用它? 如果需要解决方案,我已准备好提供更多代码

1 个答案:

答案 0 :(得分:0)

所以我终于弄明白了问题所在。 在Android和其他&#34; PC&#34;之间使用加密跨平台时平台确保您指定算法,模式和填充(例如&#34; AES / CBC / PKCS5Padding&#34;),因为仅指定算法(如&#34; AES&#34;)似乎会引起误解。