我正在寫一個程序,在該程序中,我接受一個字符串,對其進行加密,然後將其寫入文件中。然後,我從文件中讀取字符串,解密並修改它。這裏是我的DES加密/解密代碼:DES從文件中加密/解密
/* class for crypting and decrypting a file */
class DESEncrypter
{
private Cipher encryptionCipher;
private Cipher decryptionCipher;
public DESEncrypter (SecretKey key) throws Exception
{
encryptionCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
decryptionCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
decryptionCipher.init(Cipher.DECRYPT_MODE, key);
}
/* write to 'out' the encryption of the information read from 'in' */
public String encrypt(String unencryptedString)
{
String encryptedString = "";
try {
byte[] unencryptedByteArray = unencryptedString.getBytes("UTF8");
byte[] encryptedBytes = this.encryptionCipher.doFinal(unencryptedByteArray);
encryptedString = new sun.misc.BASE64Encoder().encode(encryptedBytes);
} catch (Exception ex) {
Logger.getLogger(DESEncrypter.class.getName()).log(Level.SEVERE, null, ex);
}
return encryptedString;
}
private static String bytes2String(byte[] bytes)
{
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++)
{
stringBuffer.append((char) bytes[i]);
}
return stringBuffer.toString();
}
/* write to 'out' the information obtained by decrypting the information read from 'in' */
public String decrypt (String encryptedString) throws UnsupportedEncodingException
{
byte[] unencryptedByteArray = new byte[4096];
try {
// Encode bytes to base64 to get a string
byte[] decodedBytes = new sun.misc.BASE64Decoder().decodeBuffer(encryptedString);
// Decrypt
unencryptedByteArray = this.decryptionCipher.doFinal(decodedBytes);
} catch (Exception ex) {
Logger.getLogger(DESEncrypter.class.getName()).log(Level.SEVERE, null, ex);
}
return bytes2String(unencryptedByteArray);
}
}
而這正是我在文件中寫一個加密的字符串函數:
public void writeToFileEncrypted(String filename, String owner, String departament)
{
try
{
BufferedReader br = new BufferedReader(new FileReader(new File("files_encrypted")));
String crypt = "";
String aux;
while ((aux = br.readLine()) != null)
{
crypt += aux;
}
br.close();
String info = this.server.crypt.decrypt(crypt);
info += filename + " " + owner + " " + departament + "\n";
/* delete the old encryption */
File temp = new File("files_encrypted");
temp.delete();
String infoCrypt = this.server.crypt.encrypt(info);
File newFiles = new File("files_encrypted");
if (newFiles.createNewFile() == false)
{
log.severe("Failed to re-create the 'files_encrypted' file when trying to add a new file");
return;
}
BufferedWriter bw = new BufferedWriter(new FileWriter(newFiles));
bw.write(infoCrypt);
bw.close();
}
catch (Exception e)
{
log.warning("An exception was caught while trying to remove '" + clientName + "' from the banned list");
e.printStackTrace();
return;
}
}
當服務器運行時,我可以修改該字符串從文件(多次運行該功能)。問題是,當我關閉服務器,然後我再次打開它,因爲我得到的錯誤: javax.crypto.BadPaddingException:給定最後一個塊未正確填充
這是我從文件中讀取服務器開啓時:
BufferedReader br = new BufferedReader(new FileReader(new File("files_encrypted")));
String crypto = new String();
String aux;
while ((aux = br.readLine()) != null)
{
crypto += aux;
readBytes++;
}
br.close();
System.out.println(readBytes);
info = this.crypt.decrypt(crypto);
爲什麼我得到那個錯誤?我做錯了什麼?我必須以其他方式將加密的字符串寫入文件中?
以後編輯:
我已經改變,從文件中讀取一個字符串函數,解密它,修改它,對它進行加密,然後在文件中寫道。
public void writeToFileEncrypted(String filename, String owner, String departament)
{
try
{
File f = new File("files_encrypted");
int nrRead = 0;
String info = null;
FileInputStream fis = new FileInputStream(f);
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = fis.read()) != -1)
{
sb.append((char)ch);
nrRead++;
}
fis.close();
StringBuilder sba = null;
if (nrRead != 0)
{
info = this.server.crypt.decrypt(new String(sb.toString().getBytes("UTF-8"), "UTF-8"));
sba = new StringBuilder(info);
sba.append(filename + " " + owner + " " + departament + " ");
}
else
{
sba = new StringBuilder(filename + " " + owner + " " + departament + " ");
}
/* delete the old encryption */
File temp = new File("files_encrypted");
temp.delete();
//System.out.println("before: " + sba.toString());
String infoCrypt = this.server.crypt.encrypt(sba.toString());
//System.out.println("after: " + infoCrypt);
File newFiles = new File("files_encrypted");
if (newFiles.createNewFile() == false)
{
log.severe("Failed to re-create the 'files_encrypted' file when trying to add a new file");
return;
}
FileOutputStream fos = new FileOutputStream(newFiles);
fos.write(infoCrypt.getBytes("UTF-8"));
fos.flush();
fos.close();
}
catch (Exception e)
{
log.warning("An exception was caught while trying to remove '" + clientName + "' from the banned list");
e.printStackTrace();
return;
}
}
我也修改了,我從文件中讀取的信息時,服務器打開的第一次:
FileInputStream fis = new FileInputStream(f);
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = fis.read()) != -1)
{
sb.append((char)ch);
readBytes++;
}
fis.close();
if (readBytes != 0)
{
System.out.println("on: " + sb.toString());
info = this.crypt.decrypt(new String(sb.toString().getBytes("UTF-8"), "UTF-8"));
System.out.println("load: " + info);
}
}
在用的System.out.println「上:」我從讀文件正是我寫的加密,沒有任何空格或新行。如果我用read(buffer)讀取,其中緩衝區是byte [],看起來增加了很多空間。
雖然我做了這一切的改變我仍然得到錯誤javax.crypto.BadPaddingException:鑑於最終塊未正確填充
有人偷任何想法,這是怎麼回事呢?
我的第一個猜測是你的閱讀方法。首先,在這裏使用字符串連接是不好的做法。使用一個StringBuilder。其次,你使用readline作爲二進制數據。第三你編碼('getBytes')爲UTF8。請注意,Java標準是UTF 16.這可能會破壞您的閱讀。 – Fildor
@Fildor - 加密的數據是Base64編碼的,所以它不是二進制數據。而且,只要正確的編碼用於編碼和解碼,getBytes()就可以了。 java在內部使用UTF-16,但這是無關緊要的。 – jtahlborn
這是一個字符串,是的。但是String代表二進制數據。如果他將它讀到一個字節[]然後創建一個字符串,他至少在調試時會有更多的控制權。新行將被刪除。但是換行符在這裏可能不是新行。 – Fildor