加密与解密
文章目录
- 加密与解密
- 一、概述
- 1、对称加密
- 2、非对称加密
- 3、哈希加密
- 4、盐值
- 5、小结
- 二、AES 对称加密
- 三、RSA 非对称加密
- 1、加密与解密
- 2、签名与验签
- 四、MD5 哈希加密
- 五、SHA 哈希加密
加密与解密
一、概述
1、对称加密
对称加密,就是加密和解密使用同一个密钥。(密钥的保密性至关重要)
- 常见的有 AES、DES、3DES、Blowfish 等
2、非对称加密
非对称加密,使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。(公钥可以公开,而私钥必须保密)
- 常见的有 RSA、DSA、ECC 等。
3、哈希加密
哈希加密,用于将 任意长度的数据 转换为 固定长度的输出,通常称为哈希值或摘要。
- 常见的有 MD5、SHA-1、SHA-256。
哈希加密的特点:
- 不可逆:无法从哈希值反推出原始数据。
- 固定长度:无论输入数据的大小,哈希值的长度是固定的。
- 唯一性:相同的输入总是产生相同的哈希值。
理想情况下,不同的输入数据应产生不同的哈希值(尽管 MD5 和 SHA-1 存在碰撞漏洞)。
4、盐值
盐值(Salt)是一个随机数据,和原数据结合后进行哈希,用于增强密码存储安全性。
- 主要目的是防止彩虹表攻击(通过预计算的哈希表来快速破解密码)
- 加盐后,即使两个用户的密码相同,最终的哈希结果也会不同。
假设用户的密码是 123456
,生成的盐值是 random_salt
,哈希过程如下:
hashed_password = hash(random_salt + 123456)
存储时,数据库中会保存 random_salt
和 hashed_password
。
5、小结
- 对称加密:同一个密钥,加密和解密速度快,适合快速加密大量数据,但密钥管理难度高。
- 非对称加密:一对密钥(公钥和私钥),安全性更高,但速度相对较慢。
- 哈希加密:不可逆,无法解密出原始数据,一般用于数据的校验,例如:密码。
这三种加密方式各有优缺点,通常在实际应用中会结合使用,以实现更高的安全性。
例如,在 HTTPS 中,使用 非对称加密 安全地交换 对称加密 的密钥,然后使用 对称加密 进行数据传输。
二、AES 对称加密
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;public class AESExample {public static void main(String[] args) throws Exception {String plainText = "Hello, World!";SecretKey secretKey = generateAESKey();String encryptedText = encrypt(plainText, secretKey);String decryptedText = decrypt(encryptedText, secretKey);System.out.println("Original: " + plainText);System.out.println("Encrypted: " + encryptedText);System.out.println("Decrypted: " + decryptedText);}public static SecretKey generateAESKey() throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128); // or 256return keyGenerator.generateKey();}public static String encrypt(String plainText, SecretKey key) throws Exception {Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());return Base64.getEncoder().encodeToString(encryptedBytes);}public static String decrypt(String encryptedText, SecretKey key) throws Exception {Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.DECRYPT_MODE, key);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));return new String(decryptedBytes);}
}
三、RSA 非对称加密
1、加密与解密
- A 生成公钥和私钥,私钥自己保留,公钥任何人可以获取。
- B 拿到公钥,将数据通过公钥加密,然后将密文传给 A。
- A 收到密文,通过私钥解密,得到明文。
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import javax.crypto.Cipher;public class RSAExample {public static void main(String[] args) throws Exception {String plainText = "Hello, RSA!";KeyPair keyPair = generateRSAKeyPair();String encryptedText = encrypt(plainText, keyPair.getPublic());String decryptedText = decrypt(encryptedText, keyPair.getPrivate());System.out.println("Original: " + plainText);System.out.println("Encrypted: " + encryptedText);System.out.println("Decrypted: " + decryptedText);}public static KeyPair generateRSAKeyPair() throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);return keyGen.generateKeyPair();}public static String encrypt(String plainText, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());return Base64.getEncoder().encodeToString(encryptedBytes);}public static String decrypt(String encryptedText, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));return new String(decryptedBytes);}
}
2、签名与验签
验签是指通过私钥对消息进行签名,使得消息无法篡改和伪造。
- A 生成公钥和私钥,私钥自己保留,公钥任何人可以获取。
- A 使用
私钥
对消息加签,并将加签后的消息传给 B。 - B 通过
公钥
验签,如果返回是true,则说明消息是A发过来的且未被篡改。
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Base64;public class RSASignatureExample {public static void main(String[] args) throws Exception {String message = "这是需要签名的消息";KeyPair keyPair = generateRSAKeyPair();// 数字签名String signature = signMessage(keyPair.getPrivate(), message);System.out.println("签名: " + signature);// 验证签名boolean isValid = verifySignature(keyPair.getPublic(), message, signature);System.out.println("签名有效性: " + isValid);}public static KeyPair generateRSAKeyPair() throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);return keyGen.generateKeyPair();}// 签名方法public static String signMessage(PrivateKey privateKey, String message) throws Exception {Signature rsa = Signature.getInstance("SHA256withRSA");rsa.initSign(privateKey);rsa.update(message.getBytes());byte[] signature = rsa.sign();return Base64.getEncoder().encodeToString(signature);}// 验证签名方法public static boolean verifySignature(PublicKey publicKey, String message, String signature) throws Exception {Signature rsa = Signature.getInstance("SHA256withRSA");rsa.initVerify(publicKey);rsa.update(message.getBytes());byte[] signatureBytes = Base64.getDecoder().decode(signature);return rsa.verify(signatureBytes);}}
四、MD5 哈希加密
常用于将密码加密后保存到数据库。用户输入密码后先 MD5 计算,再和数据库里的 MD5密码 比较。
import java.security.MessageDigest;public class MD5Example {public static void main(String[] args) throws Exception {String text = "Hello, MD5!";String hash = md5(text);System.out.println("MD5 Hash: " + hash);}public static String md5(String input) throws Exception {MessageDigest md = MessageDigest.getInstance("MD5");byte[] digest = md.digest(input.getBytes());return byteToHex(digest);}private static String byteToHex(byte[] digest) {StringBuilder hexString = new StringBuilder();for (byte b : digest) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexString.append('0');}hexString.append(hex);}return hexString.toString();}}
五、SHA 哈希加密
和 MD5 类似的信息摘要算法,但是它比 MD5 更加安全。
import java.security.MessageDigest;public class SHAExample {public static void main(String[] args) throws Exception {String text = "Hello, SHA-256!";String hash = sha256(text);System.out.println("SHA-256 Hash: " + hash);}// sha-1加密(160位,20字节,40个十六进制字符)public static String sha1(String input) throws Exception {MessageDigest md = MessageDigest.getInstance("SHA-1");byte[] digest = md.digest(input.getBytes());return byteToHex(digest);}// sha-256加密(256位,32字节,64个十六进制字符)public static String sha256(String input) throws Exception {MessageDigest md = MessageDigest.getInstance("SHA-256");byte[] digest = md.digest(input.getBytes());return byteToHex(digest);}// sha-512加密(512位,64字节,128个十六进制字符)public static String sha512(String input) throws Exception {MessageDigest md = MessageDigest.getInstance("SHA-512");byte[] digest = md.digest(input.getBytes());return byteToHex(digest);}private static String byteToHex(byte[] digest) {StringBuilder hexString = new StringBuilder();for (byte b : digest) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexString.append('0');}hexString.append(hex);}return hexString.toString();}}
由于安全性问题,MD5 和 SHA-1 不再被推荐用于安全相关的用途。SHA-256 和 SHA-512 是目前较为安全的选择。
对于简单的完整性检查,可以考虑使用 MD5,但需谨慎评估其风险。