在JDK的javax.crypto 的包中提供了对一些通用算法的加密解密的支持,本文简介一下使用DES算法来对数据加密解密。通常是数据加密方用密钥将数据加密,数据解密方用同样的密钥将数据解密。这个密钥是包含8位byte的一个二进制的文件,加密解密方可以是任何开发语言。
用JAVA生成一个key并保存到一个二进制文件中去的方法如下:
public static void saveBytePriveKey(String file) {
try {
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecretKey key = keyGen.generateKey();// 生成私钥Key
FileOutputStream fop = new FileOutputStream(file);
fop.write(key.getEncoded());
fop.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
从密钥文件中读取内容生成密钥:
public static SecretKey getBytePriveKey(String file) throws Exception {
File keyf = new File(file);
long length = keyf.length();
byte[] bytes = new byte[(int) length];
FileInputStream fis = new FileInputStream(keyf);
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
DESKeySpec dks = new DESKeySpec(bytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(dks);
return key;
}
对文件进行加密,对文件的操作应该是以流的方式,加密后的数据是一个二进制流,它可能不能被对应到任何编码的String,所以在操作过程中不应该将加密后的byte数据转换为String。将一个文件加密为另一个文件的代码如下:
public static void encryptFile(String plainFile, String encryptedFile, String keyFile) {
try {
SecretKey key = getBytePriveKey(keyFile);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
FileInputStream fis = new FileInputStream(plainFile);
FileOutputStream fos = new FileOutputStream(encryptedFile);
crypt(fis, fos, cipher);
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException,
GeneralSecurityException {
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
System.out.println("blockSize " + blockSize + " outputSize" + outputSize);
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);
} else {
more = false;
}
}
if (inLength > 0)
outBytes = cipher.doFinal(inBytes, 0, inLength);
else
outBytes = cipher.doFinal();
out.write(outBytes);
}
同样,在解密过程中,对数据也应该以流的方式:
public static void decryptFile(String encryptedFile, String decryptedFile, String keyFile) {
try {
SecretKey key = getBytePriveKey(keyFile);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream(encryptedFile);
FileOutputStream fos = new FileOutputStream(decryptedFile);
crypt(fis, fos, cipher);
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
如果是想把很多String一行一行的加密后保存到一个文件,应该先把这些String保存到一个中间文件,然后把中间文件以流的方式读入,以加密文件的方式进行。我尝试着把
加密一个String就写到文件中,但是发现最后解密的时候会有问题。
下面是整个类的源代码:
package com.test.endecrypt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class DESCrypter {
private static String bytekeyfile = "d://temp//bytekeyfile";
private static String originalfile = "d://temp//originalfile";
private static String encryptedfile = "d://temp//encryptedfile";
private static String decryptedfile = "d://temp//decryptedfile";
public static void main(String args[]) {
saveBytePriveKey(bytekeyfile);
encryptFile(originalfile, encryptedfile, bytekeyfile);
decryptFile(encryptedfile, decryptedfile, bytekeyfile);
String[] strings = { "要加密的串 the text to be encrypt", "AAAAAAAAAAA", "要加密的串 the text to be encrypt" };
encryptStringsTofile(strings, encryptedfile, bytekeyfile);
decryptFile(encryptedfile, decryptedfile, bytekeyfile);
}
public static void encryptFile(String plainFile, String encryptedFile, String keyFile) {
try {
SecretKey key = getBytePriveKey(keyFile);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
FileInputStream fis = new FileInputStream(plainFile);
FileOutputStream fos = new FileOutputStream(encryptedFile);
crypt(fis, fos, cipher);
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void encryptStringsTofile(String[] strings, String encryptedFile, String keyFile) {
try {
SecretKey key = getBytePriveKey(keyFile);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream fos = new FileOutputStream(encryptedFile);
crypt(strings, fos, cipher);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException,
GeneralSecurityException {
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
System.out.println("blockSize " + blockSize + " outputSize" + outputSize);
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);
} else {
more = false;
}
}
if (inLength > 0)
outBytes = cipher.doFinal(inBytes, 0, inLength);
else
outBytes = cipher.doFinal();
out.write(outBytes);
}
public static void crypt(String strings[], OutputStream out, Cipher cipher) throws IOException,
GeneralSecurityException {
for (String str : strings) {
byte[] encryptedBytes = encrypt(str + "\r\n", "UTF8", cipher);
out.write(encryptedBytes);
}
}
public static byte[] encrypt(String in, String strEncode, Cipher cipher) throws IOException,
GeneralSecurityException {
byte[] originalBytes = in.getBytes(strEncode);
byte[] encryptedBytes = cipher.doFinal(originalBytes);
return encryptedBytes;
}
public static void decryptFile(String encryptedFile, String decryptedFile, String keyFile) {
try {
SecretKey key = getBytePriveKey(keyFile);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream(encryptedFile);
FileOutputStream fos = new FileOutputStream(decryptedFile);
crypt(fis, fos, cipher);
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static SecretKey createSecretKey(String algorithm) {
// 声明KeyGenerator对象
KeyGenerator keygen;
// 声明 密钥对象
SecretKey deskey = null;
try {
// 返回生成指定算法的秘密密钥的 KeyGenerator 对象
keygen = KeyGenerator.getInstance(algorithm);
// 生成一个密钥
deskey = keygen.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 返回密匙
return deskey;
}
// 把Key 写到文件中:生成一个私有Key对象,保存在文件中
public static void saveBytePriveKey(String file) {
try {
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecretKey key = keyGen.generateKey();// 生成私钥Key
FileOutputStream fop = new FileOutputStream(file);
fop.write(key.getEncoded());
fop.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static SecretKey getBytePriveKey(String file) throws Exception {
File keyf = new File(file);
long length = keyf.length();
byte[] bytes = new byte[(int) length];
FileInputStream fis = new FileInputStream(keyf);
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
DESKeySpec dks = new DESKeySpec(bytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(dks);
return key;
}
}