数据加密和解密
数据加密 的基本过程,就是对原来为 明文 的文件或数据按 某种算法 进行处理,使其成为 不可读 的一段代码,通常称为 “密文”。通过这样的途径,来达到 保护数据 不被 非法人窃取、阅读的目的。
加密 的 逆过程 为 解密,即将该 编码信息 转化为其 原来数据 的过程
对称加密算法 (AES / DES / 3DES)
对称式加密就是加密和解密使用同一个密钥, 又称为 共享密钥加密算法
AES 本身就是为了取代 DES 的,AES 具有更好的 安全性、效率 和 灵活性。[1]
AES 加密算法是密码学中的 高级加密标准,该加密算法采用 对称分组密码体制,密钥长度的最少支持为 128 位、 192 位、256 位,分组长度 128 位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的 区块加密标准。[1]
非对称加密算法 (RSA / DSA / ECC)
非对称式加密 就是加密和解密 使用两个不同的密钥, 又称为 公开密钥加密算法, 通常有两个密钥 公钥(public key)
和 私钥(private key)
散列算法 (MD5 / SHA1 / HMAC)
Hash算法: MD2 / MD4 / MD5 / HAVAL / SHA / SHA-1 / HMAC / HMAC-MD5 / HMAC-SHA1
MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)
SHA1 是和 MD5 一样流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更强
java 实现
AES
public class AES256Util {
/**
* 密钥, 256位32个字节
*/
public static final String DEFAULT_SECRET_KEY = "iNsLseFmH82LdIz14LsMwqBcZb02xIAd";
/**
* 初始向量IV, 初始向量IV的长度规定为128位16个字节, 初始向量的来源为随机生成.
*/
private static final byte[] KEY_VI = "jI46Ql9owOk0zPrN".getBytes();
/**
* 加密解密算法/加密模式/填充方式
*/
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String AES = "AES";
private static java.util.Base64.Encoder base64Encoder = java.util.Base64.getEncoder();
private static java.util.Base64.Decoder base64Decoder = java.util.Base64.getDecoder();
/**
* AES加密
*/
public static String encode(String key, String content) {
try {
javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(KEY_VI);
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey, iv);
// 获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte[] byteEncode = content.getBytes(java.nio.charset.StandardCharsets.UTF_8);
// 根据密码器的初始化方式加密
byte[] byteAES = cipher.doFinal(byteEncode);
// 将加密后的数据转换为字符串
return base64Encoder.encodeToString(byteAES);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* AES解密
*/
public static String decode(String key, String content) {
try {
javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(KEY_VI);
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, iv);
// 将加密并编码后的内容解码成字节数组
byte[] byteContent = base64Decoder.decode(content);
// 解密
byte[] byteDecode = cipher.doFinal(byteContent);
return new String(byteDecode, java.nio.charset.StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String dbPassword = "abc123def456";
String encryptDbPwd = AES256Util.encode(DEFAULT_SECRET_KEY, dbPassword);
System.out.println("encrypt: " + encryptDbPwd);
String decrypt = AES256Util.decode(DEFAULT_SECRET_KEY, encryptDbPwd);
System.out.println("decrypt: " + decrypt);
}
}
RSA
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RSAUtil {
private String algorithm = "RSA";
private Integer keySize = 1024;
private String publicKeyFile = "/var/tmp/temp_key_pub";
private String privateKeyFile = "/var/tmp/temp_key_pri";
public static void main(String[] args) {
RSAUtil rsaUtil = new RSAUtil();
Map<String, String> keyPairMap = rsaUtil.initKeyPair();
String publicKey = keyPairMap.get("publicKey");
String privateKey = keyPairMap.get("privateKey");
System.out.println("公钥:");
System.out.println(publicKey);
System.out.println();
System.out.println("私钥:");
System.out.println(privateKey);
System.out.println();
String source = "Hello World";
System.out.println("待加密字符串:" + source);
System.out.println();
String strEncrypt = rsaUtil.encrypt(source);
System.out.println("加密后的字符串:");
System.out.println(strEncrypt);
System.out.println();
String strDecrypt = rsaUtil.decrypt(strEncrypt);
System.out.println("解密后的字符串:");
System.out.println(strDecrypt);
}
// MARK: 私有方法
/**
* 生成密钥对
*
* @return 返回map集合,其中包含publicKey与privateKey
* @throws NoSuchAlgorithmException
*/
private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
/**
* RSA算法要求有一个可信任的随机数源
*/
SecureRandom secureRandom = new SecureRandom();
/**
* 为RSA算法创建一个KeyPairGenerator对象
*/
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
/**
* 利用上面的随机数据源初始化这个KeyPairGenerator对象
*/
keyPairGenerator.initialize(keySize, secureRandom);
/**
* 生成密匙对
*/
KeyPair keyPair = keyPairGenerator.generateKeyPair();
/**
* 得到公钥
*/
Key publicKey = keyPair.getPublic();
/**
* 得到私钥
*/
Key privateKey = keyPair.getPrivate();
Map<String, Key> keyPairMap = new HashMap<>();
keyPairMap.put("publicKey", publicKey);
keyPairMap.put("privateKey", privateKey);
return keyPairMap;
}
/**
* 获取文件中获取密钥对象
*
* @param fileName 文件名
* @return 密钥对象
*/
private Key getKeyFromFile(String fileName) {
Key key = null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(fileName));
key = (Key) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return key;
}
/**
* 将密钥对生成到文件中
*/
private void generateKeyPairToFiles() {
ObjectOutputStream oosPublicKey = null;
ObjectOutputStream oosPrivateKey = null;
try {
oosPublicKey = new ObjectOutputStream(new FileOutputStream(publicKeyFile));
oosPrivateKey = new ObjectOutputStream(new FileOutputStream(privateKeyFile));
Map<String, Key> keyPairMap = generateKeyPair();
Key publicKey = keyPairMap.get("publicKey");
Key privateKey = keyPairMap.get("privateKey");
oosPublicKey.writeObject(publicKey);
oosPrivateKey.writeObject(privateKey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
/**
* 清空缓存,关闭文件输出流
*/
oosPublicKey.close();
oosPrivateKey.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// MARK: 公有方法
/**
* 初始化密钥对文件
*
* @return 返回密钥对信息【publicKey(公钥字符串)、、privateKey(私钥字符串)】
*/
public Map<String, String> initKeyPair() {
Map<String, String> keyPairMap = new HashMap<>();
File publicFile = new File(publicKeyFile);
File privateFile = new File(privateKeyFile);
/**
* 判断是否存在公钥和私钥文件
*/
if (!publicFile.exists() || !privateFile.exists()) {
generateKeyPairToFiles();
}
Key publicKey = getKeyFromFile(publicKeyFile);
Key privateKey = getKeyFromFile(privateKeyFile);
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
/**
* 公钥字符串
*/
keyPairMap.put("publicKey", publicKeyBase64);
/**
* 私钥字符串
*/
keyPairMap.put("privateKey", privateKeyBase64);
return keyPairMap;
}
/**
* 加密方法
*
* @param source 源数据
* @return 加密后的字符串
*/
public String encrypt(String source) {
Key publicKey = getKeyFromFile(publicKeyFile);
String encryptSource = null;
try {
/**
* 得到Cipher对象来实现对源数据的RSA加密
*/
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = source.getBytes();
/**
* 执行加密操作
*/
encryptSource = Base64.getEncoder().encodeToString(cipher.doFinal(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptSource;
}
/**
* 解密方法
*
* @param source 密文
* @return 解密后的字符串
*/
public String decrypt(String source) {
Key privateKey = getKeyFromFile(privateKeyFile);
String decryptSource = null;
try {
/**
* 得到Cipher对象对已用公钥加密的数据进行RSA解密
*/
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
/**
* 执行解密操作
*/
byte[] bytes = Base64.getDecoder().decode(source);
decryptSource = new String(cipher.doFinal(bytes), "UTF-8");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptSource;
}
}
网友评论