【问题标题】:Java encryption won't decrypt on AndroidJava 加密不会在 Android 上解密
【发布时间】:2019-11-06 06:15:05
【问题描述】:

好的,所以当我加密任何东西时,让我们说在这种情况下是一个文件,用我的电脑。它可以很好地加密和解密所述文件。但是,如果用我的计算机加密文件,然后将它发送给我的 android 并运行我编写的相同解密代码,它不会正确解密文件。它没有显示任何错误,但是文件显然没有正确解密。

所以我了解到 Bouncy Castle 与 JVM/JDK 标准加密库完全不同,所以我不能 100% 确定这是否是问题所在。然而,这将是有道理的。问题是,如果是我不知道如何在我的 android 上使用 JVM/JDK 库进行加密。我不想在我的电脑上使用 Bouncy Castle 库。

public static void encrypt(File source, File dest, String password){
    try{
        FileInputStream inFile = new FileInputStream(source.getPath());
        FileOutputStream outFile = new FileOutputStream(dest.getPath());

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] input = new byte[64];
        int bytesRead;

        while((bytesRead = inFile.read(input)) != -1){
            byte[] output = cipher.update(input, 0, bytesRead);
            if(output != null){
                outFile.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            outFile.write(output);
        }

        inFile.close();
        outFile.flush();
        outFile.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void decrypt(File source, File dest, String password){
    try{
        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
        FileInputStream fis = new FileInputStream(source.getPath());
        FileOutputStream fos = new FileOutputStream(dest.getPath());
        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

结果也将能够使用我的计算机使用标准 JVM/JDK 加密库加密任何文件,并且也能够使用我的 android 解密相同的文件。

但是,如果除了 Bouncy Castle 之外还有其他可以与 android 一起使用的库,我愿意提供想法。

【问题讨论】:

  • 您可能有兴趣查看CipherInputStream/CipherOutputStream 类和Files 类的copy(...) 方法。它们一起可以用来消除代码中的读写 I/O 循环。结果更短、更清晰、更不容易出错。从 API 26 开始,Files 类在 Android 中可用。

标签: java android file encryption


【解决方案1】:

我也遇到过类似的问题。首先检查您的加密和解密设置是否正确。

如果没问题,那么您应该将加密文本转换为 Base64 或类似编码。

然后在手机上先解码Base64编码再解密文件。

出现此问题的原因是,某些字符不适合在媒体之间保存或传输。它们也会受到底层操作系统的影响。即使有一点改变,你的整个解密文本也会改变,这里可能就是这种情况

安卓代码

public static void decrypt(File source, File dest, String password){
    try{
        Base64InputStream fis = new Base64InputStream(new DataInputStream(new FileInputStream(source.getPath())), Base64.DEFAULT);
        FileOutputStream fos = new FileOutputStream(dest.getPath());


        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

常规 JVM

public static void encrypt(File source, File dest, String password){
    try{
        FileInputStream inFile = new FileInputStream(source.getPath());
        OutputStream outFile = Base64.getEncoder().wrap(new FileOutputStream(dest.getPath()));

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] input = new byte[64];
        int bytesRead;

        while((bytesRead = inFile.read(input)) != -1){
            byte[] output = cipher.update(input, 0, bytesRead);
            if(output != null){
                outFile.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            outFile.write(output);
        }

        inFile.close();
        outFile.flush();
        outFile.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void decrypt(File source, File dest, String password){
    try{
        InputStream fis = Base64.getDecoder().wrap(new FileInputStream(source.getPath()));
        //FileInputStream fis = new FileInputStream(source.getPath());
        FileOutputStream fos = new FileOutputStream(dest.getPath());

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

【讨论】:

  • 这是有道理的,但是它在一个文件中。你认为这会影响我的文件,即使我不将它作为字符串而是字节读取?
  • @TheAnarch 雅。实际上这发生在我使用文件时!
  • 嗯,这太奇怪了。我现在想出一些代码。谢谢您的回答。如果可行,我会确保也写回答:)
  • 我也可以用 JVM 包装我的流,效果很好。但是使用相同的代码需要 API 26。但是我认为这应该可以工作。因为我也能够解码文件的一部分。
  • @TheAnarch 我的荣幸 :)
猜你喜欢
  • 2016-05-04
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多