我正在尝试使用CBC模式加密和解密数据。 在这里,我首先从plaintext.txt文件中读取数据,然后将输出作为plaintext.txt的数据写入另一个ciphertext.txt文件。尝试解密时,我正在将文件中的加密数据读取为字节,但是由于某种原因,这给了我一个错误。有人可以帮我解决这个问题吗?
这是我的加密功能
// The encryption Function CBC MODE
public static byte[] encrypt(String plainText, String key) throws Exception
{
// Loading the secret key from the Key.txt file
String fileName="../data/key.txt";
try
{
BufferedReader in = new BufferedReader(new FileReader(fileName)); // Initialize a Buffer reader
key = in.readLine(); // Reading the data from txt file
}
//error message if the file is not found
catch(FileNotFoundException ex)
{
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex)
{
System.out.println("Error reading file '" + fileName + "'");
}
byte[] clean = plainText.getBytes(); //Getting the data in bytes from the plain text
// Generating IV.
//From the initialization vector, we create an IvParameterSpec which is required when creating the Cipher.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
//System.out.println("The Iv is = "+ivParameterSpec);
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
try
{
PrintWriter writer = new PrintWriter("../data/ciphertext.txt");
writer.println(encryptedIVAndText);
writer.close();
}
catch(Exception ex)
{
System.out.println(ex);
System.out.println("File is not there");
}
return encryptedIVAndText;
}
这是我的解密功能。
// Decrypting fucntion CBC mode
public static String decrypt(byte[] encryptedIvTextBytes, String key) throws Exception
{
FileInputStream encryptedTextFis = new FileInputStream("../data/ciphertext.txt");
byte[] encText = new byte[encryptedTextFis.available()];
int lol = encryptedTextFis.available();
System.out.println("lol "+ lol);
encryptedTextFis.read(encText);
encryptedTextFis.close();
// encrypted = readFile("../data/ciphertext.txt", StandardCharsets.UTF_8).getBytes();
encryptedIvTextBytes = encText;
//System.out.println("..........??????");
String fileName="../data/key.txt";
String fileName2="../data/ciphertext.txt";
try
{
BufferedReader in = new BufferedReader(new FileReader(fileName));
BufferedReader in2 = new BufferedReader(new FileReader(fileName2));
key = in.readLine();
// byte[] array = Files.readAllBytes(new File("/path/to/file").toPath());
}
//error message if the file is not found
catch(FileNotFoundException ex)
{
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex)
{
System.out.println("Error reading file '" + fileName + "'");
}
int ivSize = 16;
int keySize = 32;
//System.out.println("..........??????");
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
System.out.println("..........??????");
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
System.out.println("..........??????");
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); //Decrypting the encrypted data to a cipherblock data
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes); // Decrypting the cipher dadat to Plaintext
//Writing the output to a txt file
try
{
PrintWriter writer = new PrintWriter("../data/result.txt");
writer.println(new String(decrypted));
writer.close();
}
catch(Exception ex)
{
System.out.println(ex);
System.out.println("File is not there");
}
return new String(decrypted); //Returning the decrypted data to main function
}
答案 0 :(得分:0)
似乎例外:
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
数组encryptedIvTextBytes
的长度为11(如您所说,结果也显示)。现在,您要从encryptedIvTextBytes
复制16个字节(作为iv的长度)。
但是主要是由于此注释,您用于保存加密数据的保存方法无效。加密的数据可能包含一些不是可读字符的字节。当您将加密数据另存为字符串时,将丢弃这些字节。要解决此问题,请参阅@Maarten和@ MS90注释。
答案 1 :(得分:0)
以下是适合您需求的代码:
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
String key = "abcdefghijklmop";// you could store it somewhere ...
justToMakePlainTextFile();
byte[] encrypted = encrypt("plaintext",key);
decrypt(encrypted, key);
}
public static void justToMakePlainTextFile() {
try {
RandomAccessFile randomAccessFile = new RandomAccessFile("plaintext", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
String randomText = "Ho-ho-ho-ho! This is going to be a nice weekend and I am going to swim soon.";
byte[] bytes = randomText.getBytes();
ByteBuffer byteBuffer = ByteBuffer.allocate(randomText.length());//alocate new ByteBuffer of size randomeText.length
byteBuffer.put(bytes);
byteBuffer.flip();
fileChannel.write(byteBuffer);
randomAccessFile.close();
fileChannel.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
}
public static byte[] encrypt(String file, String key) throws Exception {
RandomAccessFile reader = new RandomAccessFile(file, "r");
FileChannel channel = reader.getChannel();
int bufferSize = 1024;
if (bufferSize > channel.size()) {
bufferSize = (int) channel.size();
}
ByteBuffer buff = ByteBuffer.allocate(bufferSize);
channel.read(buff);
buff.flip();
byte[] clean = buff.array();
channel.close();
reader.close();
// Generating IV.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[16];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
return encryptedIVAndText;
}
public static void decrypt(byte[] encryptedIvTextBytes, String key) throws Exception {
int ivSize = 16;
int keySize = 16;
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);
try {
RandomAccessFile randomAccessFile = new RandomAccessFile("ciphertext", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
byte[] bytes = decrypted;
ByteBuffer byteBuffer = ByteBuffer.allocate(decrypted.length);//alocate new ByteBuffer of size randomeText.length
byteBuffer.put(bytes);
byteBuffer.flip();
fileChannel.write(byteBuffer);
randomAccessFile.close();
fileChannel.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
}
密文和纯文本文件在您的项目主文件夹中创建。