1. 常见加密算法
Java常用的登录加密算法有MD5加密算法、SHA加密算法、BCrypt加密算法、RSA非对称加密算法等。
其中,MD5和SHA算法是单向散列函数,不能还原明文,常用于对用户密码进行加密存储;
BCrypt算法则是一种基于哈希函数的密码加密算法,可以防止彩虹表攻击,常用于对密码进行加密存储和验证;
RSA算法是一种非对称加密算法,它的安全性基于大数分解的困难性,即将一个大质数分解成两个质数的乘积。RSA算法通过生成一对公钥和私钥来实现加密和解密操作,其中公钥可以公开传输,私钥只能由私有持有者使用。RSA算法广泛用于电子商务、数字签名、SSL/TLS协议等领域中的安全通信。
2. MD5 加密算法
1)MD5加密方法工具类
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Map;
public class CrowdFundingUtils {
/**
* 判断字符串是否有效
* @param source 待验证字符串
* @return true表示有效,false表示无效
*/
public static boolean stringEffective(String source) {
return source != null && source.length() > 0;
}
/**
* MD5加密工具方法
* @param source 明文
* @return 密文
*/
public static String md5(String source) {
// 判断传入的明文字符串是否有效
if(!stringEffective(source)) {
// 如果检测到明文字符串无效,抛出异常通知方法的调用者
throw new RuntimeException("传入明文字符串无效!");
}
// 声明StringBuilder待用
StringBuilder builder = new StringBuilder();
// 准备字符数组
char[] characters = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
// 指定加密算法
String algorithm = "MD5";
try {
// 执行加密操作的核心对象
MessageDigest digest = MessageDigest.getInstance(algorithm);
// 将要加密的明文转换成字节数组形式
byte[] inputBytes = source.getBytes();
// 执行加密
byte[] outputBytes = digest.digest(inputBytes);
// 遍历outputBytes
for (int i = 0; i < outputBytes.length; i++) {
// 获取当前字节数值
byte b = outputBytes[i];
// 获取低四位值
int lowValue = b & 15;
// 右移四位和15做与运算得到高四位值
int highValue = (b >> 4) & 15;
// 以高四位、低四位的值为下标从字符数组中获取对应字符
char highCharacter = characters[highValue];
char lowCharacter = characters[lowValue];
// 拼接
builder.append(highCharacter).append(lowCharacter);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return builder.toString();
}
}
2)简单测试
@Test
public void testMD5() {
String sou = "123";
String target = CrowdFundingUtils.md5(sou);
System.out.println(target); //202CB962AC59075B964B07152D234B70
}
3. RSA非对称加密算法
3.1 Java 使用 RSA 算法进行登录验证
Java 登录非对称加密通常使用RSA算法,实现步骤如下:
① 生成公钥和私钥:
使用Java中的KeyPairGenerator类生成公钥和私钥,示例代码如下:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024); // 初始化密钥长度为1024
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
② 使用公钥加密用户密码
将用户输入的密码使用公钥进行加密,示例代码如下:
String password = "123456";
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedPassword = cipher.doFinal(password.getBytes());
③ 使用私钥解密用户密码
在服务器端使用私钥对加密后的密码进行解密,示例代码如下:
byte[] decryptedPassword = null;
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
decryptedPassword = cipher.doFinal(encryptedPassword);
String password = new String(decryptedPassword);
⑤ 比较解密后的密码和数据库中的密码是否一致,如果一致则登录成功。 需要注意的是,RSA算法每次加密的密文都不一样,因此在比较密码时需要将数据库中的密码使用相同的方式加密后再进行比较。
3.2 Java 登录用 RSA 加 AES 做登录加密
Java登录用RSA加AES做登录加密可以提高安全性。前后端的实现步骤如下:
1)后端实现
① 生成 RSA 公钥和私钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
② 将公钥发送给前端
String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
return new Result().success(publicKeyStr);
2)前端实现
③ 前端使用 RSA 公钥加密 AES 密钥
// 生成AES密钥
const aesKey = CryptoJS.enc.Hex.parse(CryptoJS.lib.WordArray.random(16).toString());
// 使用RSA公钥加密AES密钥
const encryptAesKey = publicKey.encrypt(aesKey.toString(), "RSA-OAEP");
④ 使用 AES 加密用户密码,将加密后的 AES 密钥和密码传递给后端进行验证。
const encryptedPassword = CryptoJS.AES.encrypt(password, aesKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString();
3)后端实现
⑤ 在后端接收到加密后的密码后,使用 RSA 私钥解密 AES 密钥,然后使用 AES 解密密码进行验证。
需要注意的是,由于RSA算法每次加密的密文都不一样,因此在比较密码时需要将数据库中的密码使用相同的方式加密后再进行比较。
// 使用RSA私钥解密AES密钥
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = cipher.doFinal(Base64.getDecoder().decode(encryptAesKey));
SecretKeySpec aesKeySpec = new SecretKeySpec(aesKeyBytes, "AES");
// 使用AES解密密码
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.DECRYPT_MODE, aesKeySpec);
byte[] decryptedPasswordBytes = aesCipher.doFinal(Base64.getDecoder().decode(encryptedPassword));
String decryptedPassword = new String(decryptedPasswordBytes);