在对称加密算法中,数据发送方将明文(原始数据)和加密密钥一块儿通过特殊加密算法处理后,使其变成复杂的加密密文发送出去。接受方收到密文后,若想解读原文,则须要使用加密用过的密文及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。java
常见的对称加密算法:redis
特色:算法
加密模式:apache
填充模式:当须要按块处理的数据,数据长度不符合时,按照必定的方法填充满块的长度的规则数组
Demo代码:安全
package encryptAndDecrypt; import com.sun.org.apache.xml.internal.security.utils.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * @className: AesDesDemo * @description: 使用DES加密解密,加密和解密都是使用同一个密钥 * @author: charon * @create: 2021-02-25 08:27 */ public class AesDesDemo { public static void main(String[] args) throws Exception { // 须要加密的内容,若是是不使用填充模式,那么密文的字节数必须是8的整数倍 String input = "charon周1234567"; // 密钥,DES加密的密钥必须是8位,若是是AES加密的密钥必须是16位 String key = "12345678"; // 加密算法,DES表示加密类型,CBC表示加密模式,NoPadding表示填充模式。 // 默认状况下是使用 DES/ECB/PKCS5padding String algorithm = "DES/CBC/NoPadding"; String algorithmType = "DES"; //偏移量,是使用cbc的加密模式,在使用iv向量进行加密的时候,IV也必须是8位 String offset = "12345678"; // 加密 String encryptDes = encryptDES(input, key, algorithm, algorithmType,offset); System.out.println("密文: " + encryptDes); // 解密 String decryptDES = decryptDES(encryptDes, key, algorithm, algorithmType,offset); System.out.println("解密: "+ decryptDES); } /** * 解密 * @param encryptDes 密文 * @param key 密钥 * @param algorithm 解密算法 * @param algorithmType 解密类型 * @param offset 偏移量 * @return */ private static String decryptDES(String encryptDes, String key, String algorithm, String algorithmType,String offset) throws Exception { // 获取解密对象 Cipher cipher = Cipher.getInstance(algorithm); // 建立加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithmType); // 建立iv向量 IvParameterSpec ivParameterSpec = new IvParameterSpec(offset.getBytes()); // 初始化解密规则 cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec); // 加密 byte[] bytes = cipher.doFinal(Base64.decode(encryptDes)); return new String(bytes); } /** * 加密 * @param input 加密内容 * @param key 密钥 * @param algorithm 加密算法 * @param algorithmType 加密类型 * @param offset 偏移量 * @return 密文 */ private static String encryptDES(String input, String key, String algorithm, String algorithmType,String offset) throws Exception { // 获取加密对象 Cipher cipher = Cipher.getInstance(algorithm); // 建立加密规则 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithmType); // 建立iv变量,iv向量,是使用cbc的加密模式 // 在使用iv向量进行加密的时候,IV也必须是8位 IvParameterSpec ivParameterSpec = new IvParameterSpec(offset.getBytes()); // 初始化加密 cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec); // 加密 byte[] bytes = cipher.doFinal(input.getBytes()); // 返回加密后的数据 return Base64.encode(bytes); } }
与对称加密算法不一样,非对称加密算法须要两个密钥:公钥和私钥。公钥与私钥是一对,若是使用公钥对数据进行加密,那么只能有对应的私钥才能解密;若是使用私钥进行加密,那么只能用对应的公钥才能解密。由于加密和解密是使用的两个不一样的密钥。session
常见的非对称加密算法:electron
特色:编码
demo代码:加密
package encryptAndDecrypt; import com.sun.org.apache.xml.internal.security.utils.Base64; import org.apache.commons.io.FileUtils; import javax.crypto.Cipher; import java.io.File; import java.nio.charset.Charset; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** * @className: RsaDemo * @description: 非对称加密之RSA * @author: charon * @create: 2021-02-25 11:05 */ public class RsaDemo { public static void main(String[] args) throws Exception { String algorithm = "RSA"; // 生成密钥对并保存在本地文件中,这样就能够不用每次都从新申请了。 // 也有系统为了更安全,每次都会新生成密钥,而后将公钥返回给客户端,私钥存入redis中,解密的时候从根据session从redis中取对应的私钥 generateKeyToFile(algorithm, "pub.txt", "pri.txt"); // 获取公钥 PublicKey publicKey = getPublicKey("pub.txt", "RSA"); // 获取私钥 PrivateKey privateKey = getPrivateKey("pri.txt", "RSA"); // 原文 String input = "charon周"; // 加密 String encryptRSA = encryptRSA(input,algorithm,publicKey); System.out.println("密文:"+ encryptRSA); // 解密 String decryptRSA = decryptRSA(encryptRSA,algorithm,privateKey); System.out.println("原文:"+ decryptRSA); } /** * 解密 * @param encryptRSA 密文 * @param algorithm 算法 * @param privateKey 私钥 * @return 原文 */ private static String decryptRSA(String encryptRSA, String algorithm, PrivateKey privateKey) throws Exception{ Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE,privateKey); byte[] bytes = cipher.doFinal(Base64.decode(encryptRSA)); return new String(bytes); } /** * 加密 * @param input 原文 * @param algorithm 加密算法 * @param publicKey 公钥 * @return 密文 */ private static String encryptRSA(String input, String algorithm, PublicKey publicKey) throws Exception{ Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE,publicKey); byte[] bytes = cipher.doFinal(input.getBytes()); return Base64.encode(bytes); } /** * 获取私钥 * @param privateKeyPath 私钥文件路径 * @param algorithm 算法 * @return 私钥 */ public static PrivateKey getPrivateKey(String privateKeyPath, String algorithm) throws Exception { // 读取文件内容 String strPrivateKey = FileUtils.readFileToString(new File(privateKeyPath), Charset.defaultCharset()); // 建立key工厂 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); // 建立私钥规则 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(strPrivateKey)); return keyFactory.generatePrivate(pkcs8EncodedKeySpec); } /** * 获取公钥 * @param publicKeyPath 公钥文件路径 * @param algorithm 算法 * @return 公钥 */ public static PublicKey getPublicKey(String publicKeyPath, String algorithm) throws Exception{ // 读取文件内容 String strPublicKey = FileUtils.readFileToString(new File(publicKeyPath), Charset.defaultCharset()); // 建立key工厂 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); // 建立公钥规则 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(strPublicKey)); return keyFactory.generatePublic(x509EncodedKeySpec); } /** * 生成密钥对,并放入本地文件 * @param algorithm * @param publicKeyPath * @param privateKeyPath */ private static void generateKeyToFile(String algorithm, String publicKeyPath, String privateKeyPath) throws Exception{ // 生成实例 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // 生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成私钥 PrivateKey privateKey = keyPair.getPrivate(); // 获取私钥字节数组 byte[] privateKeyEncoded = privateKey.getEncoded(); // 生成公钥 PublicKey publicKey = keyPair.getPublic(); // 获取公钥的字节数组 byte[] publicKeyEncoded = publicKey.getEncoded(); // base64编码 String strPrivateKeyEncoded = Base64.encode(privateKeyEncoded); String strPublicKeyEncoded = Base64.encode(publicKeyEncoded); // 存到文件中 FileUtils.write(new File(privateKeyPath),strPrivateKeyEncoded, Charset.forName("UTF-8")); FileUtils.write(new File(publicKeyPath),strPublicKeyEncoded, Charset.forName("UTF-8")); } }
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人没法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证实。它是一种相似写在纸上的普通的物理签名,可是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名一般定义两种互补的运算,一个用于签名,另外一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。
demo代码:
package encryptAndDecrypt; import com.sun.org.apache.xml.internal.security.utils.Base64; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; /** * @className: SignatureDemo * @description: 数字签名 * @author: charon * @create: 2021-02-25 15:40 */ public class SignatureDemo { public static void main(String[] args) throws Exception{ // 这里直接使用以前的公钥和私钥 // 获取公钥 PublicKey publicKey = RsaDemo.getPublicKey("pub.txt", "RSA"); // 获取私钥 PrivateKey privateKey = RsaDemo.getPrivateKey("pri.txt", "RSA"); String input = "charon周"; // 获取签名 String signature = getSignature(input, "Sha256withrsa", privateKey); System.out.println("签名:" + signature); // 校验签名 boolean verifySignature = verifySignature(input, "Sha256withrsa", publicKey, signature); System.out.println("结果: "+ verifySignature); } /** * 校验签名 * @param input 原文 * @param algorithm 算法 * @param publicKey 公钥 * @param signatureData 签名 * @return */ private static boolean verifySignature(String input, String algorithm, PublicKey publicKey, String signatureData) throws Exception{ Signature signature = Signature.getInstance(algorithm); signature.initVerify(publicKey); signature.update(input.getBytes()); // 校验数据 boolean verify = signature.verify(Base64.decode(signatureData)); return verify; } /** * 签名 * @param input 原文 * @param algorithm 算法 * @param privateKey 私钥 * @return 签名 */ private static String getSignature(String input, String algorithm, PrivateKey privateKey) throws Exception{ // 获取签名对象 Signature signature = Signature.getInstance(algorithm); // 初始化签名 signature.initSign(privateKey); signature.update(input.getBytes()); // 签名 byte[] bytes = signature.sign(); return Base64.encode(bytes); } }
参考文章: