赞
踩
编码是直接给每个字符指定一个若干字节表示的整数。
常见的编解码算法有:URL编码、Base64编码。
1、URL编码是浏览器发送数据给服务器时使用的编码。
特点:把数据编码成前缀为%表示的字符串。
URL编码对A(a)-Z(z),0-9, - , _ , . , * 这些字符不进行编码,除此以外的字符则需要进行编码。
URLEncoder类:对URL进行斑马操作的。
有编码必然有解码,URLDecoder类:对URL进行解码操作的。
2.Base64编码:将字节数组编码成字符串或将字符串解码为字节数组
特点:把字符编码成%xx表示的形式。
1、哈希算法又称摘要算法,作用是对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
目的:验证原始数据是否被篡改。
2、哈希碰撞是指:两个不同的输入得到了相同的输出。
哈希碰撞不能避免,因为输出的字节长度是固定的,而且最多有4294967296中输出,但是有无限种输入。
3、常见的哈希算法:MD5算法,SHA-1(20字节),SHA-256(32字节),SHA-512(64字节),RipeMD-160算法(Java标准类库中没有提供RipeMD-160算法)。
MD5算法(长度:16字节)
需要编写一个hash算法的工具类,定义bytesToHex()方法,将字节数组转换为十六进制字符串。
SHA-1算法:与MD5使用方法一样,只用在实例化MessageDigest对象时将传入的参数改为"SHA-1"即可。
RipeMD160算法
- public class Demo03 {
- //使用第三方开源库提供的RipeMD160消息摘要算法实现
- public static void main(String[] args) throws NoSuchAlgorithmException {
- //注册BouncyCastleBouncyCastleProvider通知类
- //将提供的消息摘要算法注册至Security
- Security.addProvider(new BouncyCastleProvider());
-
- //获取RipeMD160算法的“消息摘要对象”(加密对象)
- MessageDigest ripeMd160 = MessageDigest.getInstance("RipeMD160");
- //更新原始数据
- ripeMd160.update("wbjxxmy".getBytes());
- //获取消息摘要(加密)
- byte[] result = ripeMd160.digest();
- //消息摘要的字节长度和内容
- System.out.println("加密结果(字节长度):"+result.length);//160位=20字节
- System.out.println("加密结果(字节内容):"+Arrays.toString(result));
-
- //16进制内容字符串
- String hex = new BigInteger(1,result).toString(16);
- System.out.println("加密结果(字符串长度):"+hex.length());
- System.out.println("加密结果(字符串内容):"+hex);
- }
- }
4.存储用户密码
如果直接将用户的密码不做任何处理直接放入数据库中,会存在很大的安全风险。所以改进方法是存储用户密码的哈希。
什么是彩虹表攻击?例如:使用MD5。就是将常用口令和它们MD5制作成一张表(这个表足够庞大),这个表就是彩虹表。为了防止彩虹表攻击,对每个口令前面追加一些额外的数字,这就是盐值。
5.解决MD5算法与SHA-1算法代码冗余
- //hash算法工具类
- public class HashTools {
- //定义全局变量,消息摘要对象
- private static MessageDigest digest;
-
- //构造方法私有
- private HashTools() {}
-
- //按照MD5进行消息摘要算法(哈希计算)
- public static String digestByMD5(String source) throws NoSuchAlgorithmException {
- //基于MD5算法
- digest = MessageDigest.getInstance("MD5");
- return handler(source);
- }
- //按照SHA-1进行消息摘要算法(哈希计算)
- public static String digestBySHA1(String source) throws NoSuchAlgorithmException {
- //基于SHA-1算法
- digest = MessageDigest.getInstance("SHA-1");
- return handler(source);
- }
- //通过消息摘要对象,处理加密内容
- private static String handler(String source) {
- //更新原始数据
- digest.update(source.getBytes());
- //进行加密处理
- byte[] bytes = digest.digest();
- //将字节数组转换成十六进制
- String hash = bytesToHex(bytes);
- return hash;
- }
- //将字节数组转换为16进制字符串
- public static String bytesToHex(byte[] bytes) {
- StringBuilder ret = new StringBuilder();
- for(Byte b : bytes) {
- //将字节值转换为2位十六进制字符串
- ret.append(String.format("%02x", b));
- }
- return ret.toString();
- }
- }
1、使用秘钥生成器生成秘钥,进行加密处理
- public class Demo01 {
- public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
- String password = "wbjxxmy";
- //1.产生秘钥
- //获取HmacMD5秘钥生成器
- KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
- //生成密钥
- SecretKey key = keyGen.generateKey();
- System.out.println("秘钥:"+Arrays.toString(key.getEncoded()));
- System.out.println("秘钥长度(64字节):"+key.getEncoded().length);
- System.out.println("秘钥:"+HashTools.bytesToHex(key.getEncoded()));
-
- //2.使用秘钥,进行加密
- //获取HMac加密算法
- //创建Mac对象,传入"HmacMD5"算法
- Mac mac = Mac.getInstance("HmacMD5");
- //初始化秘钥
- mac.init(key);
- //更新原始加密内容
- mac.update(password.getBytes());
- //加密处理,并获取加密结果
- byte[] bytes = mac.doFinal();
- //加密结果处理成16进制字符串
- String result = HashTools.bytesToHex(bytes);
- System.out.println("加密结果16进制字符串:"+result);
- System.out.println("加密结果(字节长度16字节):"+bytes.length);
- System.out.println("加密结果(字符长度32字节):"+result.length());
- }
- }
2、给定秘钥字节数组,恢复Hmac秘钥
给定一个秘钥字节数组,先将其恢复成秘钥对象,再进行加密处理。
- //秘钥(字节数组)
- byte[] keyBytes = {51, 8, 87, 91, 106, -78, 70, -119, 5, -75, 78, -52, -62, -33,
- -64, -102, 80, 56, 7, -43, -115, 57, 29, 69, -61, 121, -37, -47, -95,
- 66, -82, -116, -22, 19, -8, -42, 127, 67, 18, -109, -9, 89, 7, 6, 59,
- -63, 51, 35, 0, 45, -102, -20, -82, -82, 29, -105, 10, 0, -110, -70, 76,
- -102, -57, 50};
- try {
- //恢复秘钥(字节数组)
- SecretKey key = new SecretKeySpec(keyBytes, "HmacMD5");
- //创建Hmac加密算法对象
- Mac mac = Mac.getInstance("HmacMD5");
- //初始化秘钥
- mac.init(key);
- //更新原始加密内容
- mac.update(password.getBytes());
- //加密结果处理成16进制字符串
- String result = HashTools.bytesToHex(mac.doFinal());
- //输出
- System.out.println(result);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- }
3、按照"字符串",恢复Hmac秘钥
先将字符串转换成字节数组再进行后续步骤。
- //秘钥(字符串)
- String keyStr = "1dbb7361d48949df91e3ff0c5fab8666c5358a8daf965d6"
- + "bbd84ff90e17c3a365b2c6613ac257ae961d75402e88d47c6a0854de60cde"
- + "00.070982b3e437e4dec91af";
- //用于保存秘钥,秘钥长度为64字节
- byte[] keyBytes = new byte[64];
- //遍历字符串,将其保存进字节数组keyBytes中
- for(int i = 0,k = 0;i < keyStr.length();i += 2,k++) {
- //每次截取两位
- String s = keyStr.substring(i,i+2);
- //将截取的两位字符转换成16进制,放入字节数组中
- keyBytes[k] = (byte) Integer.parseInt(s,16);
- }
- try {
- //恢复秘钥(字节数组)
- SecretKey key = new SecretKeySpec(keyBytes, "HmacMD5");
- //创建Hmac加密算法对象
- Mac mac = Mac.getInstance("HmacMD5");
- //初始化秘钥
- mac.init(key);
- //更新原始加密内容
- mac.update(password.getBytes());
- //加密结果处理成16进制字符串
- String result = HashTools.bytesToHex(mac.doFinal());
- //输出
- System.out.println(result);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。