文章16 | 阅读 7019 | 点赞0
PBE(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。PBE算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由PBE算法中的KDF函数完成。KDF函数的实现过程为:将用户输入的口令首先通过“盐”(salt)的扰乱产生准密钥,再将准密钥经过散列函数多次迭代后生成最终加密密钥,密钥生成后,PBE算法再选用对称加密算法对数据进行加密,可以选择DES、3DES、RC5等对称加密算法。
package com.jianggujin.codec;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import com.jianggujin.codec.util.JCipherInputStream;
import com.jianggujin.codec.util.JCipherOutputStream;
import com.jianggujin.codec.util.JCodecException;
/** * Password-based encryption(基于密码加密) * * @author jianggujin * */
public class JPBE {
/** * 默认迭代次数 */
public static final int DEFAULT_ITERATION_COUNT = 100;
/** * PBE算法 * * @author jianggujin * */
public static enum JPBEAlgorithm {
PBEWithMD5AndDES, PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40;
public String getName() {
return this.name();
}
}
/** * 初始化盐 * * @return */
public static byte[] initSalt() {
byte[] salt = new byte[8];
Random random = new Random();
random.nextBytes(salt);
return salt;
}
/** * 加密 * * @param data * @param password * @param salt * @param algorithm * @return */
public static byte[] encrypt(byte[] data, char[] password, byte[] salt, String algorithm) {
return encrypt(data, password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 加密 * * @param data * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static byte[] encrypt(byte[] data, char[] password, byte[] salt, int iterationCount, String algorithm) {
// 数据加密
Cipher cipher = getEncryptCipher(password, salt, iterationCount, algorithm);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 包裹输出流,包裹后的输出流为加密输出流 * * @param out * @param password * @param salt * @param algorithm * @return */
public static OutputStream wrap(OutputStream out, char[] password, byte[] salt, String algorithm) {
return wrap(out, password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 包裹输出流,包裹后的输出流为加密输出流 * * @param out * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static OutputStream wrap(OutputStream out, char[] password, byte[] salt, int iterationCount,
String algorithm) {
// 数据加密
Cipher cipher = getEncryptCipher(password, salt, iterationCount, algorithm);
return new JCipherOutputStream(cipher, out);
}
/** * 获得加密模式的{@link Cipher} * * @param password * @param salt * @param algorithm * @return */
public static Cipher getEncryptCipher(char[] password, byte[] salt, String algorithm) {
return getEncryptCipher(password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 获得加密模式的{@link Cipher} * * @param data * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static Cipher getEncryptCipher(char[] password, byte[] salt, int iterationCount, String algorithm) {
return getCipher(password, salt, iterationCount, algorithm, Cipher.ENCRYPT_MODE);
}
/** * 解密 * * @param data * @param password * @param salt * @param algorithm * @return */
public static byte[] decrypt(byte[] data, char[] password, byte[] salt, String algorithm) {
return decrypt(data, password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 解密 * * @param data * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static byte[] decrypt(byte[] data, char[] password, byte[] salt, int iterationCount, String algorithm) {
// 数据解密
Cipher cipher = getDecryptCipher(password, salt, iterationCount, algorithm);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 包裹输入流,原输入流为加密数据输入流 * * @param in * @param password * @param salt * @param algorithm * @return */
public static InputStream wrap(InputStream in, char[] password, byte[] salt, String algorithm) {
return wrap(in, password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 包裹输入流,原输入流为加密数据输入流 * * @param in * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static InputStream wrap(InputStream in, char[] password, byte[] salt, int iterationCount, String algorithm) {
// 数据解密
Cipher cipher = getDecryptCipher(password, salt, iterationCount, algorithm);
return new JCipherInputStream(cipher, in);
}
/** * 获得解密模式的{@link Cipher} * * @param password * @param salt * @param algorithm * @return */
public static Cipher getDecryptCipher(char[] password, byte[] salt, String algorithm) {
return getDecryptCipher(password, salt, DEFAULT_ITERATION_COUNT, algorithm);
}
/** * 获得解密模式的{@link Cipher} * * @param password * @param salt * @param iterationCount * @param algorithm * @return */
public static Cipher getDecryptCipher(char[] password, byte[] salt, int iterationCount, String algorithm) {
return getCipher(password, salt, iterationCount, algorithm, Cipher.DECRYPT_MODE);
}
private static Cipher getCipher(char[] password, byte[] salt, int iterationCount, String algorithm, int opmode) {
// 生成本地密钥
SecretKey secretKey = getSecretKey(password, algorithm);
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
try {
// 数据加密
Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
cipher.init(opmode, secretKey, paramSpec);
return cipher;
} catch (Exception e) {
throw new JCodecException(e);
}
}
private static SecretKey getSecretKey(char[] password, String algorithm) {
try {
PBEKeySpec keySpec = new PBEKeySpec(password);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
return keyFactory.generateSecret(keySpec);
} catch (Exception e) {
throw new JCodecException(e);
}
}
}
测试代码:
package com.jianggujin.codec.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.junit.Test;
import com.jianggujin.codec.JBase64;
import com.jianggujin.codec.JBase64.JEncoder;
import com.jianggujin.codec.JPBE;
import com.jianggujin.codec.JPBE.JPBEAlgorithm;
public class PBETest {
String str = "jianggujin";
String password = "12345678";
File file = new File(getClass().getSimpleName() + ".dat");
@Test
public void test() throws Exception {
System.out.println("原串:" + str);
JEncoder encoder = JBase64.getEncoder();
byte[] salt = JPBE.initSalt();
System.out.println("盐:" + encoder.encodeToString(salt, "UTF-8"));
System.out.println("密码:" + password);
for (JPBEAlgorithm algorithm : JPBEAlgorithm.values()) {
System.out.println("-----------------------------------------");
System.out.println("算法:" + algorithm.getName());
byte[] encrypt = JPBE.encrypt(str.getBytes(), password.toCharArray(), salt, algorithm.getName());
System.out.println("加密:" + encoder.encodeToString(encrypt, "UTF-8"));
System.out
.println("解密:" + new String(JPBE.decrypt(encrypt, password.toCharArray(), salt, algorithm.getName())));
System.out.print("输出流加密:" + file.getAbsolutePath());
OutputStream out = JPBE.wrap(new FileOutputStream(file), password.toCharArray(), salt, algorithm.getName());
out.write(str.getBytes());
out.flush();
out.close();
System.out.println();
System.out.print("输入流解密:");
InputStream in = JPBE.wrap(new FileInputStream(file), password.toCharArray(), salt, algorithm.getName());
byte[] buffer = new byte[1024];
int len = in.read(buffer);
System.out.println(new String(buffer, 0, len));
}
}
}
测试结果:
原串:jianggujin
盐:pWJQ1HJ61xY=
密码:12345678
—————————————–
算法:PBEWithMD5AndDES
加密:hHk6186Lq1+VmcgYzs/8lw==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\PBETest.dat
输入流解密:jianggujin
—————————————–
算法:PBEWithSHA1AndDESede
加密:uN/5iUjaUKYjfTqas8dhvw==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\PBETest.dat
输入流解密:jianggujin
—————————————–
算法:PBEWithSHA1AndRC2_40
加密:J7aT2klCSCAVjAg4q3cR5A==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\PBETest.dat
输入流解密:jianggujin
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/jianggujin/article/details/50537070
内容来源于网络,如有侵权,请联系作者删除!