什么数据需要加密
密码、用户不公开数据比如个人隐私、个人可见数据,为了信息安全,需要在传输、存储时加密。
区分加密与编码
1. aes加密:用于对密钥、敏感数据进行加密
2. base64编码:文本中的emoji,如果直接存进数据库很有可能有乱码问题,用base64编码后存储可解决。
对称加密与非对称加密
签名与加密
签名:防篡改,私钥签名,公钥验签。
加密:防信息泄露,公钥加密,私钥解密。
先签名后加密可以防止被替换签名,如果签名被作为身份认证的凭据,要先签名再加密。
先加密和签名可以减少接收方的资源开销,因为解密是比签名更耗时的。
发送方计算摘要,使用私钥对摘要进行加密。
接收方使用公钥对加密的值进行解密,再计算摘要,验证是否签名相同。
密钥管理
Root key : 根密钥 相当于KEK
Working key : 随机生成,使用root key加密为密文存放在配置中,相当于DEK
// 随机生成working key (也叫kek)
// 生成root key(也叫master key或者domain key) 对working key加密
// 如果是对数据加密,需要随机生成工作密钥(也叫dek)再用工作密钥对敏感数据进行加密 初始向量是随机的,所以同样的密文加密的结果也是不一样的
// 如果是对其他key进行加密,就直接加密就行了
// 最后把加密的初始向量与密文拼接
byte[] cipherTextArr = Hex.decodeHex(encryptedStr.toCharArray());
byte[] keyArr = Hex.decodeHex(workKey.toCharArray());
SecretKeySpec secretKeySpec = new SecretKeySpec(keyArr, "AES");
// 初始化向量
byte[] iv = new byte[16];
for (int i = 0; i < 16; i++) {
iv[i] = encryptedStr[i];
}
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
String plainStr = StringUtils.newStringUtf8(cipher.doFinal(encryptedStr, 16, encryptedStr.length - 16));
SecretKeySpec secretKeySpec = new SecretKeySpec(workKey, "AES");
// 生成16位随机初始向量
byte[] iv = new byte[16];
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// 加密
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] encryptedText = cipher.doFinal(plainText);
// 拼装初始向量+密文
byte[] resultArr = new byte[iv.length + encryptedText.length];
System.arraycopy(iv, 0, resultArr, 0, iv.length);
System.arraycopy(encryptedText, 0, resultArr, iv.length, encryptedText.length);
String encryptedStr = Hex.encodeHexString(resultArr);