[原创]Java实现PKCS7填充的DES加密(修订版)
在一个项目中,要求C#和Java交互,为了保障数据的安全传输,我们用到DES加密。
在DES加密中,要求指定Key,IV,CipherMode(CBC),PaddingMode。Key和IV,CipherMode都好说,只是PaddingMode不好指定,因为C#的模式有:ANSIX923、ISO10126、None、PKCS7、Zero,而Java有:OAEPWith<digest>And<mgf>Padding、PKCS5Padding、SSL3Padding,没有交集呀。
我用C#先写出来的,PaddingMode = PKCS7,Java方的不好作了。没有办法,只好帮人家写一个Java的例子,于是有了下面的代码:(Java高手不要笑话呀)
import java.io.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import sun.misc.BASE64Encoder;
/*
作者:阿牛(牛昆亮) QQ:273352165 MSN:niukl@hotmail.com
声明:可以免费使用,请您保留此信息
如果您有什么改过,记得告诉我!
*/
public class DesPKCS7Encrypter {
Cipher ecipher;
Cipher dcipher;
DesPKCS7Encrypter(byte[] keyBytes, byte[] ivBytes)
throws Exception
{
Init(keyBytes,ivBytes);
}
DesPKCS7Encrypter(DESKeySpec keySpec, IvParameterSpec ivSpec)
throws Exception
{
Init(keySpec,ivSpec);
}
private void Init(byte[] keyBytes, byte[] ivBytes)
throws Exception
{
DESKeySpec dks = new DESKeySpec(keyBytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Init(key,iv);
}
private void Init(DESKeySpec keySpec, IvParameterSpec iv)
throws Exception
{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( keySpec );
Init(key,iv);
}
private void Init(SecretKey key, IvParameterSpec iv)
throws Exception
{
AlgorithmParameterSpec paramSpec = iv;
try {
ecipher = Cipher.getInstance("DES/CBC/NoPadding");
dcipher = Cipher.getInstance("DES/CBC/NoPadding");
// CBC requires an initialization vector
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
}
catch (Exception e) {
throw e;
}
}
public void encrypt(InputStream in, OutputStream out) {
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
byte[] buf = new byte[this.ecipher.getBlockSize()];
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while (true)
{
numRead = in.read(buf);
boolean bBreak = false;
if(numRead == -1 || numRead < buf.length)
{
int pos = numRead == -1? 0:numRead;
byte byteFill = (byte)(buf.length - pos);
for(int i = pos;i<buf.length; ++i)
{
buf[i] = byteFill;
}
bBreak = true;
}
out.write(buf);
if(bBreak)
break;
}
out.close();
} catch (java.io.IOException e) {
System.out.println("Exception e in encrypt="+e);
}
}
public void decrypt(InputStream in, OutputStream out) {
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
byte[] buf = new byte[this.dcipher.getBlockSize()];
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
if(in.available() > 0)
{
out.write(buf, 0, numRead);
}
else
{
byte byteBlock = buf[buf.length -1];
int i = 0;
for(i = buf.length - byteBlock; i >= 0 && i < buf.length; ++i)
{
if(buf[i] != byteBlock)
{
break;
}
}
if(i == buf.length)
{
out.write(buf,0,buf.length - byteBlock);
}
else
{
out.write(buf);
}
}
}
out.close();
} catch (java.io.IOException e) {
System.out.println("Exception e in decrypt="+e);
}
}
public static void main(String args[])
{
try
{
// 生成Key和IV
byte[] byteKey = new byte[8]; //"12345678".getBytes("ASCII");
byte[] byteIv = new byte[8]; //"98765432".getBytes("ASCII");
FileInputStream fisKey = new FileInputStream("key.dat");
FileInputStream fisIv = new FileInputStream("iv.dat");
fisKey.read(byteKey);
fisIv.read(byteIv);
fisKey.close();
fisIv.close();
// 创建加密实例
DesPKCS7Encrypter encrypter = new DesPKCS7Encrypter(byteKey,byteIv);
// 生成要加密的数据
String strData = "ni hao";
System.out.println(strData);
ByteArrayInputStream bais = new ByteArrayInputStream(strData.getBytes("utf-8"));
// 声明加密输出
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Base64 加密实例
BASE64Encoder base64Encoder = new BASE64Encoder();
//加密
encrypter.encrypt(bais,baos);
//Base64加密
String outStr = base64Encoder.encode(baos.toByteArray());
//结果
System.out.println(outStr);
// 初始化解密数据
bais = new ByteArrayInputStream(baos.toByteArray());
// 声明解密输出
baos = new ByteArrayOutputStream();
// 解密
encrypter.decrypt(bais,baos);
//查看解密结果
System.out.println(baos.toString("utf-8"));
} catch (Exception e) {
System.out.println("Exception e="+e);
}
}
}
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import sun.misc.BASE64Encoder;
/*
作者:阿牛(牛昆亮) QQ:273352165 MSN:niukl@hotmail.com
声明:可以免费使用,请您保留此信息
如果您有什么改过,记得告诉我!
*/
public class DesPKCS7Encrypter {
Cipher ecipher;
Cipher dcipher;
DesPKCS7Encrypter(byte[] keyBytes, byte[] ivBytes)
throws Exception
{
Init(keyBytes,ivBytes);
}
DesPKCS7Encrypter(DESKeySpec keySpec, IvParameterSpec ivSpec)
throws Exception
{
Init(keySpec,ivSpec);
}
private void Init(byte[] keyBytes, byte[] ivBytes)
throws Exception
{
DESKeySpec dks = new DESKeySpec(keyBytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Init(key,iv);
}
private void Init(DESKeySpec keySpec, IvParameterSpec iv)
throws Exception
{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( keySpec );
Init(key,iv);
}
private void Init(SecretKey key, IvParameterSpec iv)
throws Exception
{
AlgorithmParameterSpec paramSpec = iv;
try {
ecipher = Cipher.getInstance("DES/CBC/NoPadding");
dcipher = Cipher.getInstance("DES/CBC/NoPadding");
// CBC requires an initialization vector
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
}
catch (Exception e) {
throw e;
}
}
public void encrypt(InputStream in, OutputStream out) {
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
byte[] buf = new byte[this.ecipher.getBlockSize()];
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while (true)
{
numRead = in.read(buf);
boolean bBreak = false;
if(numRead == -1 || numRead < buf.length)
{
int pos = numRead == -1? 0:numRead;
byte byteFill = (byte)(buf.length - pos);
for(int i = pos;i<buf.length; ++i)
{
buf[i] = byteFill;
}
bBreak = true;
}
out.write(buf);
if(bBreak)
break;
}
out.close();
} catch (java.io.IOException e) {
System.out.println("Exception e in encrypt="+e);
}
}
public void decrypt(InputStream in, OutputStream out) {
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
byte[] buf = new byte[this.dcipher.getBlockSize()];
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
if(in.available() > 0)
{
out.write(buf, 0, numRead);
}
else
{
byte byteBlock = buf[buf.length -1];
int i = 0;
for(i = buf.length - byteBlock; i >= 0 && i < buf.length; ++i)
{
if(buf[i] != byteBlock)
{
break;
}
}
if(i == buf.length)
{
out.write(buf,0,buf.length - byteBlock);
}
else
{
out.write(buf);
}
}
}
out.close();
} catch (java.io.IOException e) {
System.out.println("Exception e in decrypt="+e);
}
}
public static void main(String args[])
{
try
{
// 生成Key和IV
byte[] byteKey = new byte[8]; //"12345678".getBytes("ASCII");
byte[] byteIv = new byte[8]; //"98765432".getBytes("ASCII");
FileInputStream fisKey = new FileInputStream("key.dat");
FileInputStream fisIv = new FileInputStream("iv.dat");
fisKey.read(byteKey);
fisIv.read(byteIv);
fisKey.close();
fisIv.close();
// 创建加密实例
DesPKCS7Encrypter encrypter = new DesPKCS7Encrypter(byteKey,byteIv);
// 生成要加密的数据
String strData = "ni hao";
System.out.println(strData);
ByteArrayInputStream bais = new ByteArrayInputStream(strData.getBytes("utf-8"));
// 声明加密输出
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Base64 加密实例
BASE64Encoder base64Encoder = new BASE64Encoder();
//加密
encrypter.encrypt(bais,baos);
//Base64加密
String outStr = base64Encoder.encode(baos.toByteArray());
//结果
System.out.println(outStr);
// 初始化解密数据
bais = new ByteArrayInputStream(baos.toByteArray());
// 声明解密输出
baos = new ByteArrayOutputStream();
// 解密
encrypter.decrypt(bais,baos);
//查看解密结果
System.out.println(baos.toString("utf-8"));
} catch (Exception e) {
System.out.println("Exception e="+e);
}
}
}
也许还有更好的方法,也许Java已经有了该方法。还请高手告诉我呀。
QQ:273352165
evlon#126.com
转载请注明出处。