在對稱加密算法中,數據發送方將明文(原始數據)和加密密鑰一塊兒通過特殊加密算法處理後,使其變成複雜的加密密文發送出去。接受方收到密文後,若想解讀原文,則須要使用加密用過的密文及相同算法的逆算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密算法中,使用的密鑰只有一個,雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰。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); } }
參考文章: