加密算法
加密算法可以分为单向加密算法、对称加密算法和非对称加密算法。
-
单向加密算法:只能加密不能解密,输入是任意长度字符串,输出是固定长度的字符串。常见的有MD算法、SHA算法,一般用于信息摘要。
-
对称加密算法:既能加密又能解密,并且加密解密使用相同的密钥。常见的有AES、DES算法,一般用于数字签名。
-
非对称加密算法:既能加密又能解密,密钥成对出现,被公钥加密的密文只能被私钥解密,被私钥加密的密文只能被公钥解密。常见的有RSA算法,一般用于数字签名。
MD5算法
输入任意长度字符串,输出32位16进制字符串。
public class Md5Util {
private static MessageDigest md5;
static{
try{
md5=MessageDigest.getInstance("MD5");
}
catch(NoSuchAlgorithmException ex){
ex.printStackTrace();
}
}
/**
* MD5加密
* @param primitiveValue 原始值
* @return 加密值
*/
public static byte[] encrypt(byte[] primitiveValue){
md5.update(primitiveValue);
return md5.digest();
}
}
复制代码
SHA1算法
输入任意长度字符串,输出40位16进制字符串。
public class Sha1Until {
private static MessageDigest sha1;
static{
try{
sha1=MessageDigest.getInstance("SHA1");
}
catch(NoSuchAlgorithmException ex){
ex.printStackTrace();
}
}
/**
* SHA1加密
* @param primitiveValue 原始值
* @return 加密值
*/
public static byte[] encrypt(byte[] primitiveValue){
sha1.update(primitiveValue);
return sha1.digest();
}
}
复制代码
MD5和SHA1是类似的,不过后者的安全性更强一些,它们一般用于信息摘要,以确保数据不被篡改。
HMAC算法
HMAC算法是以单向加密算法为基础,添加密钥,以确保数据不被伪造。
public class HmacUtil {
/**
* HMAC加密
* @param key 密钥
* @param primitiveValue 原始值
* @return 加密值
*/
private static byte[] encrypt(byte[] key,byte[] primitiveValue,String algorithm){
try{
SecretKey secretKey = new SecretKeySpec(key,algorithm);
Mac mac=Mac.getInstance(algorithm);
mac.init(secretKey);
return mac.doFinal(primitiveValue);
}
catch(InvalidKeyException | NoSuchAlgorithmException ex){
ex.printStackTrace();
return null;
}
}
/**
* HMAC加密,使用MD5
* @param key 密钥
* @param primitiveValue 原始值
* @return 加密值
*/
public static byte[] encryptByMd5(byte[] key,byte[] primitiveValue){
return encrypt(key,primitiveValue,"HmacMD5");
}
/**
* HMAC加密,使用SHA1
* @param key 密钥
* @param primitiveValue 原始值
* @return 加密值
*/
public static byte[] encryptBySha1(byte[] key,byte[] primitiveValue){
return encrypt(key,primitiveValue,"HmacSHA1");
}
}
复制代码
AES算法
AES算法是对称加密算法。
public class AesUtil {
private static SecretKeySpec keySpec;
private static IvParameterSpec iv;
private static Cipher cipher;
static{
try {
cipher = Cipher.getInstance("AES/CFB/NoPadding");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void init(byte[] aesKey) {
if ((aesKey.length == 16)||(aesKey.length==24)||(aesKey.length==32)) {
keySpec = new SecretKeySpec(aesKey, "AES");
iv = new IvParameterSpec(Md5Util.encrypt(aesKey));
}
else{
throw new RuntimeException("密钥长度无效,只能是16、24或32字节");
}
}
/**
* AES加密
* @param key 密钥
* @param primitivaValue 原始值
* @return 加密值
*/
public static byte[] encrypt(byte[] key,byte[] primitivaValue) {
init(key);
try {
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
return cipher.doFinal(primitivaValue);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* AES解密
* @param key 密钥
* @param encryptedValue 加密值
* @return 原始值
*/
public static byte[] decrypt(byte[] key,byte[] encryptedValue) {
init(key);
try {
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
return cipher.doFinal(encryptedValue);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
复制代码
RSA算法
RSA是非对称加密算法。
public class RsaUtil {
private static Cipher cipher;
static{
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
}
/**
* 生成密钥对
* @param keySize 密钥对长度
* @param seed 随机数种子
* @return 密钥对
*/
public static KeyPair generateKeyPair(int keySize,byte[] seed){
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048,new SecureRandom(seed));
return keyPairGen.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获得密钥经base64编码后文本
* @param key 密钥
* @return 文本
*/
public static String getKeyText(Key key) {
return (new BASE64Encoder()).encode(key.getEncoded());
}
/**
* 加密
* @param key 密钥
* @param primitiveValue
* @return 原始值
*/
public static String encrypt(Key key, String primitiveValue){
try {
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] enBytes = cipher.doFinal(primitiveValue.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 解密
* @param key 密钥
* @param encryptedValue 加密值
* @return
*/
public static String decrypt(Key key, String encryptedValue){
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(encryptedValue));
return new String(deBytes);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
复制代码
典型应用
数字签名
数字签名,就是一种身份认证的方式。数字签名通常定义两种互补的操作,一个用于签名,另一个用于验证。分别由发送者持有能够代表自己身份的私钥 (私钥不可泄露),由接受者持有与私钥对应的公钥(公钥是公开的) ,能够在接受 到来自发送者信息时用于验证其身份。