Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
文件加密Java_Java_Security_Encryption - Fatal编程技术网

文件加密Java

文件加密Java,java,security,encryption,Java,Security,Encryption,我正在制作一个系统,其中包含一些数据,我希望它以XML格式获取这些数据,并将其保存为txt文件中的加密字符串,稍后当软件再次打开时,解密文件并正常读取。我已经有了将xml转换成字符串的所有代码,我已经有了保存它的代码,我只需要一些加密/解密代码的帮助 注意:我确实找到了一些要加密/解密的代码,但似乎无法将代码拆分为两种方法 以下是我的尝试: public class AesEncrDec { public static String encrypt(String Data) {

我正在制作一个系统,其中包含一些数据,我希望它以XML格式获取这些数据,并将其保存为txt文件中的加密字符串,稍后当软件再次打开时,解密文件并正常读取。我已经有了将xml转换成字符串的所有代码,我已经有了保存它的代码,我只需要一些加密/解密代码的帮助

注意:我确实找到了一些要加密/解密的代码,但似乎无法将代码拆分为两种方法

以下是我的尝试:

    public class AesEncrDec
{

public static String encrypt(String Data)
{
    byte[] byteCipherText = null;
    try {
        String plainData=Data,cipherText,decryptedText;
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        SecureRandom rnd = new SecureRandom();
        SecretKey secretKey = keyGen.generateKey();
        IvParameterSpec iv;
        iv = new IvParameterSpec(rnd.generateSeed(16));
        Cipher aesCipher = Cipher.getInstance("AES");
        aesCipher.init(Cipher.ENCRYPT_MODE,secretKey,iv); 
        byte[] byteDataToEncrypt = plainData.getBytes();
        byteCipherText = aesCipher.doFinal(byteDataToEncrypt);
        cipherText = new BASE64Encoder().encode(byteCipherText);
        return new String(byteCipherText);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalBlockSizeException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (BadPaddingException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidAlgorithmParameterException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    }
    return new String(byteCipherText);
}

public static String dencrypt(String Data)
{
    byte[] byteDecryptedText = null;
    try {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        IvParameterSpec iv;
        SecureRandom rnd = new SecureRandom();
        iv = new IvParameterSpec(rnd.generateSeed(16));
        Cipher aesCipher = Cipher.getInstance("AES");
        SecretKey secretKey = keyGen.generateKey();
        aesCipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);
        byteDecryptedText = aesCipher.doFinal(Data.getBytes());
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidAlgorithmParameterException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalBlockSizeException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    } catch (BadPaddingException ex) {
        Logger.getLogger(AesEncrDec.class.getName()).log(Level.SEVERE, null, ex);
    }
    return new String(byteDecryptedText);
}
}
编辑:在对@Libin的响应中,以下是错误

Mar 24, 2014 6:27:42 PM PrefsReadAndWrite.AesEncrDec decrypt
SEVERE: null
javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2121)
    at PrefsReadAndWrite.AesEncrDec.decrypt(AesEncrDec.java:61)
    at PrefsReadAndWrite.AesEncrDec.decryptedString(AesEncrDec.java:104)
    at smarthouse.SmartHouse.main(SmartHouse.java:12)

Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.<init>(String.java:554)
    at PrefsReadAndWrite.AesEncrDec.decryptedString(AesEncrDec.java:105)
    at smarthouse.SmartHouse.main(SmartHouse.java:12)
Java Result: 1

您没有定义要使用的填充,因此使用了实现定义的填充。根据你的错误,这可能是你的情况。指定填充和操作模式,例如AES/CBC/PKCS5P添加。由于您现在将使用CBC,因此还需要一个初始化向量:

IvParameterSpec iv = new IvParameterSpec(rnd.generateSeed(16));
aesCipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);

其中rnd是一个SecureRandom实例。以字符串形式返回数据也是一个坏主意,直接使用字节。当然,按照Libins的建议使用相同的密钥进行加密和解密。

您只需生成一次密钥,然后使用它进行加密和解密。。使用此代码

AppSecurity类应用于生成新密钥和加密/解密

方法对字符串进行加密

 private static byte[] encryptedByte(String s) {
    return AppSecurity.encrypt(YourApplication.getSecretKey(),toBytes(s));
 }
方法对字节进行解密

  private static String decryptedString(byte[] blob) {
    // here getSecretKey() should be the one used on encryption
    byte[] decrypted =  AppSecurity.decrypt(YourApplication.getSecretKey(),blob);
    return toString(decrypted);
}

