Java文件加密缺少字节
我正在尝试编写一个简单的程序,使用AES算法对文件进行加密和解密。稍后的意图是在更复杂的程序中使用将简单程序拆分为加密和解密方法。 他是程序的加密部分:Java文件加密缺少字节,java,file,encryption,Java,File,Encryption,我正在尝试编写一个简单的程序,使用AES算法对文件进行加密和解密。稍后的意图是在更复杂的程序中使用将简单程序拆分为加密和解密方法。 他是程序的加密部分: KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128); SecretKey key = kg.generateKey(); Cipher c = Cipher.getInstance("AES"); c.init(Cipher.ENCRYPT_MODE, key);
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey key = kg.generateKey();
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, key);
FileInputStream fis; FileOutputStream fos; CipherOutputStream cos;
fis = new FileInputStream("FileTo.encrypt");
fos = new FileOutputStream("Encrypted.file");
//write encrypted to file
cos = new CipherOutputStream(fos, c);
byte[] b = new byte[16];
int i = fis.read(b);
while (i != -1) {
cos.write(b, 0, i);
i = fis.read(b);
}
cos.close();
//write key to file
byte[] keyEncoded = key.getEncoded();
FileOutputStream kos = new FileOutputStream("crypt.key");
kos.write(keyEncoded);
kos.close();
以下是解密部分:
//Load Key
FileInputStream fis2= new FileInputStream("a.key");
File f=new File("a.key");
long l=f.length();
byte[] b1=new byte[(int)l];
fis2.read(b1, 0, (int)l);
SecretKeySpec ks2=new SecretKeySpec(b1,"AES");
Cipher c1 = Cipher.getInstance("AES");
c1.init(Cipher.DECRYPT_MODE, ks2);
FileInputStream fis1=new FileInputStream("Encrypted.file");
CipherInputStream in= new CipherInputStream(fis1,c1);
FileOutputStream fos0 =new FileOutputStream("decrypted.file");
byte[] b3=new byte[1];
int ia=in.read(b3);
while (ia >=0)
{
c1.update(b3); //<-------remove this
fos0.write(b3, 0, ia);
ia=in.read(b3);
}
in.close();
fos0.flush();
fos0.close();
//加载密钥
FileInputStream fis2=新的FileInputStream(“a.key”);
文件f=新文件(“a.key”);
长l=f.长度();
字节[]b1=新字节[(int)l];
fis2.读取(b1,0,(int)l);
SecretKeySpec ks2=新的SecretKeySpec(b1,“AES”);
Cipher c1=Cipher.getInstance(“AES”);
c1.init(Cipher.DECRYPT_模式,ks2);
FileInputStream fis1=新的FileInputStream(“Encrypted.file”);
CipherInputStream in=新的CipherInputStream(fis1,c1);
FileOutputStream fos0=新的FileOutputStream(“decrypted.file”);
字节[]b3=新字节[1];
int ia=英寸读数(b3);
而(ia>=0)
{
c1.update(b3);//下面是我找到的一些DES示例代码,可能会有帮助……尤其是对doFinal的调用
package forums;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
/**
This program tests the DES cipher. Usage:
java DESTest -genkey keyfile
java DESTest -encrypt plaintext encrypted keyfile
java DESTest -decrypt encrypted decrypted keyfile
*/
public class DESTest
{
private static void usage() {
System.err.print(
"This program tests the javax.crypto DES cipher package.\n"
+ "usage: java DESTest -genkey keyfile\n"
+ "java DESTest -encrypt plaintext encrypted keyfile\n"
+ "java DESTest -decrypt encrypted decrypted keyfile\n"
);
}
public static void main(String[] args) {
if ( args.length < 2 || args.length > 4
|| !args[0].matches("-genkey|-encrypt|-decrypt")
) {
usage();
return;
}
try {
if ("-genkey".equals(args[0])) {
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
keygen.init(random);
SecretKey key = keygen.generateKey();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]));
out.writeObject(key);
out.close();
} else {
int mode;
if ("-encrypt".equals(args[0])) {
mode = Cipher.ENCRYPT_MODE;
} else { //-decrypt
mode = Cipher.DECRYPT_MODE;
}
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));
Key key = (Key) keyIn.readObject();
keyIn.close();
InputStream in = new FileInputStream(args[1]);
OutputStream out = new FileOutputStream(args[2]);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(mode, key);
crypt(in, out, cipher);
in.close();
out.close();
}
} catch (IOException exception) {
exception.printStackTrace();
} catch (GeneralSecurityException exception) {
exception.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
/**
Uses a cipher to transform the bytes in an input stream
and sends the transformed bytes to an output stream.
@param in the input stream
@param out the output stream
@param cipher the cipher that transforms the bytes
*/
public static void crypt(InputStream in, OutputStream out, Cipher cipher)
throws IOException, GeneralSecurityException
{
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
byte[] inBytes = new byte[blockSize];
byte[] outBytes = new byte[outputSize];
int inLength = 0;;
boolean more = true;
while (more) {
inLength = in.read(inBytes);
if (inLength == blockSize) {
int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
out.write(outBytes, 0, outLength);
System.out.println(outLength);
} else {
more = false;
}
}
if (inLength > 0) {
outBytes = cipher.doFinal(inBytes, 0, inLength);
} else {
outBytes = cipher.doFinal();
}
System.out.println(outBytes.length);
out.write(outBytes);
}
}
套餐论坛;
导入java.io.*;
导入java.security.*;
导入javax.crypto.*;
导入javax.crypto.spec.*;
/**
此程序测试DES密码。用法:
javadestest-genkey密钥文件
java DESTest-加密明文加密密钥文件
java DESTest-解密加密的密钥文件
*/
公众阶级最不信任
{
私有静态void用法(){
System.err.print(
“此程序测试javax.crypto-DES密码包。\n”
+“用法:java DESTest-genkey密钥文件\n”
+“java DESTest-加密明文加密密钥文件\n”
+“java DESTest-解密加密的密钥文件\n”
);
}
公共静态void main(字符串[]args){
如果(args.length<2 | | args.length>4
||!args[0]。匹配项(“-genkey |-encrypt |-decrypt”)
) {
用法();
返回;
}
试一试{
如果(“-genkey”.equals(args[0])){
KeyGenerator keygen=KeyGenerator.getInstance(“DES”);
SecureRandom=新的SecureRandom();
密钥初始(随机);
SecretKey=keygen.generateKey();
ObjectOutputStream out=新的ObjectOutputStream(新的FileOutputStream(args[1]);
out.writeObject(键);
out.close();
}否则{
int模式;
如果(“-encrypt”.equals(args[0])){
模式=Cipher.ENCRYPT\u模式;
}else{//-解密
mode=Cipher.DECRYPT_模式;
}
ObjectInputStream keyIn=新ObjectInputStream(新文件输入流(args[3]);
Key=(Key)keyIn.readObject();
keyIn.close();
InputStream in=新文件InputStream(args[1]);
OutputStream out=新文件OutputStream(args[2]);
Cipher Cipher=Cipher.getInstance(“DES”);
cipher.init(模式,密钥);
密码(输入、输出、密码);
in.close();
out.close();
}
}捕获(IOException异常){
异常。printStackTrace();
}catch(GeneralSecurityException异常){
异常。printStackTrace();
}捕获(ClassNotFoundException异常){
异常。printStackTrace();
}
}
/**
使用密码转换输入流中的字节
并将转换后的字节发送到输出流。
@输入流中的参数
@参数输出输出流
@param cipher转换字节的密码
*/
公共静态无效密码(输入流输入、输出流输出、密码)
抛出IOException,GeneralSecurityException
{
int blockSize=cipher.getBlockSize();
int outputSize=cipher.getOutputSize(blockSize);
字节[]inBytes=新字节[块大小];
字节[]输出字节=新字节[outputSize];
int-inLength=0;;
布尔更多=真;
而(更多){
inLength=英寸读取(以字节为单位);
if(inLength==块大小){
int outLength=cipher.update(inBytes,0,blockSize,outBytes);
out.write(outBytes,0,outLength);
系统输出打印项次(输出长度);
}否则{
更多=错误;
}
}
如果(长度>0){
outBytes=cipher.doFinal(inBytes,0,inLength);
}否则{
outBytes=cipher.doFinal();
}
System.out.println(outBytes.length);
out.write(输出字节);
}
}
您只需删除代码中的这一行,它就可以正常工作了:
c1.update(b3);
由于您使用的是密码输入流
,因此不需要手动更新密码
。它会为您处理该问题,而通过调用它,您就干扰了解密
另一方面,为了提高效率,您应该增加byte[]b
和byte[]b3
数组的大小。通常8192是一个很好的缓冲大小。import javax.crypto.Cipher;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESTest {
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
public static void main(String[] args) throws Exception {
String keyString = "ssssssssssssssss";
// 546578746F2070617261207465737465 (Hex)
byte[] key = keyString.getBytes();
System.out.println(asHex(key).toUpperCase());
String clearText = "sdhhgfffhamayaqqqaaaa";
// ZXNzYXNlbmhhZWhmcmFjYQ== (Base64)
// 6573736173656E686165686672616361 (Hex)
byte[] clear = clearText.getBytes();
System.out.println(asHex(clear).toUpperCase());
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
// PKCS5Padding or NoPadding
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
System.out.println(asHex(encrypted).toUpperCase());
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original =
cipher.doFinal(encrypted);
System.out.println(original);
String originalString = new String(original);
System.out.println("Original string: " +
originalString + " " + asHex(original));
}
}
导入javax.crypto.spec.SecretKeySpec;
公共类测试{
公共静态字符串asHex(字节buf[]{
StringBuffer strbuf=新的StringBuffer(buf.length*2);
int i;
对于(i=0;i