一、介紹
1、概念
非對稱加密,又稱現代加密算法,非對稱加密是計算機通信安全的基石,保證了加密數據不會被破解
。加密和解密使用的是兩個不同
的密鑰,這種算法叫作非對稱加密算法
。
2、示例
首先生成密鑰對, 公鑰為(5,14),私鑰為(11,14);
現在A希望將原文2發送給B:
A使用公鑰加密數據. 2的5次方mod 14 = 4 , 將密文4發送給B;
B使用私鑰解密數據. 4的11次方mod14 = 2, 得到原文2。
3、和對稱加密的比較
與對稱加密算法不同,非對稱加密算法需要兩個密鑰:公開密鑰(publickey)
?和私有密(privatekey)
4、特點
(1)加密和解密使用不同的密鑰,且公開密鑰和私有密鑰是一對。
(2)如果用公開密鑰
對數據進行加密
,只能用對應的私有密鑰
才能解密;
? ? ? ? 如果用私有密鑰
對數據進行加密
,只能用對應的公開密鑰
才能解密
。
(3)處理數據的速度較慢, 因為安全級別高
5、常用算法
- RSA
- ECC
二、?RSA
1、使用方法
首先需要生成公鑰和密鑰對;之后使用一個加密另外一個解密。
import org.apache.commons.io.FileUtils;import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;public class RsaUtil {public static void main(String[] args) throws Exception {String input = "測試wtyy666";// 加密算法String algorithm = "RSA";String priPath = "a.pri";String pubPath = "a.pub";//1、生成密鑰對并保存在本地文件中generateKeyToFile(algorithm, pubPath, priPath);//2、加密String s = encryptRSA(algorithm, getPrivateKey(priPath,algorithm), input);System.out.println("加密后:"+s);// 3、解密String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);System.out.println("解密后:"+s1);}//讀取私鑰public static PrivateKey getPrivateKey(String priPath,String algorithm) throws Exception{// 將文件內容轉為字符串String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());// 獲取密鑰工廠KeyFactory keyFactory = KeyFactory.getInstance(algorithm);// 構建密鑰規范 進行Base64解碼PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));// 生成私鑰return keyFactory.generatePrivate(spec);}//讀取公鑰public static PublicKey getPublicKey(String pulickPath,String algorithm) throws Exception{// 將文件內容轉為字符串String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());// 獲取密鑰工廠KeyFactory keyFactory = KeyFactory.getInstance(algorithm);// 構建密鑰規范 進行Base64解碼X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));// 生成公鑰return keyFactory.generatePublic(spec);}/*** 生成密鑰對并保存在本地文件中** @param algorithm : 算法* @param pubPath : 公鑰保存路徑* @param priPath : 私鑰保存路徑* @throws Exception*/private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {// 獲取密鑰對生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);// 獲取密鑰對KeyPair keyPair = keyPairGenerator.generateKeyPair();// 獲取公鑰PublicKey publicKey = keyPair.getPublic();// 獲取私鑰PrivateKey privateKey = keyPair.getPrivate();// 獲取byte數組byte[] publicKeyEncoded = publicKey.getEncoded();byte[] privateKeyEncoded = privateKey.getEncoded();// 進行Base64編碼String publicKeyString = Base64.getEncoder().encodeToString(publicKeyEncoded);String privateKeyString = Base64.getEncoder().encodeToString(privateKeyEncoded);// 保存文件FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));System.out.println("生成的共鑰: " + publicKeyString);System.out.println("生成的私鑰: " + privateKeyString);}/*** 解密數據** @param algorithm : 算法* @param encrypted : 密文* @param key : 密鑰* @return : 原文* @throws Exception*/public static String decryptRSA(String algorithm,Key key,String encrypted) throws Exception{// 創建加密對象// 參數表示加密算法Cipher cipher = Cipher.getInstance(algorithm);// 私鑰進行解密cipher.init(Cipher.DECRYPT_MODE,key);// 由于密文進行了Base64編碼, 在這里需要進行解碼byte[] decode = Base64.getDecoder().decode(encrypted);// 對密文進行解密,不需要使用base64,因為原文不會亂碼byte[] bytes1 = cipher.doFinal(decode);//System.out.println(new String(bytes1));return new String(bytes1);}/*** 使用密鑰加密數據** @param algorithm : 算法* @param input : 原文* @param key : 密鑰* @return : 密文* @throws Exception*/public static String encryptRSA(String algorithm,Key key,String input) throws Exception{// 創建加密對象// 參數表示加密算法Cipher cipher = Cipher.getInstance(algorithm);// 初始化加密// 第一個參數:加密的模式// 第二個參數:使用私鑰進行加密cipher.init(Cipher.ENCRYPT_MODE,key);// 私鑰加密byte[] bytes = cipher.doFinal(input.getBytes());// 對密文進行Base64編碼System.out.println(Base64.getEncoder().encodeToString(bytes));return Base64.getEncoder().encodeToString(bytes);}
}
生成的共鑰: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4QYyI6aTqFZrQrcprgbCE2g60eLKVYBguiPLt7zPT2rCw+13s5c7G7WWjgiJ7UN2rQ+r+aVEKSe8eou/7lb8kEMrbJYJGg8y9KGyQ62ry1/0Rvw5DtHCoSpcu8czTVkB2mhYSCG+BTXaMmsVNICEXR7g4CZ/ILfLCugjNangkQ8iIEFYaLE1ssbcZmXCyA3kTVMqdplHYi1wgd9Vk8tQP77K5joZzb23F5bWZW+8yS+i1gKq1sxipzb8ZG/UMCP6upjqAHh6bgTJa+ORZmT6cXtjW235XK/Jq5NelN/9RGzsHbPSFgvFIayEAgA8WyyR/JCAIqUtj6hjwNG7tOAEfQIDAQAB
生成的私鑰: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhBjIjppOoVmtCtymuBsITaDrR4spVgGC6I8u3vM9PasLD7XezlzsbtZaOCIntQ3atD6v5pUQpJ7x6i7/uVvyQQytslgkaDzL0obJDravLX/RG/DkO0cKhKly7xzNNWQHaaFhIIb4FNdoyaxU0gIRdHuDgJn8gt8sK6CM1qeCRDyIgQVhosTWyxtxmZcLIDeRNUyp2mUdiLXCB31WTy1A/vsrmOhnNvbcXltZlb7zJL6LWAqrWzGKnNvxkb9QwI/q6mOoAeHpuBMlr45FmZPpxe2Nbbflcr8mrk16U3/1EbOwds9IWC8UhrIQCADxbLJH8kIAipS2PqGPA0bu04AR9AgMBAAECggEACMs038WzPCrXrcj/1nvKIKXwbigttT3G+Hf7MYJoG8wv4A7oK/U2+hWmAvoiW5B3mSNT4Gov75YpolMYnHmeDK828kPle8xcttQ7wuIkMG3e8qsJrihxYDdy6XrLLmj1AxUrdyFyFAKvV8DKjPHWy9cv2nnrBjJv0qnLGy+47kI7J4yR137NGz4TvnfS3IxYi1LGwvI7fi38cNVF11FRCQLlkdUYe0RWQ0RFlAu9G6/87cwLB2YnWiZ6RH+zSGcMK2/M7TPHeBtxEkJnMUjpfTVeOqsf6/XRpELwHtRDr2qfEq4LGCPvX1rQFJ11NpJKnh5MbdAOGwevQXWawrYlawKBgQDubHucFUcIyFJciu7fo3NvsbrXBWbaU6bdXZPPhSsxBfOvCIRmS0I+AqBYwjZVB+gejB3p21LFFjz9PO6ewz5bXTJrB2J8CEJfA8zj/7A2XKCl9po4X6ngDOy5ls0PwkELvnILpgdpW5ZfjEpviOHsXJk+QPHCrtINn1sHcUDeXwKBgQDxnNZidrnGgJxpDJvJtmimci5sbnnfg8Vs/YzJTyPh+9m1OZ23gg4h1mfFBi4wuSHofjD7nLG/TYFeF4BbsY032nBSz30EaSYO4IrO0UxgNGQfFnaCS0hQVr0Rr4na+KpYFr26pIJL+FGCR6iYiYTVhGVDTBLK2+WUEOve/ahSowKBgQCoIVn9lEeWWuUxm0ud6z5xKmzuSkHgfhLykZW1RlxR4reX27K6DCI3ZlS6oqH7zmqSeA50JhS1JNx3W+uNi3NCrHLsZLW/b3eWVzC6K0mQ3DrxLfhM/rDlbVfV/BC5JywFYxQ7QKaDVnGxCVZIVseyjQ4Hh3a06eD4eEKR+fxbkwKBgQDgdWflSY8FDm5AWWpRVpiaKPFf4rJuJ6i9vD+StWcMhkCWz9Ppq3UdkmYM79TxhswthS5UUhn/My3AD+07QhODk/dNt1zZQCYPJCNQR7jAl2t8Rg4KtY2UtUAosf9L4j++XkIcpsA1e5edhJzoOLmi8sBwaLf8pZT+nUnDe7toKQKBgQCxu1yYVjCz1i+sJ3inUOaGZjZ/cOLCxmGzLxpKBMPa6VHVbJZtt+n9hdU+Jxi+U1QIdXLtXdvNrkW9LrXEBvuk7uU6VBZSHmaJ/7iGl52bUuQHQnUW8ZKs30obXq7nW5K5VBcHcJMroms+e7xHS2aNdBVXNtQDCUXL3TAZnrTmVg==
KmeXpGFH77J3wowoZ7g68MDJ6X5GnGocHBhGebYeo6aZUFz3CUK/itbuWPv/mdsYqhLeRASYSUA2qrDxglrH8kxKM8WUTkstGjp1N+flX+bjItaE8sAXTF2k/0Mq3bKqpGJ7XB694CEhiS4YRLZQGgloat7aE+P32ayKbCIM58wgZa2mEFlYCbHmohX7tofsEB6DUf7LBKnYGd/MXGRwxgYPqiR3r/V38aVK4cpMRoJPqxXWsq5i2ZvFkwWXduxNXmrXFwF/7hFxqlMOpLPADFikG9cox7FicLJ3FiGZNxOrdMO/xNyGE9V3PBBwStoLqTjIrvEDPij91cEEbNWh4w==
加密后:KmeXpGFH77J3wowoZ7g68MDJ6X5GnGocHBhGebYeo6aZUFz3CUK/itbuWPv/mdsYqhLeRASYSUA2qrDxglrH8kxKM8WUTkstGjp1N+flX+bjItaE8sAXTF2k/0Mq3bKqpGJ7XB694CEhiS4YRLZQGgloat7aE+P32ayKbCIM58wgZa2mEFlYCbHmohX7tofsEB6DUf7LBKnYGd/MXGRwxgYPqiR3r/V38aVK4cpMRoJPqxXWsq5i2ZvFkwWXduxNXmrXFwF/7hFxqlMOpLPADFikG9cox7FicLJ3FiGZNxOrdMO/xNyGE9V3PBBwStoLqTjIrvEDPij91cEEbNWh4w==
解密后:測試wtyy666
2、測試
(1)私鑰加密需要公鑰解密
① 先使用私鑰加密并且解密:
//2、加密String s = encryptRSA(algorithm, getPrivateKey(priPath,algorithm), input);System.out.println("加密后:"+s);// 3、解密String s1 = decryptRSA(algorithm, getPrivateKey(priPath,algorithm), s);System.out.println("解密后:"+s1);
運行報錯 ,因為私鑰加密,只能公鑰解密。
② 改為公鑰解密則正常運行:
String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);
(2)公鑰加密需要私鑰解密
?① 先使用公鑰加密并且解密
//2、加密String s = encryptRSA(algorithm, getPublicKey(pubPath,algorithm), input);System.out.println("加密后:"+s);// 3、解密String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);System.out.println("解密后:"+s1);
同樣運行報錯
② 改為私鑰解密則正常運行:
String s1 = decryptRSA(algorithm, getPrivateKey(priPath,algorithm), s);
?