加密算法
时间:2022-03-29 01:57
加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。
双向加密:大体意思就是明文加密后形成密文,可以通过算法还原成明文。 单向加密:只是对信息进行了摘要计算,不能通过算法生成明文,单向加密从严格意思上说不能算是加密的一种,应该算是摘要算法。 主要算法提供方: JDK:java.security和javax.crypto包下的类 Bouncy Castle(丰富JDK中加密算法的不足)jar包:bcprov-jdk15on-1.57.jar
主页: Commons Codec(简化JDK中加密的操作)jar包是:commons-codec-1.10.jar 主页:
1、Base64
采用Base64编码具有不可读性,多用于网络中传输的数据进行编码,严格意义上属于编码的格式,有64个字符的对应的编码,Base64就是将内容按照该格式进行编码。可以对数据编码和解码,是可逆的,安全度较低,不过,也可以作为最基础最简单的加密算法用于加密要求较弱的情况。JDk实现主要使用用BASE64Encoder和BASE64Decoder类的方法(注意:在Eclipse中使用JDK的Base64可能会出现找不到的问题,是因为Base64Encoder并不属于JDK标准库范畴,但是又包含在了JDK中,需要我们手动导入\jre\lib目录下的rt.jar包即可)。 注意点: 1、标准的Base64并不适合直接放在URL里传输; 2、不是加密算法,而是一种将数据编码为64位二进制字符;
package com.paic.java8; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Base64; import java.util.UUID; public class Base64Demo { public static void main(String args[]) { try { // 使用基本编码 String bStr = "I am a hero!"; System.out.println("字符串:"+bStr); String base64encodedString = Base64.getEncoder().encodeToString(bStr.getBytes("utf-8")); System.out.println("基本(编码) :" + base64encodedString); // 解码 byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString); System.out.println("基本(解码): " + new String(base64decodedBytes, "utf-8")); //----------------------- String urlStr = "TutorialsPoint?java8"; System.out.println("URL字符串:"+urlStr); base64encodedString = Base64.getUrlEncoder().encodeToString(urlStr.getBytes("utf-8")); System.out.println("URL(编码) :" + base64encodedString); base64decodedBytes = Base64.getUrlDecoder().decode(base64encodedString); System.out.println("URL(解码): " + new String(base64decodedBytes, "utf-8")); //--------------------------- StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < 10; ++i) { stringBuilder.append(UUID.randomUUID().toString()); } System.out.println("MIME字符串 :"+stringBuilder.toString()); byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8"); String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes); System.out.println("MIME(编码) :" + mimeEncodedString); base64decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString); System.out.println("MIME(解码): " + new String(base64decodedBytes, "utf-8")); } catch (UnsupportedEncodingException e) { System.out.println("Error :" + e.getMessage()); } } }
字符串:I am a hero! 基本(编码) :SSBhbSBhIGhlcm8h 基本(解码): I am a hero! URL字符串:TutorialsPoint?java8 URL(编码) :VHV0b3JpYWxzUG9pbnQ_amF2YTg= URL(解码): TutorialsPoint?java8 MIME字符串 :ff3eb049-2440-4776-ba6d-becccda60c6f5def99b1-2009-433b-a09c-7fc393305e0641629364-0a92-4d5e-8c5d-1c5ad6a14025ec2ad8ce-2a51-4a0e-b633-ddbb9b2671a15a4fe3e9-7217-4209-a2f1-c478f29cf2dc591579bb-5e31-4984-b4c2-a960924e06e125b28902-aea3-4f76-bcd2-afe533a65cccb66a5eda-71e4-46ba-93fa-0ce685e7e67b9f704c87-34a0-441c-88fc-867a861d771d450d445d-a7ef-4309-b884-f787615f0512 MIME(编码) :ZmYzZWIwNDktMjQ0MC00Nzc2LWJhNmQtYmVjY2NkYTYwYzZmNWRlZjk5YjEtMjAwOS00MzNiLWEw OWMtN2ZjMzkzMzA1ZTA2NDE2MjkzNjQtMGE5Mi00ZDVlLThjNWQtMWM1YWQ2YTE0MDI1ZWMyYWQ4 Y2UtMmE1MS00YTBlLWI2MzMtZGRiYjliMjY3MWExNWE0ZmUzZTktNzIxNy00MjA5LWEyZjEtYzQ3 OGYyOWNmMmRjNTkxNTc5YmItNWUzMS00OTg0LWI0YzItYTk2MDkyNGUwNmUxMjViMjg5MDItYWVh My00Zjc2LWJjZDItYWZlNTMzYTY1Y2NjYjY2YTVlZGEtNzFlNC00NmJhLTkzZmEtMGNlNjg1ZTdl NjdiOWY3MDRjODctMzRhMC00NDFjLTg4ZmMtODY3YTg2MWQ3NzFkNDUwZDQ0NWQtYTdlZi00MzA5 LWI4ODQtZjc4NzYxNWYwNTEy MIME(解码): ff3eb049-2440-4776-ba6d-becccda60c6f5def99b1-2009-433b-a09c-7fc393305e0641629364-0a92-4d5e-8c5d-1c5ad6a14025ec2ad8ce-2a51-4a0e-b633-ddbb9b2671a15a4fe3e9-7217-4209-a2f1-c478f29cf2dc591579bb-5e31-4984-b4c2-a960924e06e125b28902-aea3-4f76-bcd2-afe533a65cccb66a5eda-71e4-46ba-93fa-0ce685e7e67b9f704c87-34a0-441c-88fc-867a861d771d450d445d-a7ef-4309-b884-f787615f0512View Code
2、摘要算法
摘要算法主要分为MD,SHA和Hmac算法(已经被攻破,彩虹表和MD5站点)。摘要算法其实是用于效验数据完整性的,我们在下载某些文件时,会有MD5和SHA1值提供我们校验下载的文件是否完整,可以用于根据数据生成其唯一的摘要值,无法根据摘要值知道原数据,属于不可逆的。 原理:摘要由一个单向Hash加密函数对消息进行作用而产生,HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母,通过哈希算法作用后都将产生不同的值。而HASH算法的单向性使得要找到哈希值相同的两个不同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。 主要过程如下:
说明:
1、以上是坏蛋不知密钥情况下,发送请求,第三方根据请求参数+密钥生成sign与请求的sign比较;
2、而如果坏蛋通过截获的sign,解密md5获得明文,并且通过大量的请求分析出密钥与消息体的拼接规则,则依然存在安全问题;MD5
注意:这里128位是二进制,换算16进制32位
如:
package com.paic.java8; import org.apache.commons.codec.binary.Hex; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MDXDemo { public static void main(String[] args) { String screctKey = "123"; String content = "Hello"; encrypt(content,screctKey); } /** * 加密 * @param content * @param screctKey */ public static void encrypt(String content,String screctKey){ MessageDigest md5= null; MessageDigest md2= null; //内容 + 密钥 //原因:如果单单只是内容,攻击方也是可以通过MD5得到sign1,拼接攻击方不知到的密钥,在攻击方篡改内容后将得到不同的sign2 //当然攻击方可以根据sign1解密从而获得密钥 String src = content + screctKey; try { md5 = MessageDigest.getInstance("MD5"); md2 = MessageDigest.getInstance("MD2"); byte[] digest5 = md5.digest(src.getBytes()); byte[] digest2 = md2.digest(src.getBytes()); System.out.println("JDK MD5: "+ Hex.encodeHexString(digest5)); System.out.println("JDK MD2: "+ Hex.encodeHexString(digest2)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } }
32位字符
JDK MD5: d0aabe9a362cb2712ee90e04810902f3
JDK MD2: 014b1eb8d5557bb786b83a18c9fbbe2e
解密,在线上测试下:https://www.somd5.com/
SHA
安全性:SHA1所产生的摘要比MD5长32位。若两种散列函数在结构上没有任何问题的话,SHA1比MD5更安全
package com.paic.java8; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHAXDemo { public static void main(String[] args) { String content = "Hello"; jdkSHA1(content); ccsha(content); } /** * JDK实现方式(同样是使用MessageDigest) * @param src */ public static void jdkSHA1(String src){ MessageDigest digest; try { digest = MessageDigest.getInstance("SHA"); digest.update(src.getBytes()); System.out.println("JDK SHA1:"+Hex.encodeHexString(digest.digest())); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * cc的实现方式 * @param src */ public static void ccsha(String src){ System.out.println("CC SHA1:"+ DigestUtils.sha1Hex(src)); } //BC略... }
JDK SHA1:f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
CC SHA1:f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
Hmac
含有密钥的摘要算法,也有简称mac,密钥不同摘要也不同
package com.paic.java8.encry; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public class HmacDemo { public static void main(String[] args) { encrypt("Hello","aaaaaaaaaa"); } /** * JDK的实现方式 BC略 * @param content * @param key */ public static void encrypt(String content,String key){ SecretKey secretKey = getSecretKey(key); try { Mac mac= Mac.getInstance(secretKey.getAlgorithm()); //初始化mac mac.init(secretKey); byte[] hmacMD5Bytes=mac.doFinal(content.getBytes()); //jdk hmacMD5: bfb61695a42d5d16add45743a4e0eea4 System.out.println("jdk hmacMD5: "+Hex.encodeHexString(hmacMD5Bytes)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } } /** * 获取默认密钥 * @return */ public static SecretKey getDefaultSecretKey() { SecretKey secretKey = null; //初始化KeyGenerator KeyGenerator keyGenerator = null; try { keyGenerator = KeyGenerator.getInstance("HmacMD5"); //产生密钥 secretKey = keyGenerator.generateKey(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return secretKey; } /** * 自定义密钥 * @param key * @return */ public static SecretKey getSecretKey(String key){ SecretKey secretKey = null; byte[] keyByteArr= null; try { //长度必须偶数 boolean flag = (null == key)? true : ((key.length()) & 1) != 0; if(flag){ throw new DecoderException("Key长度必须偶数"); } keyByteArr = Hex.decodeHex(key.toCharArray()); secretKey = new SecretKeySpec(keyByteArr,"HmacMD5"); } catch (DecoderException e) { e.printStackTrace(); } return secretKey; } }
3、对称加密
待续
4、非对称加密
待续