当前位置: 首页 > 面试题库 >

可序列化对象的ArrayList的加密保存和解密加载

翁烨霖
2023-03-14
问题内容

ArrayList使用以下两种方法将包含可序列化对象的文件保存并加载到SD卡中

保存方法

public static void saveUserList(ArrayList<User> userList) {
        if (storageAvailable()) {
            try {
                createFolder();

                FileOutputStream userList = new FileOutputStream(
                        baseDir + File.separator + baseAppDir + File.separator
                                + fileName);

                ObjectOutputStream oos = new ObjectOutputStream(
                        userList);
                oos.writeObject(userList);

                oos.close();
            } catch (Exception exc) {
                exc.printStackTrace();
            }
        }

    }

加载方式

 public static ArrayList<User> loadUserList() {
        if (storageAvailable()) {
            ArrayList<User> userList = new ArrayList<User>();
            try {
                FileInputStream userList = new FileInputStream(baseDir
                        + File.separator + baseAppDir + File.separator
                        + fileName);

                ObjectInputStream oos = new ObjectInputStream(
                        userList);

                userList = (ArrayList<User>) oos.readObject();
                oos.close();

            } catch (Exception exc) {
                exc.printStackTrace();
            }

            return userList;
        } else {
            return null;
        }

    }

现在,我希望该方法saveUserList根据特定的内容在保存期间加密文件的内容,String keyword并且该方法loadUserList使用相同的关键字解密文件以返回arrayList。

我该怎么办?我看了一下,CipherOutputStream但我不知道该怎么用。

建议使用隐蔽库的方法

public static void saveUserListCrypted(ArrayList<User> userList) {
    if (storageAvailable()) {
        try {
            createFolder();
            Crypto crypto = new Crypto(
                new SharedPrefsBackedKeyChain(context),
                new SystemNativeCryptoLibrary());

            FileOutputStream userList = new FileOutputStream(
                    baseDir + File.separator + baseAppDir + File.separator
                            + fileName);

            OutputStream cryptedStream = crypto.getCipherOutputStream(
                userList, new Entity("UserList");


            ObjectOutputStream oos = new ObjectOutputStream(
                    cryptedStream);
            oos.writeObject(userList);

            oos.close();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

}

导致这个错误

 this error java.lang.UnsupportedOperationException 02-12 21:29:05.026 2051-2051/com.myapp W/System.err﹕ at com.facebook.crypto.streams.NativeGCMCipherOutputStream.write

问题答案:

请尝试(添加适当的检查并尝试省略的块以使代码更具可读性)这样的保存

public static void AESObjectEncoder(Serializable object, String password, String path) {
        try {
            Cipher cipher = null;
            cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            cipher.init(Cipher.ENCRYPT_MODE, fromStringToAESkey(password));
            SealedObject sealedObject = null;
            sealedObject = new SealedObject(object, cipher);
            CipherOutputStream cipherOutputStream = null;
            cipherOutputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(path)), cipher);
            ObjectOutputStream outputStream = null;
            outputStream = new ObjectOutputStream(cipherOutputStream);
            outputStream.writeObject(sealedObject);
            outputStream.close();    
    }

这要加载

 public static Serializable AESObjectDedcoder(String password, String path) {
        Cipher cipher = null;
        Serializable userList = null;
        cipher = Cipher.getInstance("AES/CBC/PKCS7Pdding");

        //Code to write your object to file
        cipher.init(Cipher.DECRYPT_MODE, fromStringToAESkey(password));         
        CipherInputStream cipherInputStream = null;
        cipherInputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(path)), cipher);

        ObjectInputStream inputStream = null;
        inputStream = new ObjectInputStream(cipherInputStream);
        SealedObject sealedObject = null;
        sealedObject = (SealedObject) inputStream.readObject();
        userList = (Serializable) sealedObject.getObject(ciper);  
        return userList;
    }

SecretKey从字符串创建一个,您可以使用此

public static SecretKey fromStringToAESkey(String s) {
        //256bit key need 32 byte
        byte[] rawKey = new byte[32];
        // if you don't specify the encoding you might get weird results
        byte[] keyBytes = new byte[0];
        try {
            keyBytes = s.getBytes("ASCII");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.arraycopy(keyBytes, 0, rawKey, 0, keyBytes.length);
        SecretKey key = new SecretKeySpec(rawKey, "AES");
        return key;
    }

注意:

代码两次加密和解密,以显示密封对象和密码流的使用方式



 类似资料:
  • 我想在Java文件中存储一个加密的密码。我看到了一个使用javax.crypto的解决方案,但问题是密钥是动态生成的,并且是随机的。 有没有办法告诉javax.crypto方法: 这是否可以替换为基于某个私钥生成一次的我自己的密钥? 有谁能给我指出一些如何做到这一点的资源吗?

  • 这是可能的还是加密必须共享和使用相同的密钥? 主要目的就是这样。 我将有两个客户端可以发送和接收加密数据到彼此。

  • 我有一个问题如下-有一个jsp页面register.jsp,它的表单如下- 正如您所看到的,我正在jsp上加密国家和州的id,现在处理这个请求的控制器方法如下所示- 用户bean有一个名为country的属性,它引用对象country类这里是我的country类- 提交表单后,我发现了这个错误- 无法将类型java.lang.String的属性值转换为属性City.State.country.id

  • 问题内容: 我迅速编写了一个应用程序,我需要AES加密和解密功能,我从另一个.Net解决方案中接收了加密数据,但是我找不到解决办法。 这是我的.net加密: 我需要迅速解密功能。 问题答案: 我找到了解决方案,它是一个很好的库。 跨平台256位AES加密/解密。 此项目包含在所有平台(C#,iOS,Android)上均可使用的256位AES加密的实现。关键目标之一是通过简单的实现使AES在所有平台

  • 问题内容: 按照本教程,我将使用flexiprovider基于椭圆曲线的不对称算法进行加密/解密。稍作修改,我将出于个人目的将公共密钥和私有密钥转换为Base64(例如存储到数据库或文本文件中)。但是我的代码不是在android设备中运行的,而在Java设备中运行的是dekstop,不是Java中的android和dekstop版本,我认为这是一个很大的差异(只是为了清理我的问题信息)。好的,在我

  • 我正在使用AES加密下面的员工类,并将其保存为sealedObject作为serviceA的一部分。 在serviceB中,当我尝试将sealedObject解密回员工类时。 它抛出ClassNotFoundException,表示org。公司服务A。模型未找到员工。 显然,它试图通过完全限定的名称找到ServiceA的employee类,即使我在serviceB中创建了类似的类。 当加密和解密都