Hash算法

1,Hash算法之前先说一下编码算法:

编码就是Ascll码,ASCII编码最多只能有127个字符,要想对更多的文字进行编码,就需要用占用2个字节的Unicode或者3个字节的UTF-8。例如:中文的"中"字使用Unicode编码就是0x4e2d,UTF-8编码是0xe4b8ad,这是一些简单的编码,更为复杂就是要通过一些算法去编码。

URL编码:网页地址栏中会对中文进行编码,就是通常我们在地址栏看到的类似于一堆乱码一样,肉眼看不懂是啥的东西,这是应为是通过URL编码把中文转化之后的结果。

对“中文”加密------>"%E4%B8%AD%E6%96%87%21"


import java.net.URLEncoder;
public class Main {
    public static void main(String[] args) {
        String encoded = URLEncoder.encode("中文!", "utf-8");
		System.out.println(encoded);
    }
}

对加密结果("%E4%B8%AD%E6%96%87%21")进行解密--->中文

public class Main {
    public static void main(String[] args) {
        String decoded = URLDecoder.decode("%E4%B8%AD%E6%96%87%21", "utf-8");
		System.out.println(decoded);
    }
}

Base64编码:URL编码是对字符进行编码,表示成%xx的形式,而Base64编码是对二进制数据进行编码,表示成文本格式。

Base64编码可以把任意长度的二进制数据变为纯文本,并且纯文本内容中且只包含指定字符内容:A~Z、a~z、0~9、+、/、=。它的原理是把3字节的二进制数据按6bit一组,用4个int整数表示,然后查表,把int整数用索引对应到字符,得到编码后的字符串。
6位整数的范围总是0~63,所以,能用64个字符表示:字符A~Z对应索引0~25,字符a~z对应索引26~51,字符0~9对应索引52~61,最后两个索引62、63分别用字符+和/表示

对一个图片进行加密写到TXT文件:


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
public class demo02 {
	public static void main(String[] args) throws IOException {
      byte[] bytes = Files.readAllBytes(Paths.get("D:\\桌面\\jjg.png"));
      String string = Base64.getEncoder().encodeToString(bytes);
      List<String> list=new ArrayList<>();
      list.add(string);
      Files.write(Paths.get("D:\\桌面\\jjg.txt"), list);
      
	}
}

解密:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;

public class demo03 {
	public static void main(String[] args) throws IOException {
		List<String> list = Files.readAllLines(Paths.get("D:\\桌面\\jjg.txt"));

		String string = list.get(0);
		byte[] decode = Base64.getDecoder().decode(string);

		Files.write(Paths.get("D:\\桌面\\jg.jpg"), decode);

	}
}

Base64编码的缺点是传输效率会降低,因为它把原始数据的长度增加了1/3。和URL编码一样,Base64编码是一种编码算法,不是加密算法。
如果把Base64的64个字符编码表换成32个、48个或者58个,就可以使用Base32编码,Base48编码和Base58编码。字符越少,编码的效率就会越低。

2:哈希算法:

哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法最重要的特点就是:
●相同的输入一定得到相同的输出;
●不同的输入大概率得到不同的输出。(由于哈希碰撞是不可避免的,我们只能降低它发生碰撞的概率)
所以,哈希算法的目的:为了验证原始数据是否被篡改。

Java中标准库提供了常用的哈希算法,通过统一的接口进行调用,以MD5哈希算法为例,加密过程

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class demo04 {
	public static void main(String[] args) {
		String s = "大撒";

		try {
			// 创建一个MessageDigest实例:
			MessageDigest digest = MessageDigest.getInstance("MD5");
			// 可以反复调用update输入数据:
			digest.update(s.getBytes());
			// 将输入数据转化为字节数组,进行数据摘要
			byte[] digest2 = digest.digest();
			// 把摘要的数据进行十六进制的转化
			StringBuilder builder = new StringBuilder();
			for (byte r : digest2) {
				builder.append(String.format("%02x", r));
			}
			System.out.println(Arrays.toString(digest2));
			System.out.println("秘闻字符:" + builder);
		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
		}
	}
}

哈希算法用于检测文件是否被篡改,用户密码加密等,由于在不发生哈希碰撞的前提下,同样的输入,同样的哈希算法,信息摘要的结果是相同的所以可以有以上用途,因此当作为密码时,就很容易被解密(就是暴力试探即可解密)

也就是可以根据彩虹表便可快速解密,因此在进行哈希算法是要加盐的,也就是在进行数据摘要事前通过加入一个随机数据,两者结合进行数据摘要,即可大大降低彩虹表的攻击。

Hmac算法:加盐的哈希算法

       Hmac算法就是一种基于密钥的消息认证码算法,它的全称是Hash-based Message Authentication Code,是一种更安全的消息摘要算法。
Hmac算法总是和某种哈希算法配合起来用的。例如,我们使用MD5算法,对应的就是Hmac MD5算法,它相当于“加盐”的MD5:HmacMD5 ≈ md5(secure_random_key, input)
因此,HmacMD5可以看作带有一个安全的key的MD5。使用HmacMD5而不是用MD5加salt,有如下好处:
●HmacMD5使用的key长度是64字节,更安全;
●Hmac是标准算法,同样适用于SHA-1等其他哈希算法;
●Hmac输出和原有的哈希算法长度一致。

import java.util.Base64;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;

public class demo01 {
	public static void main(String[] args) {
		String password="686874Yyd";
		try {
//			创建密钥生成器对象
            KeyGenerator keygen = KeyGenerator.getInstance("HmacMD5");
//           生成密钥
            SecretKey generateKey = keygen.generateKey();
            
//          获取秘钥原始内容(字节数组)
           byte[] encoded = generateKey.getEncoded();
           String keystring = Base64.getEncoder().encodeToString(encoded);
//           基于密钥,进行HmacMD5的信息摘要计算
           Mac mac = Mac.getInstance("HmacMD5");
           mac.init(generateKey);
//           添加原文
           mac.update(password.getBytes());
           
//           最终计算
           byte[] doFinal = mac.doFinal();
           
           StringBuilder builder = new StringBuilder();
           
           for(byte b : doFinal) {
        	   builder.append(String.format("%02x", b));
        	   
           }
           System.out.println("密钥的长度:"+encoded.length);
           System.out.println("密钥的内容:"+keystring);
           
           System.out.println("加密的长度:"+doFinal.length);
           System.out.println("加密的内容:"+builder);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值