[轉(zhuǎn)帖]數(shù)據(jù)加密之加密算法
當(dāng)前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
:數(shù)據(jù)加密之加密算法 encrypt-decrypt1 密碼學(xué)基本概念1.1 古典密碼學(xué)1.2 近代密碼學(xué)1.3 現(xiàn)代密碼學(xué)2 凱撒加密2.1 凱撒加密解密的實現(xiàn)public class KaiSaUtil { // 加密 public static String encryptKaiser(String original, Integer key) { // 1、將輸入的字符串轉(zhuǎn)換成字符數(shù)組 char[] chars = original.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) { // 2、獲取字符的ascii編碼 int asciiCode = aChar; // 3、偏移數(shù)據(jù) asciiCode += key; // 4、將偏移后的數(shù)據(jù)轉(zhuǎn)為字符 char result = (char) asciiCode; // 5、拼接數(shù)據(jù) sb.append(result); } return sb.toString(); } // 解密 public static String decryptKaiser(String encryptedData, int key) { // 1、將密文轉(zhuǎn)換成字符數(shù)組 char[] chars = encryptedData.toCharArray(); StringBuilder sb = new StringBuilder(); for (char aChar : chars) { // 2、獲取字符的ascii編碼 int asciiCode = aChar; // 3、偏移數(shù)據(jù) asciiCode -= key; // 4、將偏移后的數(shù)據(jù)轉(zhuǎn)為字符 char result = (char) asciiCode; // 5、拼接數(shù)據(jù) sb.append(result); } return sb.toString(); }}123456789101112131415161718192021222324252627282930313233343536 public class KaiSaDemo { public static void main(String[] args) { String input = "welcome"; Integer key = 3; System.out.println("加密前:" + input); String encryptKaiser = KaiSaUtil.encryptKaiser(input, key); System.out.println("加密后:" + encryptKaiser); String decryptKaiser = KaiSaUtil.decryptKaiser(encryptKaiser, key); System.out.println("解密后:" + decryptKaiser); }}測試結(jié)果: 加密前:welcome 加密后:zhofrph 解密后:welcome123456789101112131415 2.2 使用頻度分析法破解凱撒加密public static void main(String[] args) throws Exception { //測試1,統(tǒng)計字符個數(shù) //printCharCount("article.txt"); //加密文件 int key = 3; encryptFile("article.txt", "article_en.txt", key); //讀取加密后的文件 // String artile = Util.file2String("article_en.txt"); //解密(會生成多個備選文件) // decryptCaesarCode(artile, "article_de.txt"); }12345678910111213 public static void main(String[] args) throws Exception { //測試1,統(tǒng)計字符個數(shù) printCharCount("article_en.txt"); //加密文件 int key = 3; //encryptFile("article.txt", "article_en.txt", key); //讀取加密后的文件 // String artile = Util.file2String("article_en.txt"); //解密(會生成多個備選文件) // decryptCaesarCode(artile, "article_de.txt"); }12345678910111213 public class FrequencyUtil { public static void print(byte[] bytes) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { sb.append(bytes[i]).append(" "); } System.out.println(sb); } public static String file2String(String path) throws IOException { FileReader reader = new FileReader(new File(path)); char[] buffer = new char[1024]; int len = -1; StringBuffer sb = new StringBuffer(); while ((len = reader.read(buffer)) != -1) { sb.append(buffer, 0, len); } return sb.toString(); } public static void string2File(String data, String path) { FileWriter writer = null; try { writer = new FileWriter(new File(path)); writer.write(data); } catch (Exception e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static String inputStream2String(InputStream in) throws IOException { int len = -1; byte[] buffer = new byte[1024]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((len = in.read(buffer)) != -1) { baos.write(buffer, 0, len); } baos.close(); return baos.toString("UTF-8"); }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 public class FrequencyAnalysis { //英文里出現(xiàn)次數(shù)最多的字符 private static final char MAGIC_CHAR = 'e'; //破解生成的最大文件數(shù) private static final int DE_MAX_FILE = 4; public static void main(String[] args) throws Exception { //測試1,統(tǒng)計字符個數(shù)// printCharCount("D:\\IDEA\\encrypt-decrypt\\src\\article.txt"); //加密文件 int key = 3;// encryptFile("D:\\\\IDEA\\\\encrypt-decrypt\\\\src\\\\article.txt", "D:\\IDEA\\encrypt-decrypt\\src\\article_en.txt", key); //讀取加密后的文件 String artile = FrequencyUtil.file2String("D:\\IDEA\\encrypt-decrypt\\src\\article_en.txt"); //解密(會生成多個備選文件) decryptCaesarCode(artile, "article_de.txt"); } public static void printCharCount(String path) throws IOException { String data = FrequencyUtil.file2String(path); List<Entry<Character, Integer>> mapList = getMaxCountChar(data); for (Entry<Character, Integer> entry : mapList) { //輸出前幾位的統(tǒng)計信息 System.out.println("字符'" + entry.getKey() + "'出現(xiàn)" + entry.getValue() + "次"); } } public static void encryptFile(String srcFile, String destFile, int key) throws IOException { String artile = FrequencyUtil.file2String(srcFile); //加密文件 String encryptData = KaiSaUtil.encryptKaiser(artile, key); //保存加密后的文件 FrequencyUtil.string2File(encryptData, destFile); } /** * 破解凱撒密碼 * * @param input 數(shù)據(jù)源 * @return 返回解密后的數(shù)據(jù) */ public static void decryptCaesarCode(String input, String destPath) { int deCount = 0;//當(dāng)前解密生成的備選文件數(shù) //獲取出現(xiàn)頻率最高的字符信息(出現(xiàn)次數(shù)越多越靠前) List<Entry<Character, Integer>> mapList = getMaxCountChar(input); for (Entry<Character, Integer> entry : mapList) { //限制解密文件備選數(shù) if (deCount >= DE_MAX_FILE) { break; } //輸出前幾位的統(tǒng)計信息 System.out.println("字符'" + entry.getKey() + "'出現(xiàn)" + entry.getValue() + "次"); ++deCount; //出現(xiàn)次數(shù)最高的字符跟MAGIC_CHAR的偏移量即為秘鑰 int key = entry.getKey() - MAGIC_CHAR; System.out.println("猜測key = " + key + ", 解密生成第" + deCount + "個備選文件" + "\n"); String decrypt = KaiSaUtil.decryptKaiser(input, key); String fileName = "de_" + deCount + destPath; FrequencyUtil.string2File(decrypt, fileName); } } //統(tǒng)計String里出現(xiàn)最多的字符 public static List<Entry<Character, Integer>> getMaxCountChar(String data) { Map<Character, Integer> map = new HashMap<Character, Integer>(); char[] array = data.toCharArray(); for (char c : array) { if (!map.containsKey(c)) { map.put(c, 1); } else { Integer count = map.get(c); map.put(c, count + 1); } } //輸出統(tǒng)計信息 for (Entry<Character, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + "出現(xiàn)" + entry.getValue() + "次"); } //獲取獲取最大值 int maxCount = 0; for (Entry<Character, Integer> entry : map.entrySet()) { //不統(tǒng)計空格 if (/*entry.getKey() != ' ' && */entry.getValue() > maxCount) { maxCount = entry.getValue(); } } //map轉(zhuǎn)換成list便于排序 List<Entry<Character, Integer>> mapList = new ArrayList<Map.Entry<Character, Integer>>(map.entrySet()); //根據(jù)字符出現(xiàn)次數(shù)排序 Collections.sort(mapList, new Comparator<Entry<Character, Integer>>() { public int compare(Entry<Character, Integer> o1, Entry<Character, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } }); return mapList; }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 3 常見加密方式3.1 對稱加密3.2 DES加密解密public class DesAesDemo { public static void main(String[] args) throws Exception { // 原文 String input = "hello"; // des加密必須是8位 String key = "12345678"; // 算法 String algorithm = "DES"; // 加密類型 String transformation = "DES"; // Cipher:密碼,獲取加密對象 // transformation:參數(shù)表示使用什么類型加密 Cipher cipher = Cipher.getInstance(transformation); // 指定秘鑰規(guī)則 // 第一個參數(shù)表示:密鑰,key的字節(jié)數(shù)組 // 第二個參數(shù)表示:算法 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); // 對加密進(jìn)行初始化 // 第一個參數(shù):表示模式,有加密模式和解密模式 // 第二個參數(shù):表示秘鑰規(guī)則 cipher.init(Cipher.ENCRYPT_MODE, sks); // 進(jìn)行加密 byte[] bytes = cipher.doFinal(input.getBytes()); // 打印字節(jié),因為ascii碼有負(fù)數(shù),解析不出來,所以亂碼 for (byte b : bytes) { System.out.println(b); } // 打印密文 System.out.println(new String(bytes)); }}測試結(jié)果: -70 22 -58 -96 37 113 37 -81 �Ơ%q%�1234567891011121314151617181920212223242526272829303132333435363738394041 轉(zhuǎn)碼代碼: String encode = Base64.encode(bytes); 測試結(jié)果: base64轉(zhuǎn)碼前:�i,6�M base64轉(zhuǎn)碼后:2GksNrsVEk0=123456 // 解密方法: public static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception { // 1,獲取Cipher對象 Cipher cipher = Cipher.getInstance(transformation); // 指定密鑰規(guī)則 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); cipher.init(Cipher.DECRYPT_MODE, sks); // 3. 解密,上面使用的base64編碼,下面直接用密文 byte[] bytes = cipher.doFinal(Base64.decode(input)); // 因為是明文,所以直接返回 return new String(bytes); }123456789101112 3.3 base64Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)碼的可讀性編碼算法之一 可讀性編碼算法不是為了保護(hù)數(shù)據(jù)的安全性,而是為了可讀性 可讀性編碼不改變信息內(nèi)容,只改變信息內(nèi)容的表現(xiàn)形式 所謂Base64,即是說在編碼過程中使用了64種字符:大寫A到Z、小寫a到z、數(shù)字0到9、“+”和“/” Base58是Bitcoin(比特幣)中使用的一種編碼方式,主要用于產(chǎn)生Bitcoin的錢包地址 相比Base64,Base58不使用數(shù)字"0",字母大寫"O",字母大寫"I",和字母小寫"i",以及"+"和"/"符號123456 public class TestBase64 { public static void main(String[] args) { // 1:MQ== 表示一個字節(jié),不夠三個字節(jié),所以需要后面通過 == 號補齊 System.out.println(Base64.encode("1".getBytes()));// System.out.println(Base64.encode("12".getBytes()));// System.out.println(Base64.encode("123".getBytes()));// // 你好:中文占6個字節(jié),6 * 8 = 48 ,剛剛好被整除,所以沒有等號// System.out.println(Base64.encode("你好".getBytes())); }}測試結(jié)果: MQ== MTI= MTIZ123456789101112131415 3.4 AES加密解密public class AESUtil { // 加密方法 public static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception { // 獲取加密對象 Cipher cipher = Cipher.getInstance(transformation); // 創(chuàng)建加密規(guī)則 // 第一個參數(shù)key的字節(jié) // 第二個參數(shù)表示加密算法 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); // ENCRYPT_MODE:加密模式 // DECRYPT_MODE: 解密模式 // 初始化加密模式和算法 cipher.init(Cipher.ENCRYPT_MODE,sks); // 加密 byte[] bytes = cipher.doFinal(input.getBytes()); // 輸出加密后的數(shù)據(jù) String encode = Base64.encode(bytes); return encode; } // 解密方法: public static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception { // 1,獲取Cipher對象 Cipher cipher = Cipher.getInstance(transformation); // 指定密鑰規(guī)則 SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm); cipher.init(Cipher.DECRYPT_MODE, sks); // 3. 解密,上面使用的base64編碼,下面直接用密文 byte[] bytes = cipher.doFinal(Base64.decode(input)); // 因為是明文,所以直接返回 return new String(bytes); }}1234567891011121314151617181920212223242526272829303132333435 public class AESDemo { public static void main(String[] args) throws Exception { String input = "原文"; // DES加密算法,key的大小必須是8個字節(jié) String key = "1234567812345678"; String transformation = "AES"; // 指定獲取密鑰的算法 String algorithm = "AES"; String encryptDES = AESUtil.encryptDES(input, key, transformation, algorithm); System.out.println("加密:" + encryptDES); String s = AESUtil.decryptDES(encryptDES, key, transformation, algorithm); System.out.println("解密:" + s); }}測試結(jié)果: 加密:TUuxDy0h/Rx1KwhMFXEnog== 解密:原文1234567891011121314151617 3.5 toString()與new String ()用法區(qū)別4 加密模式5 填充模式AES/CBC/NoPadding (128)AES/CBC/PKCS5Padding (128)AES/ECB/NoPadding (128)AES/ECB/PKCS5Padding (128)DES/CBC/NoPadding (56)DES/CBC/PKCS5Padding (56)DES/ECB/NoPadding (56)DES/ECB/PKCS5Padding (56)DESede/CBC/NoPadding (168)DESede/CBC/PKCS5Padding (168)DESede/ECB/NoPadding (168)DESede/ECB/PKCS5Padding (168)RSA/ECB/PKCS1Padding (1024, 2048)RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)123456789101112131415 6 消息摘要- MD5- SHA1- SHA256- SHA5121234 bd465ea30ee7e0a66ed67e86d45a53aa5aba0c8d190934e7dfa58294a21ada7b967877d848e1836a19bf01437cab64f275ac827d81b3f3253eb961b60361a045 *apache-tomcat-10.0.2.exe1 // 消息摘要算法,為了防止篡改public class DigestDemo1 { public static void main(String[] args) throws NoSuchAlgorithmException { // 原文 String input = "aa"; // 算法 String algorithm = "MD5"; // 獲取數(shù)字摘要對象 MessageDigest messageDigest = MessageDigest.getInstance(algorithm); // 獲取消息數(shù)字摘要的字節(jié)數(shù)組 byte[] digest = messageDigest.digest(input.getBytes()); System.out.println(new String(digest)); // 結(jié)合base64解決轉(zhuǎn)碼 System.out.println(Base64.encode(digest)); }}測試結(jié)果: A$� �5�o$� zI 轉(zhuǎn)碼后:QSS8CpM1wn8IbyS6IHpJEg==123456789101112131415161718192021 // 4124bc0a9335c27f086f24ba207a4912 md5 在線校驗 // QSS8CpM1wn8IbyS6IHpJEg== 消息摘要使用的是16進(jìn)制12 // 消息摘要算法,為了防止篡改public class DigestDemo1 { public static void main(String[] args) throws NoSuchAlgorithmException { // 原文 String input = "aa"; // 算法 String algorithm = "MD5"; // 獲取數(shù)字摘要對象 MessageDigest messageDigest = MessageDigest.getInstance(algorithm); // 獲取消息數(shù)字摘要的字節(jié)數(shù)組 byte[] digest = messageDigest.digest(input.getBytes()); // 創(chuàng)建對象用來拼接 StringBuilder sb = new StringBuilder(); // 對密文進(jìn)行迭代 for (byte b : digest) { // 轉(zhuǎn)成 16進(jìn)制 String s = Integer.toHexString(b & 0xff);// System.out.println(s); if (s.length() == 1){ // 如果生成的字符只有一個,前面補0 s = "0"+s; } sb.append(s); } System.out.println(sb.toString()); }}12345678910111213141516171819202122232425262728 public class DigestDemo12 { public static void main(String[] args) throws Exception { // 原文 String input = "aa"; // 算法 String algorithm = "MD5"; // 獲取數(shù)字摘要對象 String md5 = getDigest(input, "MD5"); System.out.println(md5); String sha1 = getDigest(input, "SHA-1"); System.out.println(sha1); String sha256 = getDigest(input, "SHA-256"); System.out.println(sha256); String sha512 = getDigest(input, "SHA-512"); System.out.println(sha512); } private static String toHex(byte[] digest) throws Exception {// System.out.println(new String(digest)); // base64編碼// System.out.println(Base64.encode(digest)); // 創(chuàng)建對象用來拼接 StringBuilder sb = new StringBuilder(); for (byte b : digest) { // 轉(zhuǎn)成 16進(jìn)制 String s = Integer.toHexString(b & 0xff); if (s.length() == 1) { // 如果生成的字符只有一個,前面補0 s = "0" + s; } sb.append(s); } System.out.println("16進(jìn)制數(shù)據(jù)的長度:" + sb.toString().getBytes().length); return sb.toString(); } private static String getDigest(String input, String algorithm) throws Exception { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); // 消息數(shù)字摘要 byte[] digest = messageDigest.digest(input.getBytes()); System.out.println("密文的字節(jié)長度:" + digest.length); return toHex(digest); }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 public class DigestDemo { public static void main(String[] args) throws Exception { String input = "aa"; String algorithm = "MD5"; // sha1 可以實現(xiàn)秒傳功能 String sha1 = getDigestFile("D:\\apache-tomcat-9.0.41.zip", "SHA-1"); System.out.println(sha1); String sha512 = getDigestFile("D:\\apache-tomcat-9.0.41.zip", "SHA-512"); System.out.println(sha512); String md5 = getDigest("aa", "MD5"); System.out.println(md5); String md51 = getDigest("aa ", "MD5"); System.out.println(md51); } private static String getDigestFile(String filePath, String algorithm) throws Exception { FileInputStream fis = new FileInputStream(filePath); int len; byte[] buffer = new byte[1024]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((len = fis.read(buffer)) != -1) { baos.write(buffer, 0, len); } // 獲取消息摘要對象 MessageDigest messageDigest = MessageDigest.getInstance(algorithm); // 獲取消息摘要 byte[] digest = messageDigest.digest(baos.toByteArray()); System.out.println("密文的字節(jié)長度:" + digest.length); return toHex(digest); } private static String getDigest(String input, String algorithm) throws Exception { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); byte[] digest = messageDigest.digest(input.getBytes()); System.out.println("密文的字節(jié)長度:" + digest.length); return toHex(digest); } private static String toHex(byte[] digest) { // System.out.println(new String(digest)); // 消息摘要進(jìn)行表示的時候,是用16進(jìn)制進(jìn)行表示 StringBuilder sb = new StringBuilder(); for (byte b : digest) { // 轉(zhuǎn)成16進(jìn)制 String s = Integer.toHexString(b & 0xff); // 保持?jǐn)?shù)據(jù)的完整性,前面不夠的用0補齊 if (s.length() == 1) { s = "0" + s; } sb.append(s); } System.out.println("16進(jìn)制數(shù)據(jù)的長度:" + sb.toString().getBytes().length); return sb.toString(); }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 7 非對稱加密7.1 生成公鑰和私鑰public class RSAdemo { public static void main(String[] args) throws Exception { // 加密算法 String algorithm = "RSA"; // 創(chuàng)建密鑰對生成器對象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // 生成密鑰對 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成私鑰 PrivateKey privateKey = keyPair.getPrivate(); // 生成公鑰 PublicKey publicKey = keyPair.getPublic(); // 獲取私鑰字節(jié)數(shù)組 byte[] privateKeyEncoded = privateKey.getEncoded(); // 獲取公鑰字節(jié)數(shù)組 byte[] publicKeyEncoded = publicKey.getEncoded(); // 對公私鑰進(jìn)行base64編碼 String privateKeyString = Base64.encode(privateKeyEncoded); String publicKeyString = Base64.encode(publicKeyEncoded); // 打印私鑰 System.out.println(privateKeyString); // 打印公鑰 System.out.println(publicKeyString); }}12345678910111213141516171819202122232425 7.2 私鑰加密// 私鑰加密public class RSAdemo { public static void main(String[] args) throws Exception { String input = "hello"; // 加密算法 String algorithm = "RSA"; // 創(chuàng)建密鑰對生成器對象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // 生成密鑰對 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成私鑰 PrivateKey privateKey = keyPair.getPrivate(); // 生成公鑰 PublicKey publicKey = keyPair.getPublic(); // 獲取私鑰字節(jié)數(shù)組 byte[] privateKeyEncoded = privateKey.getEncoded(); // 獲取公鑰字節(jié)數(shù)組 byte[] publicKeyEncoded = publicKey.getEncoded(); // 對公私鑰進(jìn)行base64編碼 String privateKeyString = Base64.encode(privateKeyEncoded); String publicKeyString = Base64.encode(publicKeyEncoded); // 創(chuàng)建加密對象 // 參數(shù)表示加密算法 Cipher cipher = Cipher.getInstance(algorithm); // 初始化加密 // 第一個參數(shù):加密的模式 // 第二個參數(shù):使用私鑰進(jìn)行加密 cipher.init(Cipher.ENCRYPT_MODE,privateKey); // 私鑰加密 byte[] bytes = cipher.doFinal(input.getBytes()); System.out.println(Base64.encode(bytes)); }}123456789101112131415161718192021222324252627282930313233 7.3 私鑰加密私鑰解密public class RSAdemo2 { public static void main(String[] args) throws Exception { String input = "你好"; // 加密算法 String algorithm = "RSA"; // 創(chuàng)建密鑰對生成器對象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // 生成密鑰對 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成私鑰 PrivateKey privateKey = keyPair.getPrivate(); // 生成公鑰 PublicKey publicKey = keyPair.getPublic(); // 獲取私鑰字節(jié)數(shù)組 byte[] privateKeyEncoded = privateKey.getEncoded(); // 獲取公鑰字節(jié)數(shù)組 byte[] publicKeyEncoded = publicKey.getEncoded(); // 對公私鑰進(jìn)行base64編碼 String privateKeyString = Base64.encode(privateKeyEncoded); String publicKeyString = Base64.encode(publicKeyEncoded); // 創(chuàng)建加密對象 // 參數(shù)表示加密算法 Cipher cipher = Cipher.getInstance(algorithm); // 初始化加密 // 第一個參數(shù):加密的模式 // 第二個參數(shù):使用私鑰進(jìn)行加密 cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 私鑰加密 byte[] bytes = cipher.doFinal(input.getBytes()); System.out.println("加密后:"+Base64.encode(bytes)); // 私鑰進(jìn)行解密 cipher.init(Cipher.DECRYPT_MODE, privateKey); // 對密文進(jìn)行解密,不需要使用base64,因為原文不會亂碼 byte[] bytes1 = cipher.doFinal(bytes); System.out.println("解密后:"+new String(bytes1)); }}12345678910111213141516171819202122232425262728293031323334353637383940 7.4 私鑰加密公鑰解密public class RSAdemo2 { public static void main(String[] args) throws Exception { String input = "你好"; // 加密算法 String algorithm = "RSA"; // 創(chuàng)建密鑰對生成器對象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // 生成密鑰對 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成私鑰 PrivateKey privateKey = keyPair.getPrivate(); // 生成公鑰 PublicKey publicKey = keyPair.getPublic(); // 獲取私鑰字節(jié)數(shù)組 byte[] privateKeyEncoded = privateKey.getEncoded(); // 獲取公鑰字節(jié)數(shù)組 byte[] publicKeyEncoded = publicKey.getEncoded(); // 對公私鑰進(jìn)行base64編碼 String privateKeyString = Base64.encode(privateKeyEncoded); String publicKeyString = Base64.encode(publicKeyEncoded); // 創(chuàng)建加密對象 // 參數(shù)表示加密算法 Cipher cipher = Cipher.getInstance(algorithm); // 初始化加密 // 第一個參數(shù):加密的模式 // 第二個參數(shù):使用私鑰進(jìn)行加密 cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 私鑰加密 byte[] bytes = cipher.doFinal(input.getBytes()); System.out.println("加密后:"+Base64.encode(bytes)); // 公鑰進(jìn)行解密 cipher.init(Cipher.DECRYPT_MODE, publicKey); // 對密文進(jìn)行解密,不需要使用base64,因為原文不會亂碼 byte[] bytes1 = cipher.doFinal(bytes); System.out.println("解密后:"+new String(bytes1)); }}12345678910111213141516171819202122232425262728293031323334353637383940 7.5 保存公鑰和私鑰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數(shù)組 byte[] publicKeyEncoded = publicKey.getEncoded(); byte[] privateKeyEncoded = privateKey.getEncoded(); // 進(jìn)行Base64編碼 String publicKeyString = Base64.encode(publicKeyEncoded); String privateKeyString = Base64.encode(privateKeyEncoded); // 保存文件 FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8")); FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8")); }12345678910111213141516171819 7.6 讀取私鑰public static PrivateKey getPrivateKey(String priPath, String algorithm) throws Exception { // 將文件內(nèi)容轉(zhuǎn)為字符串 String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset()); // 輸出私鑰 System.out.println(privateKeyString); // 獲取密鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); // 構(gòu)建密鑰規(guī)范 進(jìn)行Base64解碼 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString)); // 生成私鑰 return keyFactory.generatePrivate(spec); }123456789101112 7.7 讀取公鑰public static PublicKey getPublicKey(String pulickPath, String algorithm) throws Exception { // 將文件內(nèi)容轉(zhuǎn)為字符串 String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset()); System.out.println(publicKeyString); // 獲取密鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); // 構(gòu)建密鑰規(guī)范 進(jìn)行Base64解碼 X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(publicKeyString)); // 生成公鑰 return keyFactory.generatePublic(spec); }123456789101112 7.8 RSA工具類<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version></dependency>12345 public class RSAUtil { private static final String KEY_ALGORITHM = "RSA"; private static KeyPairGenerator keyPairGenerator; // 為每一個字段生成公私密鑰 public static void makeRsaKeys(String pubPath, String priPath, String user) throws Exception { try { keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } //隨機數(shù)生成器 SecureRandom random = new SecureRandom(); //設(shè)置KEY_SIZE位長的秘鑰 int KEY_SIZE = 1024; keyPairGenerator.initialize(KEY_SIZE, random); //開始創(chuàng)建 KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic();//公鑰 PrivateKey privateKey = keyPair.getPrivate();//私鑰 //使用Base64進(jìn)行轉(zhuǎn)碼 String publicKeyStr = Base64.encode(publicKey.getEncoded()); String privateKeyStr = Base64.encode(privateKey.getEncoded()); // 保存文件 FileUtils.writeStringToFile(new File(pubPath), publicKeyStr, Charset.forName("UTF-8")); FileUtils.writeStringToFile(new File(priPath), privateKeyStr, Charset.forName("UTF-8")); } // 私鑰加密 public static String privateKeyDecode(String data, int mode, String priPath) throws Exception { // 將文件內(nèi)容轉(zhuǎn)為字符串 String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset()); // 輸出私鑰// System.out.println(privateKeyString); // 獲取密鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 構(gòu)建密鑰規(guī)范 進(jìn)行Base64解碼 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString)); // 生成私鑰 PrivateKey privateKey = keyFactory.generatePrivate(spec); try { Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); if (mode == Cipher.ENCRYPT_MODE) {//加密 cipher.init(mode, privateKey); return Base64.encode(cipher.doFinal(data.getBytes())); } else if (mode == Cipher.DECRYPT_MODE) {//解密 cipher.init(mode, privateKey); return new String(cipher.doFinal(Base64.decode(data)), StandardCharsets.UTF_8); } else { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } // 公鑰解密 public static String publicKeyDecode(String data, String pulickPath, int mode) throws Exception { // 將文件內(nèi)容轉(zhuǎn)為字符串 String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());// System.out.println(publicKeyString); // 獲取密鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 構(gòu)建密鑰規(guī)范 進(jìn)行Base64解碼 X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(publicKeyString)); // 生成公鑰 PublicKey publicKey = keyFactory.generatePublic(spec); try { Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); if (mode == Cipher.ENCRYPT_MODE) {//加密 cipher.init(mode, publicKey); return Base64.encode(cipher.doFinal(data.getBytes())); } else if (mode == Cipher.DECRYPT_MODE) {//解密 cipher.init(mode, publicKey); byte[] bytes = cipher.doFinal(Base64.decode(data)); return new String(bytes, StandardCharsets.UTF_8); } else { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) throws Exception { String user = "root"; // 公鑰路徑 String pubPath = "D:\\IDEA\\encrypt-decrypt\\src\\main\\java\\com\\zwh\\key\\" + user + ".txt"; // 私鑰路徑 String priPath = "D:\\IDEA\\encrypt-decrypt\\src\\main\\java\\com\\zwh\\key\\" + user + "_en.txt"; makeRsaKeys(pubPath, priPath, user); String str = "123456"; System.out.println("明文:" + str); System.out.println("---------私鑰加密,公鑰解密-----------"); String privateKeyDecode = privateKeyDecode(str, 1, priPath); System.out.println("私鑰加密:" + privateKeyDecode); String publicKeyDecode = publicKeyDecode(privateKeyDecode, pubPath, 2); System.out.println("公鑰解密:" + publicKeyDecode); }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 8 數(shù)字簽名public class SignatureDemo { public static void main(String[] args) throws Exception { String a = "123"; PublicKey publicKey = RSAdemo4.getPublicKey("a.pub", "RSA"); PrivateKey privateKey = RSAdemo4.getPrivateKey("a.pri", "RSA"); String signaturedData = getSignature(a, "sha256withrsa", privateKey); boolean b = verifySignature(a, "sha256withrsa", publicKey, signaturedData); System.out.println(b); System.out.println(signaturedData); } /** * 生成簽名 * * @param input : 原文 * @param algorithm : 算法 * @param privateKey : 私鑰 * @return : 簽名 * @throws Exception */ 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[] sign = signature.sign(); // 對簽名數(shù)據(jù)進(jìn)行Base64編碼 return Base64.encode(sign); } /** * 校驗簽名 * * @param input : 原文 * @param algorithm : 算法 * @param publicKey : 公鑰 * @param signaturedData : 簽名 * @return : 數(shù)據(jù)是否被篡改 * @throws Exception */ private static boolean verifySignature(String input, String algorithm, PublicKey publicKey, String signaturedData) throws Exception { // 獲取簽名對象 Signature signature = Signature.getInstance(algorithm); // 初始化簽名 signature.initVerify(publicKey); // 傳入原文 signature.update(input.getBytes()); // 校驗數(shù)據(jù) return signature.verify(Base64.decode(signaturedData)); }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 該文章在 2023/6/2 10:10:50 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |