常用加密算法

时间:2021-09-10 07:36:29

常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
MD(消息摘要算法),验证数据完整性
消息摘要算法所需jar包

家族(128位摘要信息)
-MD2、MD4、MD5

算法 长度 实现方
MD2 128 JDK
MD4 128 Bouncy Castle
MD5 128 JDK

1、MD加密

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

public class TestMD {

private static String src = "要加密的数据";

public static void main(String[] args) {
// jdkMD5();
// jdkMD2();
bcMD4();
// bcMD5();
// bcMD2();
bcMD41();
// ccMD5();
// jdkMD51();
}

//依赖commons codec(CC)
public static void jdkMD5() {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5Bytes = md.digest(src.getBytes());
System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes));//依赖commons codec(CC)
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

//不依赖任何第三方jar包
public static void jdkMD51() {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(src.getBytes());//可以指定编码格式 如:src.getBytes("GBK")
byte b[] = md.digest();

int i;

StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
System.out.println("JDK MD51:" + buf);
} catch (Exception e) {
e.printStackTrace();
}
}
//依赖CC
public static void jdkMD2() {
try {
MessageDigest md = MessageDigest.getInstance("MD2");
byte[] md5Bytes = md.digest(src.getBytes());
System.out.println("JDK MD2:" + Hex.encodeHexString(md5Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
//依赖bouncycastle(BC)
public static void bcMD4() {
Digest digest = new MD4Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] md4Bytes = new byte[digest.getDigestSize()];
digest.doFinal(md4Bytes, 0);
System.out.println("BC MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
}
//依赖bouncycastle(BC) + jdk
public static void bcMD41() {
Security.addProvider(new BouncyCastleProvider());
try {
MessageDigest md = MessageDigest.getInstance("MD4");
byte[] md4Bytes = md.digest(src.getBytes());
System.out.println("BC MD4:"+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

}
//依赖bc
public static void bcMD5() {
Digest digest = new MD5Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] md4Bytes = new byte[digest.getDigestSize()];
digest.doFinal(md4Bytes, 0);
System.out.println("BC MD5:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
}
//依赖bc
public static void bcMD2() {
Digest digest = new MD2Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] md4Bytes = new byte[digest.getDigestSize()];
digest.doFinal(md4Bytes, 0);
System.out.println("BC MD2:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
}
//依赖CC
public static void ccMD5() {
System.out.println("CC MD5:" + DigestUtils.md5Hex(src.getBytes()));
}

// public static void cdMD2() {
// System.out.println("CC MD2:" + DigestUtils.md2Hex(src.getBytes()));
// }

}

应用场景:比如用户注册,对密码进行消息摘要,保存到数据库中。通过用户名及密码摘要查询,这样达到保护密码的作用。

消息摘要算法-SHA

  • 安全散列算法
  • 固定长度摘要信息
算法 摘要长度 实现方
SHA-1 160 JDK
SHA-224 224 Bouncy Castle
SHA-256 256 JDK
SHA-384 384 JDK
SHA-512 512 JDK

示例代码如下:

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

public class TestSHA {

private static String src = "待加密数据";

public static void main(String[] args) {
jdkSHA1();
bcSHA1();
bcSHA224();
bcSHA224_2();
ccSHA1();
}
//依赖CC
public static void jdkSHA1() {
try {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(src.getBytes());
System.out.println("jdk SHA1:" + Hex.encodeHexString(md.digest()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

//纯jdk
public static void jdkSHA1_2(){
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(src.getBytes("UTF-8"));
System.out.println("jdk SHA-1:" + byteToHexStr(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.println("无法加载SHA 算法。");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.out.println("无法将输入字符串转换到utf ‐8 编码。");
}
}

private static char[] hexChar = {'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F'};

/**
* 将byte数组转换为16进制格式的字符串
* @param bytes 待转换数组
* @return 16进制格式的字符串
*/

public static String byteToHexStr(byte[] bytes){
StringBuffer sb = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
sb.append(hexChar[(bytes[i]&0xf0)>>>4]);
sb.append(hexChar[bytes[i]&0x0f]);
}
return sb.toString();
}

//依赖bc
public static void bcSHA1() {
Digest digest = new SHA1Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] sha1Bytes = new byte[digest.getDigestSize()];
digest.doFinal(sha1Bytes,0);
System.out.println("bc SHA1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
}

public static void bcSHA224() {
Digest digest = new SHA224Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] sha224Bytes = new byte[digest.getDigestSize()];
digest.doFinal(sha224Bytes,0);
System.out.println("bc SHA224:" + org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes));
//
}

public static void bcSHA224_2() {
Security.addProvider(new BouncyCastleProvider());
try {
MessageDigest md = MessageDigest.getInstance("SHA224");
byte[] sha224_2bytes = md.digest(src.getBytes());
System.out.println("bc sha224_2:" + o org.bouncycastle.util.encoders.Hex.toHexString(sha224_2bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
//依赖cc
public static void ccSHA1() {
System.out.println("cc sha1-1:" + new String(DigestUtils.shaHex(src.getBytes())));
System.out.println("cc sha1-2:" + DigestUtils.shaHex(src));
}
}

应用:消息鉴别-指在接收方将原始信息进行摘要,然后与接收到的摘要信息进行对比。
(明文+加入约定Key+时间戳)进行摘要


消息摘要算法-MAC

  • MAC(Message Authentication Code)
  • HMAC(keyed-Hash Message Authentication Code)
    含有密钥的散列函数算法
    示例代码如下:
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
* @author Lijingyu on 2017/8/6.
*/

public class TestMAC {

private static String src = "待加密数据";

public static void main(String[] args) {
jdkHmacMD5();
bcHamcMD5();
}

public static void jdkHmacMD5() {
try {
//初始化KeyGenerator
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
//产生密钥
SecretKey secretKey = keyGenerator.generateKey();
//获得密钥
// byte[] key = secretKey.getEncoded();

byte[] key = Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a'});

//还原密钥
SecretKey restoreSecreKey = new SecretKeySpec(key,"HmacMD5");
//实例化MAC
Mac mac = Mac.getInstance(restoreSecreKey.getAlgorithm());
//初始化Mac
mac.init(restoreSecreKey);
byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
System.out.println("jdk HamcMD5:" + Hex.encodeHexString(hmacMD5Bytes));

} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (DecoderException e) {
e.printStackTrace();
}
}


public static void bcHamcMD5() {
HMac hMac = new HMac(new MD5Digest());
hMac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("aaaaaaaa")));
hMac.update(src.getBytes(),0,src.getBytes().length);

byte[] hmacMD5Bytes = new byte[hMac.getMacSize()];
hMac.doFinal(hmacMD5Bytes,0);
System.out.println("bc hmacmd5:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));
}

}

对称加密算法

  • 加密密钥 = 解密密钥
  • 初等DES,3DES
  • AES
  • PBE
  • IDEA
密钥长度 默认 工作模式 填充方式 实现方
56 56 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128 NoPadding、PKCS5Padding、ISO10126Padding JDK
64 56 同上 PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding BC

DES -被破解 示例如下:

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

/**
* 对称加密算法
*/

public class TestDES {

private static String src = "待加密数据";

public static void main(String[] args) {
jdkDES();
bcDES();
}

public static void jdkDES(){
try {
//生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);
SecretKey secretKey = keyGenerator.generateKey();

byte[] byteskey = secretKey.getEncoded();

//KEY转换
DESKeySpec desKeySpec = new DESKeySpec(byteskey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey convertSecreKey = factory.generateSecret(desKeySpec);

//加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,convertSecreKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk des encrypt:" + Hex.encodeHexString(result));

//解密
cipher.init(Cipher.DECRYPT_MODE,convertSecreKey);
result = cipher.doFinal(result);
System.out.println("jdk des decrypt:" + new String(result));

} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}

//推荐BC
public static void bcDES() {
try {
Security.addProvider(new BouncyCastleProvider());

//生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");
keyGenerator.getProvider();
keyGenerator.init(56);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteskey = secretKey.getEncoded();

//KEY转换
DESKeySpec desKeySpec = new DESKeySpec(byteskey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey convertSecreKey = factory.generateSecret(desKeySpec);

//加密
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE,convertSecreKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bc des encrypt:" + Hex.encodeHexString(result));

//解密
cipher.init(Cipher.DECRYPT_MODE,convertSecreKey);
result = cipher.doFinal(result);
System.out.println("bc des decrypt:" + new String(result));

} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
}


}

3重DES(3DES、Triple DES、DESede)

  • 违反科克霍夫原则
  • 安全问题
    好处:

  • 密钥长度增强

  • 迭代次数提高
密钥长度 默认 工作模式 填充方式 实现方
112、168 168 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128 NoPadding、PKCS5Padding、ISO10126Padding JDK
128、192 168 同上 PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding BC
import org.apache.commons.codec.binary.Hex;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

public class Test3DES {

private static String src = "待加密数据";

public static void main(String[] args) {
jdk3DES();
}

public static void jdk3DES() {
try {
//生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
// keyGenerator.init(168);
keyGenerator.init(new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();

byte[] byteskey = secretKey.getEncoded();

//KEY转换
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteskey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey convertSecreKey = factory.generateSecret(desKeySpec);

//加密
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, convertSecreKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk 3des encrypt:" + Hex.encodeHexString(result));

//解密
cipher.init(Cipher.DECRYPT_MODE, convertSecreKey);
result = cipher.doFinal(result);
System.out.println("jdk 3des decrypt:" + new String(result));

} catch (Exception e) {
e.printStackTrace();
}
}

//推荐BC
public static void bc3DES() {
try {
Security.addProvider(new BouncyCastleProvider());

//生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede","BC");
keyGenerator.getProvider();
keyGenerator.init(new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteskey = secretKey.getEncoded();

//KEY转换
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteskey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey convertSecreKey = factory.generateSecret(desKeySpec);

//加密
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE,convertSecreKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bc 3des encrypt:" + Hex.encodeHexString(result));

//解密
cipher.init(Cipher.DECRYPT_MODE,convertSecreKey);
result = cipher.doFinal(result);
System.out.println("bc 3des decrypt:" + new String(result));

} catch Exception e) {
e.printStackTrace();
}
}

}

2、对称加密算法-AES加解密

  • AES是目前使用最多的对称加密算法
  • AES优势之一是至今尚未被破解
  • AES通常用于移动系统加密以及基于SSH协议的软件,SSHClient、secreCRT
  • 高级
  • DES替代者
密钥长度 默认 工作模式 填充方式 实现方
128、192、256 128 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128 NoPadding、PKCS5Padding、ISO10126Padding JDK(256位密钥需要获得无政策权限限制文件)
同上 同上 同上 PKCS7Padding、ZeroBytePadding BC

- 发送者:构建密钥,公布密钥给接收者,使用密钥对数据加密,发送加密数据给接收者
- 接收者:使用密钥对数据进行解密

mport java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class TestAES {
static String src = "待加密数据";
/**
* @param args
*/

public static void main(String[] args) {
// TODO Auto-generated method stub
jdkAES();
bcDES();
}

public static void jdkAES() {
// 生成key
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();

// key转换
java.security.Key key = new SecretKeySpec(keyBytes, "AES");

// 加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(src.getBytes());
System.out.print("jdk aes encrypt:"
+ Base64.encodeBase64String(result));

// 解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("jdk aes decrypt:" + new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void bcDES() {
Security.addProvider(new BouncyCastleProvider());
// 生成key
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BC");
keyGenerator.getProvider();
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteskey = secretKey.getEncoded();

// key转换
java.security.Key key = new SecretKeySpec(byteskey, "AES");

// 加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(src.getBytes());
System.out.print("bc aes encrypt:"
+ Base64.encodeBase64String(result));

// 解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("bc aes dectypt:" + new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
class AESEncryptUtil {
public static final Logger logger=Logger.getLogger(AESEncryptUtil.class);
/**
* AES加密
*
* @param key
* 密钥信息
* @param content
* 待加密信息
*/

public static byte[] encodeAES(byte[] key, byte[] content) throws Exception {
// 不是16的倍数的,补足
int base = 16;
if (key.length % base != 0) {
int groups = key.length / base + (key.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}

SecretKey secretKey = new SecretKeySpec(key, "AES");
IvParameterSpec iv = new IvParameterSpec(new byte[] {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'});
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] tgtBytes = cipher.doFinal(content);
return tgtBytes;
}

/**
* AES解密
*
* @param key
* 密钥信息
* @param content
* 待加密信息
* @return
* @throws Exception
*/

public static byte[] decodeAES(byte[] key, byte[] content) throws Exception {
// 不是16的倍数的,补足
int base = 16;
if (key.length % base != 0) {
int groups = key.length / base + (key.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}

SecretKey secretKey = new SecretKeySpec(key, "AES");
IvParameterSpec iv = new IvParameterSpec(new byte[] { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' });
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] tgtBytes = cipher.doFinal(content);
return tgtBytes;
}

/**
* 加密文件
*
* @param key
* 密钥
* @param plainFilePath
* 明文文件路径路径
* @param secretFilePath
* 密文文件路径
* @throws Exception
*/

public static void encodeAESFile(byte[] key, String plainFilePath, String secretFilePath) throws Exception {
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
FileOutputStream fos = null;
try {

fis = new FileInputStream(plainFilePath);
bos = new ByteArrayOutputStream(fis.available());

byte[] buffer = new byte[1024];
int count = 0;
while ((count = fis.read(buffer)) != -1) {
bos.write(buffer, 0, count);
}
bos.flush();

byte[] bytes = encodeAES(key, bos.toByteArray());

fos = new FileOutputStream(secretFilePath);
fos.write(bytes);
fos.flush();
} catch (Exception e) {
throw e;
} finally {
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
if (bos != null) {
try {
bos.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
}

/**
* 解密文件
*
* @param key
* 密钥
* @param plainFilePath
* 明文文件路径路径
* @param secretFilePath
* 密文文件路径
* @throws Exception
*/

public static void decodeAESFile(byte[] key, String plainFilePath, String secretFilePath) throws Exception {
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(secretFilePath);
bos = new ByteArrayOutputStream(fis.available());

byte[] buffer = new byte[1024];
int count = 0;
while ((count = fis.read(buffer)) != -1) {
bos.write(buffer, 0, count);
}
bos.flush();

byte[] bytes = decodeAES(key, bos.toByteArray());

fos = new FileOutputStream(plainFilePath);
fos.write(bytes);
fos.flush();
} catch (Exception e) {
throw e;
} finally {
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
if (bos != null) {
try {
bos.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
}
}

对称加密算法-PBE

  • PBE算法结合了消息摘要算法和对称加密算法的优点
  • PBE(Password Based Encryption)基于口令加密
  • 穷举破译 加盐(salt)进行扰乱
  • 对已有算法包装
  • JDK、BC
  • PBEWithMD5AndDES
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.commons.codec.binary.Base64;

/**
* @description:
*
* @author : lijy
* @date : 2017-8-17
*/

public class TestPBE {

static String src = "带机密数据";

public static void main(String[] args) {
jdkPBE();
}

public static void jdkPBE() {

try {
//初始化盐
SecureRandom random = new SecureRandom();
byte[] salt = random.generateSeed(8);

//口令转密钥
String password = "123456";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
Key key = factory.generateSecret(pbeKeySpec);

//加密
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk pbe encrypt:" + Base64.encodeBase64String(result));

//解密
cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
result = cipher.doFinal(result);
System.out.println("jdk pbe decrypt:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}
  • 发送者
  • 1、构建口令,2公布口令给接收者,3构建盐,4使用口令对数据加密。5发送盐、加密数据给接收者,接收者使用口令、盐对数据解密