方法将字节转换为字符串

public static String toString(byte[] bytes) {
  try {
    String s = new String(bytes ,"UTF-8");
     return s;
     } catch (UnsupportedEncodingException e) {
      return null;
     }
  }
方法将字符串转换为字节

 public static byte[] toBytes(String s) {
   try {
       return s.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {return null;}
   }
有关如何在应用程序中使用此功能的详细信息: 在应用程序/applet类上初始化initSecurity方法,并将返回键存储到变量中,并在运行时使用它

假设类名为YourApplication.java

//添加此方法以读取文件或生成一个新密钥

 private void initSecurity() {
    final String secretFile = "secure_file";
    boolean keyExists = false;
    //check if secret key exist in secure file
    try {
        FileInputStream inputStream = openFileInput(secretFile);
        mSecretKey = new byte[16];
        int result = inputStream.read(mSecretKey);
        if(result >0) {
            keyExists = true;
        }
        inputStream.close();
    }
    catch (FileNotFoundException e) {}
    catch (IOException e){}
    if(!keyExists) {
        // generate a key
        mSecretKey = AppSecurity.generateKey();
        if(mSecretKey != null) {
            // write in a secure file inside the app
            try {
                // MODE_PRIVATE will create the file (or replace a file of the same name)
                // and make it private to the application.
                FileOutputStream outputStream = openFileOutput(secretFile,Context.MODE_PRIVATE);
                outputStream.write(mSecretKey);
                outputStream.close();
            }
            catch (FileNotFoundException e){}
            catch (IOException e) {}
        }
    }
}

你说不能拆分代码到底是什么意思?另外,看到空的捕捉块会让大多数开发人员感到毛骨悚然;永远不要这样做。甚至不是为了好玩。plainData.getBytes@fge im实际上试图加密字符串而不是实际的xml即使在这种情况下,指定字符集;此加密内容的收件人的JRE/OS组合不能使用与您的JRE/OS组合相同的字符集。如果您不知道选择哪一个,请选择StandardCharsets.UTF_8。@fge谢谢您的解释,我将更改为我无法使用rnd.generateSeed16这是什么函数?@erickson:您为什么将其更改为PKCS5?我知道它是有效的,但这只是因为它被解释为pkcs7填充。PKCS5用于8字节块大小,而AES使用16字节块。因此,我建议使用PKCS7填充。@Caio Petrelli:使用SecureRandom对象。忘记提到这一点了,因为它们在该字段中非常常见。PKCS7Padding不是JCA标准算法名称定义的标准名称,因此一些提供程序将引发NoSuchAlgorithmException。当应用于长度超过8字节的块时,将PKCS5Padding解释为PKCS 7填充的提供程序是常见的。@Drunix ive尝试实现该代码,但它不起作用,仍然返回相同的错误,我要更新这个问题,看看运行时没有错误,但在加密和解密方法中都返回null。查看我的更新答案。调用encryptedByte对字符串进行加密,并使用decryptedString对加密的字节进行解密。您能看到它引发了什么异常吗?异常似乎在decrypt中。你使用的是加密所用的同一个密钥吗?你能举个例子说明我应该如何调用这些方法,以及如何打印encrypt和dencrypt值吗?我不确定我调用的方法是否正确。。对不起,我有点不知道我在编程
 // initialize it on your app startup
 String mSecretKey = initSecurity()

 // call this method when you encrypt /decrypt
 public static byte[] getSecretKey() { return mSecretKey; } 
 private void initSecurity() {
    final String secretFile = "secure_file";
    boolean keyExists = false;
    //check if secret key exist in secure file
    try {
        FileInputStream inputStream = openFileInput(secretFile);
        mSecretKey = new byte[16];
        int result = inputStream.read(mSecretKey);
        if(result >0) {
            keyExists = true;
        }
        inputStream.close();
    }
    catch (FileNotFoundException e) {}
    catch (IOException e){}
    if(!keyExists) {
        // generate a key
        mSecretKey = AppSecurity.generateKey();
        if(mSecretKey != null) {
            // write in a secure file inside the app
            try {
                // MODE_PRIVATE will create the file (or replace a file of the same name)
                // and make it private to the application.
                FileOutputStream outputStream = openFileOutput(secretFile,Context.MODE_PRIVATE);
                outputStream.write(mSecretKey);
                outputStream.close();
            }
            catch (FileNotFoundException e){}
            catch (IOException e) {}
        }
    }
}