首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文件加密Java

文件加密Java
EN

Stack Overflow用户
提问于 2014-03-24 20:09:49
回答 2查看 559关注 0票数 0

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

注意:我确实找到了一些可以加密/解密的代码,但是我似乎不能将代码分成两个方法。

以下是我的尝试:

代码语言:javascript
复制
    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的响应中,这里是错误

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-24 20:55:09

您必须只生成一次密钥,并将其用于加密和解密。用这个代码..。

应该使用AppSecurity类来生成新密钥和加密/解密

代码语言:javascript
复制
public class AppSecurity{
private AppSecurity() {}

public static byte[] encrypt(byte[] key , byte[] data) {
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    try {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE,keySpec);
        return cipher.doFinal(data);
    }
    catch (NoSuchAlgorithmException e){ }
    catch (NoSuchPaddingException e){ }
    catch (InvalidKeyException e){ }
    catch (BadPaddingException e){ }
    catch (IllegalBlockSizeException e) {}
    return null;
}

public static byte[] decrypt(byte[] key , byte[] encryptedData) {
    SecretKeySpec keySpec = new SecretKeySpec(key ,"AES");
    try {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(encryptedData);
    }
    catch (NoSuchAlgorithmException e) {}
    catch (NoSuchPaddingException e) { }
    catch (InvalidKeyException e) { }
    catch (BadPaddingException e) {}
    catch (IllegalBlockSizeException e) {}
    return null;
}

/**
 * method to generate a secure key. call this when app starts
 * @return
 */
public static byte[] generateKey(){
    try{
        // create an AES algorithm instance.
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        keyGenerator.init(128,secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        return secretKey.getEncoded();
    }
    catch (NoSuchAlgorithmException e){
        return null;
    }
  }
}

方法对字符串进行加密。

代码语言:javascript
复制
 private static byte[] encryptedByte(String s) {
    return AppSecurity.encrypt(YourApplication.getSecretKey(),toBytes(s));
 }

方法来解密字节。

代码语言:javascript
复制
  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);

}

方法将字节转换为字符串。

代码语言:javascript
复制
public static String toString(byte[] bytes) {
  try {
    String s = new String(bytes ,"UTF-8");
     return s;
     } catch (UnsupportedEncodingException e) {
      return null;
     }
  }

方法将字符串转换为Byte。

代码语言:javascript
复制
 public static byte[] toBytes(String s) {
   try {
       return s.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {return null;}
   }

详细介绍了如何在应用程序中使用此方法:初始化应用程序/applet类上的initSecurity()方法,并将返回键存储到变量中,并在运行时使用该方法。

假设类名为YourApplication.java

代码语言:javascript
复制
 // initialize it on your app startup
 String mSecretKey = initSecurity()

 // call this method when you encrypt /decrypt
 public static byte[] getSecretKey() { return mSecretKey; } 

//添加此方法以从文件中读取或生成一个新键

代码语言:javascript
复制
 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) {}
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2014-03-24 20:33:21

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

代码语言:javascript
复制
IvParameterSpec iv = new IvParameterSpec(rnd.generateSeed(16));
aesCipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22619602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档