当前位置: 首页 > news >正文

免费的黄冈网站有哪些平台游戏软件/成人职业技术培训学校

免费的黄冈网站有哪些平台游戏软件,成人职业技术培训学校,文章类网站模板,重庆在建工程信息查询目录 一、编码算法 1. 常见编码 2. URL编码 3. Base64编码 4. 小结 二、哈希算法 1. 哈希碰撞 2. 常用哈希算法 MD5算法 SHA-1算法 自定义HashTools工具类 3. 哈希算法的用途 校验下载文件 存储用户密码 4. 小结 三、Hmac算法 小结: 四、对称加密…

目录

一、编码算法

1. 常见编码

2. URL编码

3. Base64编码 

4. 小结

二、哈希算法

1. 哈希碰撞

2. 常用哈希算法

MD5算法

SHA-1算法 

自定义HashTools工具类

3. 哈希算法的用途

校验下载文件

 存储用户密码

4. 小结

三、Hmac算法

小结:

四、对称加密算法

1. 使用AES加密

ECB模式


一、编码算法

ASCII码就是一种编码,字母A的编码是十六进制的0x41,字母B是0x42,以此类推:

字母

ASCII编码

A

0x41

B

0x42

C

0x43

D

0x44

因为ASCII编码最多只能有127个字符,要想对更多的文字进行编码,就需要用占用2个字节的Unicode或者3个字节的UTF-8。例如:中文的"中"字使用Unicode编码就是0x4e2d,UTF-8编码是0xe4b8ad。

汉字

Unicode编码

UTF-8编码

0x4e2d

0xe4b8ad

0x6587

0xe69687

0x7f16

0xe7bc96

0x7801

0xe7a081

因此,最简单的编码是直接给每个字符指定一个若干字节表示的整数,复杂一点的编码就需要根据一个已有的编码推算出来。

1. 常见编码

ASCII码:ASCII码中只存储英文字符,有127个字符,占一个字节

Unicode码:可以存储中文,占两个字节

UTF-8:实际上是从Unicode码中推算出来的一种编码方式

URL编码是浏览器发送数据时的一种编码,通常附加在URL的参数部分。之所以需要,是因为很多服务器只能识别ASCII字符,对字符进行编码,URL它独有一套自己的编码规则。在java的类库中提供了URLEncoder类,来对任意字符串进行URL编码。

如果服务器收到URL编码,会对它自动进行解码

Base64编码:对二进制数据进行编码,转换成文本格式,这样在很多文本中就可以处理进制数据。
Base64编明是种编码算法。不是加密算法。

2. URL编码

URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分,例如:

https://www.baidu.com/s?wd=%E4%B8%AD%E6%96%87

之所以需要URL编码,是因为出于兼容性考虑,很多服务器只识别ASCII字符。但如果URL中包含中文、日文这些非ASCII字符怎么办?不要紧,URL编码有一套规则:

  • 如果字符是A~Z,a~z,0~9以及-、_、.、*,则保持不变;
  • 如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。

例如:字符"中"的UTF-8编码是0xe4b8ad,因此,它的URL编码是%E4%B8%AD。URL编码总是大写。
Java标准库提供了一个URLEncoder类来对任意字符串进行URL编码:

//URLEncoder,url编码操作
//URLDecoder类,url解码操作
public class Demo01 {public static void main(String[] args) throws UnsupportedEncodingException {// 编码String keyWorld = "中文";String encodeString = URLEncoder.encode(keyWorld, "utf-8");System.out.println("编码:" + encodeString);//编码:%E4%B8%AD%E6%96%87}
}

如果服务器收到URL编码的字符串,就可以对其进行解码,还原成原始字符串。Java标准库的URLDecoder就可以解码:

// 解码String decodeString = URLDecoder.decode(encodeString, "utf-8");System.out.println(decodeString);//中文

要特别注意:URL编码是编码算法,不是加密算法。URL编码的目的是把任意文本数据编码为%前缀表示的文本,编码后的文本仅包含A~Z,a~z,0~9,-,_,.,*和%,便于浏览器和服务器处理。

//URL编码注意:
public class Demo02 {public static void main(String[] args) throws UnsupportedEncodingException {//编码只对中文内容进行处理  String keyWorld = "特斯拉";String encodeString = URLEncoder.encode(keyWorld, "utf-8");String urlString = "https://www.baidu.com/s?wd=";System.out.println(urlString + encodeString);//https://www.baidu.com/s?wd=%E7%89%B9%E6%96%AF%E6%8B%89//解码操作,url可以对整个链接进行解码String decodeString = URLDecoder.decode(urlString + encodeString, "utf-8");System.out.println(decodeString);//https://www.baidu.com/s?wd=特斯拉}
}

3. 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分别用字符+和/表示。

        举个例子:3个byte数据分别是e4、b8、ad,按6bit分组得到十六进制39、0b、22和2d,分别对应十进制57、11、34、45,通过索引计算结果为5Lit4

在Java中,二进制数据就是byte[]数组。Java标准库提供了Base64来对byte[]数组进行编解码:

//Base64编码
//3字节信息一组,24-6位 4字符
public class Demo03 {public static void main(String[] args) {String string = "中";byte[] bytes = string.getBytes();// JDK1.8后才提供String encodeString = Base64.getEncoder().encodeToString(bytes);System.out.println(encodeString);// 5Lit// 解码byte[] decodeBytes = Base64.getDecoder().decode(encodeString);System.out.println(Arrays.toString(decodeBytes));// [-28, -72, -83]System.out.println(new String(decodeBytes));// 中}
}

将图片使用base64转成字符串并保存到a.txt中:

//将图片使用base64转成字符串并保存到a.txt中
//将a.txt中的信息使用base64解码,还原成图片写出
public class Demo04 {public static void main(String[] args) throws IOException {// 将一个图片进行编码,文件进行保存byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\张柯堂\\Desktop\\头像.png"));String str = Base64.getEncoder().encodeToString(bytes);Files.write(Paths.get("a.txt"), str.getBytes());System.out.println("写出图片字符信息结束");// 解码// 读入信息byte[] readBytes = Files.readAllBytes(Paths.get("a.txt"));byte[] decodeBytes = Base64.getDecoder().decode(readBytes);Files.write(Paths.get("C:\\Users\\张柯堂\\Desktop\\copy.png"), decodeBytes);System.out.println("写出图片结束");}
}

因为标准的Base64编码会出现+、/和=,所以不适合把Base64编码后的字符串放到URL中。一种针对URL的Base64编码可以在URL中使用的Base64编码,它仅仅是把+变成-,/变成_:

public class Demo05 {public static void main(String[] args) {//+ ///	原始字节内byte[] input = new byte[] {2,-114,127,0};//使用两种编码方式对input转换/-->_ +-->-String str = Base64.getEncoder().encodeToString(input);String str1 = Base64.getUrlEncoder().encodeToString(input);System.out.println(str);//Ao5/AA==System.out.println(str1);//Ao5_AA==//解码操作byte[] byte1 =Base64.getDecoder().decode(str);byte[] byte2 =Base64.getUrlDecoder().decode(str1);//输出解码后的内容System.out.println(Arrays.toString(byte1));//[2, -114, 127, 0]System.out.println(Arrays.toString(byte2));//[2, -114, 127, 0]}
}

4. 小结

  • URL编码和Base64编码都是编码算法,它们不是加密算法;
  • URL编码的目的是把任意文本数据编码为%前缀表示的文本,便于浏览器和服务器处理;
  • Base64编码的目的是把任意二进制数据编码为文本,但编码后数据量会增加1/3。

二、哈希算法

哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法最重要的特点就是:

  • 相同的输入一定得到相同的输出;
  • 不同的输入大概率得到不同的输出。

所以,哈希算法的目的:为了验证原始数据是否被篡改。

两个相同的字符串永远会计算出相同的hashCode,否则基于hashCode定位的HashMap就无法正常工作。这也是为什么当我们自定义一个class时,覆写equals()方法时我们必须正确覆写hashCode()方法。

1. 哈希碰撞

哈希碰撞是指:两个不同的输入得到了相同的输出。

碰撞能不能避免?答案是不能。碰撞是一定会出现的,因为输出的字节长度是固定的,String的hashCode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。
碰撞不可怕,我们担心的不是碰撞,而是碰撞的概率,因为碰撞概率的高低关系到哈希算法的安全性。一个安全的哈希算法必须满足:

  • 碰撞概率低;
  • 不能猜测输出。

不能猜测输出是指:输入的任意一个bit的变化会造成输出完全不同,这样就很难从输出反推输入(只能依靠暴力穷举)。

2. 常用哈希算法

哈希算法,根据碰撞概率,哈希算法的输出长度越长,就越难产生碰撞,也就越安全。

常用的哈希算法有:

算法

输出长度(位)

输出长度(字节)

MD5

128 bits

16 bytes

SHA-1

160 bits

20 bytes

RipeMD-160

160 bits

20 bytes

SHA-256

256 bits

32 bytes

SHA-512

512 bits

64 bytes

MD5算法

Java标准库提供了常用的哈希算法,通过统一的接口进行调用。 以MD5算法为例,看看如何对输入内容计算哈希:
public class Demo01 {public static void main(String[] args) throws NoSuchAlgorithmException {//获取消息摘要对象MessageDigest md = MessageDigest.getInstance("MD5");//1.使用Md5进行消息加密
//		byte[]str ="还想继续考研".getBytes();
//		byte[]b=md.digest(str);
//		System.out.println("加密前的信息:"+Arrays.toString(str));//加密前的信息:[-24, -65, -104, -26, -125, -77, -25, -69, -89, -25, -69, -83, -24, -128, -125, -25, -96, -108]
//		System.out.println("加密后的信息:"+Arrays.toString(b));//加密后的信息:[-119, -28, -47, 120, 114, -79, 7, -1, 59, -98, -69, 65, -37, -111, -87, -120]
//		System.out.println("加密信息的长度:"+b.length);//加密信息的长度:16//		// 2.大量的数据进行加密md.update("还是想考研".getBytes());md.update("zkt".getBytes());md.update("c罗".getBytes());//3.加密byte[] result = md.digest();System.out.println("加密后的信息"+Arrays.toString(result));//加密后的信息[-52, 50, -102, -69, -95, 11, -59, -6, 68, -125, 74, -45, 6, 26, 108, 75]System.out.println("加密信息的长度"+result.length);//加密信息的长度16System.out.println("转16进制的字符串"+byteToString(result));//转16进制的字符串cc329abba10bc5fa44834ad3061a6c4b}public static String byteToString(byte[] b) {StringBuilder sb = new StringBuilder();for (byte c : b) {// 1.将10字节数字转成16进制的字符串sb.append(String.format("%02x", c));}return sb.toString();}
}

使用MessageDigest时,我们首先根据哈希算法获取一个MessageDigest实例,然后,反复调用update(byte[])输入数据。当输入结束后,调用digest()方法获得byte[]数组表示的摘要,最后,把它转换为十六进制的字符串。


使用MD5算法来对图片进行加密

//使用MD5算法来对图片进行加密
public class Demo02 {public static void main(String[] args) throws IOException, NoSuchAlgorithmException {byte[] image =Files.readAllBytes(Paths.get("C:\\Users\\张柯堂\\Desktop\\头像.png"));//获取消息摘要对象MessageDigest md5 = MessageDigest.getInstance("MD5");//加密byte[] bytes = md5.digest(image);System.out.println(Demo01.byteToString(bytes));//21f50de91db2ce9a80ccfd2f916d13a0}
}

SHA-1算法 

SHA-1也是一种哈希算法,它的输出是160 bits,即20字节。SHA-1是由美国国家安全局开发的,SHA算法实际上是一个系列,包括SHA-0(已废弃)、SHA-1、SHA-256、SHA-512等。
在Java中使用SHA-1,和MD5完全一样,只需要把算法名称改为"SHA-1":

public class Demo05 {public static void main(String[] args) throws NoSuchAlgorithmException {// 1.需要加密的信息byte[] passwold = "123456".getBytes();// 2.创建信息摘要对象MessageDigest sha_1 = MessageDigest.getInstance("SHA-1");// 3.update()sha_1.update(passwold);// 4.加密--16进制的字符串byte[] result = sha_1.digest();System.out.println("加密后的信息:" + Arrays.toString(result));System.out.println("加密后的长度:" + result.length);System.out.println(Demo01.byteToString(result));}}

自定义HashTools工具类

HashTools类:

public class HashTools {//创建消息摘要对象作为静态变量private static MessageDigest mesDig;//md5加密算法加密信息public static String messageMd5(byte[] bytes) throws NoSuchAlgorithmException {mesDig = MessageDigest.getInstance("MD5");return handle(bytes);}//sha-1加密算法加密信息public static String messageSha_1(byte[] bytes) throws NoSuchAlgorithmException {mesDig = MessageDigest.getInstance("SHA-1");return handle(bytes);}//进行加密操作public static String handle(byte[] bytes) {mesDig.update(bytes);byte[] result = mesDig.digest();return byteToString(result);}//将字节数组转16进制的字符串public static String byteToString(byte[] b) {StringBuilder sb = new StringBuilder();for (byte c : b) {// 1.将10字节数字转成16进制的字符串//2.追加到StringBuilder类中sb.append(String.format("%02x", c));}return sb.toString();}//str是个16进制的字符串,每两个字符表示一个字节信息//将16进制的字符串转10进制的字节数组public static byte[] stringTobyte(String str) {byte[] result = new byte[str.length() / 2];for (int i = 0, j = 0; i < str.length(); i = i + 2, j++) {//int num = Integer.parseInt(str.substring(i, i + 2), 16);Byte num = Byte.parseByte(str.substring(i, i + 2), 16);result[j] = (byte)num;}return result;}
}
public class Demo06 {public static void main(String[] args) throws NoSuchAlgorithmException {byte[]  passWorldString = "123456".getBytes();//MD5String resultMd5=HashTools.messageMd5(passWorldString);//SHA-1String reulstSha1=HashTools.messageSha_1(passWorldString);System.out.println(resultMd5.length());//32System.out.println(reulstSha1.length());//40}}

3. 哈希算法的用途

校验下载文件

因为相同的输入永远会得到相同的输出,因此,如果输入被修改了,得到的输出就会不同。我们在网站上下载软件的时候,经常看到下载页显示的MD5哈希值: 如何判断下载到本地的软件是原始的、未经篡改的文件?我们只需要自己计算一下本地文件的哈希值,再与官网公开的哈希值对比,如果相同,说明文件下载正确,否则,说明文件已被篡改。

 存储用户密码

哈希算法的另一个重要用途是存储用户口令。如果直接将用户的原始口令存放到数据库中,会产生极大的安全风险:

  • 数据库管理员能够看到用户明文口令;
  • 数据库数据一旦泄漏,黑客即可获取用户明文口令。

username

password

bob

123456789

alice

sdfsdfsdf

tim

justdoit

不存储用户的原始口令,那么如何对用户进行认证?方法是存储用户口令的哈希,例如,MD5。在用户输入原始口令后,系统计算用户输入的原始口令的MD5并与数据库存储的MD5对比,如果一致,说明口令正确,否则,口令错误。
因此,数据库存储用户名和口令的表内容应该像下面这样:

username

password

bob

25f9e794323b453885f5181f1b624d0b

alice

73a90acaae2b1ccc0e969709665bc62f

tim

19f9f30bd097d4c066d758fb01b75032

这样一来,数据库管理员看不到用户的原始口令。即使数据库泄漏,黑客也无法拿到用户的原始口令。想要拿到用户的原始口令,必须用暴力穷举的方法,一个口令一个口令地试,直到某个口令计算的MD5恰好等于指定值。
使用哈希口令时,还要注意防止彩虹表攻击。
什么是彩虹表呢?上面讲到了,如果只拿到MD5,从MD5反推明文口令,只能使用暴力穷举的方法。然而黑客并不笨,暴力穷举会消耗大量的算力和时间。但是,如果有一个预先计算好的常用口令和它们的MD5的对照表,这个表就是彩虹表。如果用户使用了常用口令,黑客从MD5一下就能反查到原始口令:

常用口令

MD5

hello123

f30aa7a662c728b7407c54ae6bfd27d1

12345678

25d55ad283aa400af464c76d713c07ad

passw0rd

bed128365216c019988915ed3add75fb

19700101

570da6d5277a646f6552b8832012f5dc

wbjxxmy

11d7a82f45f6a176fd9d5c100ccab40a

这就是为什么不要使用常用密码,以及不要使用生日作为密码的原因。
当然,我们也可以采取特殊措施来抵御彩虹表攻击:对每个口令额外添加随机数,这个方法称之为加盐(salt):
digest = md5(salt + inputPassword)

经过加盐处理的数据库表,内容如下:

username

salt

password

bob

H1r0a

a5022319ff4c56955e22a74abcc2c210

alice

7$p2w

e5de688c99e961ed6e560b972dab8b6a

tim

z5Sk9

1eee304b92dc0d105904e7ab58fd2f64

//通过随机盐值,低于彩虹表攻击
public class Demo03 {public static void main(String[] args) throws NoSuchAlgorithmException {byte[] passworld = "123456".getBytes();// 获取消息摘要对象MessageDigest md5 = MessageDigest.getInstance("MD5");// 原始密码信息添加进去md5.update(passworld);// 产生随机的盐值,并添加进去,进行加盐操作String uuidString = UUID.randomUUID().toString().substring(0, 6);md5.update(uuidString.getBytes());System.out.println(uuidString);//73242dbyte[] result = md5.digest();System.out.println("加密后的字节数组:" + Arrays.toString(result));//加密后的字节数组:[57, 38, 44, -69, -126, -103, 126, 24, 76, -101, -53, 105, 68, -84, -21, -104]System.out.println("加密后的字符串:" + Demo01.byteToString(result));//加密后的字符串:39262cbb82997e184c9bcb6944aceb98}
}

4. 小结

  • 哈希算法可用于验证数据完整性,具有防篡改检测的功能;
  • 常用的哈希算法有MD5、SHA-1等;
  • 用哈希存储口令时要考虑彩虹表攻击

三、Hmac算法

在前面讲到哈希算法时,我们说,存储用户的哈希口令时,要加盐存储,目的就在于抵御彩虹表攻击。我们回顾一下哈希算法:digest = hash(input)
正是因为相同的输入会产生相同的输出,我们加盐的目的就在于,使得输入有所变化:
digest = hash(salt + input)
这个salt可以看作是一个额外的“认证码”,同样的输入,不同的认证码,会产生不同的输出。因此,要验证输出的哈希,必须同时提供“认证码”。

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输出和原有的哈希算法长度一致。

可见,Hmac本质上就是把key混入摘要的算法。验证此哈希时,除了原始的输入数据,还要提供key。为了保证安全,我们不会自己指定key,而是通过Java标准库的KeyGenerator生成一个安全的随机的key。

//Hmac算法-链接md5
public class Demo06 {public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
//		1.通过名称HmacMD5获取KeyGenerator实例;KeyGenerator key = KeyGenerator.getInstance("HmacMD5");
//		2.通过KeyGenerator创建一个SecretKey实例;SecretKey secretKey = key.generateKey();System.out.println("密钥数组:"+Arrays.toString(secretKey.getEncoded()));System.out.println("密钥长度:"+secretKey.getEncoded().length);System.out.println("密钥字符串:"+HashTools.byteToString(secretKey.getEncoded()));//		3.通过名称HmacMD5获取Mac实例;Mac macMd5 = Mac.getInstance("HmacMD5");
//		4.用SecretKey初始化Mac实例;macMd5.init(secretKey);
//		5.对Mac实例反复调用update(byte[])输入数据;byte[] bytes = "hxjxky".getBytes();macMd5.update(bytes);
//		6.调用Mac实例的doFinal()获取最终的哈希值。byte[] result = macMd5.doFinal();System.out.println("密钥数组:"+Arrays.toString(result));System.out.println("密钥长度:"+result.length);System.out.println("密钥字符串:"+HashTools.byteToString(result));}
}运行结果:
密钥数组:[-36, -58, -62, -96, 52, -96, -28, -43, 29, -20, -73, 126, 110, -120, 26, -2, -16, -79, 111, 48, -111, 119, -104, -76, -71, -61, 48, 1, 88, 45, 85, -112, -21, -94, -19, -104, 17, 13, 34, 23, 79, 13, 4, 96, 32, -105, -108, -10, 121, -47, -85, 49, 8, -108, 22, 116, 39, -126, 17, 56, 15, -84, 114, -94]
密钥长度:64
密钥字符串:dcc6c2a034a0e4d51decb77e6e881afef0b16f30917798b4b9c33001582d5590eba2ed98110d22174f0d0460209794f679d1ab3108941674278211380fac72a2
密钥数组:[-111, -50, 96, 58, -120, -34, -57, -74, 113, 124, -113, -70, -91, 39, 126, 58]
密钥长度:16
密钥字符串:91ce603a88dec7b6717c8fbaa5277e3a

和MD5相比,使用HmacMD5的步骤是:

  1. 通过名称HmacMD5获取KeyGenerator实例;
  2. 通过KeyGenerator创建一个SecretKey实例;
  3. 通过名称HmacMD5获取Mac实例;
  4. 用SecretKey初始化Mac实例;
  5. 对Mac实例反复调用update(byte[])输入数据;
  6. 调用Mac实例的doFinal()获取最终的哈希值。

我们可以用Hmac算法取代原有的自定义的加盐算法,因此,存储用户名和口令的数据库结构如下:

username

secret_key (64 bytes)

password

bob

a8c06e05f92e...5e16

7e0387872a57c85ef6dddbaa12f376de

alice

e6a343693985...f4be

c1f929ac2552642b302e739bc0cdbaac

tim

f27a973dfdc0...6003

af57651c3a8a73303515804d4af43790

有了Hmac计算的哈希和SecretKey,我们想要验证怎么办?这时,SecretKey不能从KeyGenerator生成,而是从一个byte[]数组恢复:
//密钥数组:[53, 11, 1, 43, -63, -58, -22, -65, 99, 41, 78, 76, 99, -84, 99, 66, -115, 106, 28, -14, -52, 45, 32, 64, 29, 118, 18, 105, 28, 14, 26, 63, -84, -34, -41, 8, 116, -78, 13, 124, -16, 60, -64, -124, -2, -55, 25, -84, 104, -56, -84, 39, -68, -27, 13, 127, -117, -102, 31, 75, 42, 24, 37, -127]//密钥长度:64
//密钥字符串:350b012bc1c6eabf63294e4c63ac63428d6a1cf2cc2d20401d7612691c0e1a3facded70874b20d7cf03cc084fec919ac68c8ac27bce50d7f8b9a1f4b2a182581
//密钥数组:[-73, 87, 121, 49, 11, -15, 82, 65, -80, 124, -110, 73, -119, -28, -32, -42]
//密钥长度:16
//密钥字符串:b75779310bf15241b07c924989e4e0d6public class Demo07 {public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
//		byte[] keybytes = { 53, 11, 1, 43, -63, -58, -22, -65, 99, 41, 78, 76, 99, -84, 99, 66, -115, 106, 28, -14, -52,
//				45, 32, 64, 29, 118, 18, 105, 28, 14, 26, 63, -84, -34, -41, 8, 116, -78, 13, 124, -16, 60, -64, -124,
//				-2, -55, 25, -84, 104, -56, -84, 39, -68, -27, 13, 127, -117, -102, 31, 75, 42, 24, 37, -127 };String string = "350b012bc1c6eabf63294e4c63ac63428d6a1cf2cc2d20401d7612691c0e1a3facded70874b20d7cf03cc084fec919ac68c8ac27bce50d7f8b9a1f4b2a182581";byte[] keybytes = HashTools.stringTobyte(string);// 恢复密钥:参数1:密钥数组 参数2:算法方式SecretKey key = new SecretKeySpec(keybytes, "HmacMD5");Mac mac = Mac.getInstance("HmacMD5");mac.init(key);mac.update("hxjxky".getBytes());byte[] result = mac.doFinal();System.out.println(HashTools.byteToString(result));//b75779310bf15241b07c924989e4e0d6}
}

恢复SecretKey的语句就是new SecretKeySpec(keybytes, "HmacMD5")。

小结:

Hmac算法是一种标准的基于密钥的哈希算法,可以配合MD5、SHA-1等哈希算法,计算的摘要长度和原摘要算法长度相同。

四、对称加密算法

对称加密算法就是传统的用一个秘钥进行加密和解密。例如,我们常用的WinZIP和WinRAR对压缩包的加密和解密,就是使用对称加密算法:

l.jpg


从程序的角度看,所谓加密,就是这样一个函数,它接收密码和明文,然后输出密文:
secret = encrypt(key, message);

而解密则相反,它接收密码和密文,然后输出明文:
plain = decrypt(key, secret);


在软件开发中,常用的对称加密算法有:

算法

密钥长度

工作模式

填充模式

DES

56/64

ECB/CBC/PCBC/CTR/...

NoPadding/PKCS5Padding/...

AES

128/192/256

ECB/CBC/PCBC/CTR/...

NoPadding/PKCS5Padding/PKCS7Padding/...

IDEA

128

ECB

PKCS5Padding/PKCS7Padding/...

        密钥长度直接决定加密强度,而工作模式和填充模式可以看成是对称加密算法的参数和格式选择。Java标准库提供的算法实现并不包括所有的工作模式和所有填充模式。
        最后,值得注意的是,DES算法由于密钥过短,可以在短时间内被暴力破解,所以现在已经不安全了。

1. 使用AES加密

AES算法是目前应用最广泛的加密算法。比较常见的工作模式是ECB和CBC。

ECB模式

ECB模式是最简单的AES加密模式,它需要一个固定长度的密钥,固定的明文会生成固定的密文。
我们先用ECB模式加密并解密:

//AES+ECB
//1. 根据算法名称/工作模式/填充模式获取Cipher实例;
//2. 根据算法名称初始化一个SecretKey实例,密钥必须是指定长度;
//3. 使用SerectKey初始化Cipher实例,并设置加密或解密模式;
//4. 传入明文或密文,获得密文或明文。
public class Demo01 {public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {// 1.message keybyte[] key = "1234567890abcdef".getBytes();String message = "我本将心像明月";// 加密操作byte[] encodeByte = encodeMessage(key, message.getBytes());System.out.println("加密后的信息:" + HashTools.byteToString(encodeByte));// 解密操作byte[] decodeByte = decodeMessage(key, encodeByte);System.out.println("解密后的信息:" + new String(decodeByte));System.out.println("加密前的字节数组:" + Arrays.toString(message.getBytes()));System.out.println("解密后的信息字节数组:" + Arrays.toString(decodeByte));}public static byte[] encodeMessage(byte[] key, byte[] message) throws NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {// 1. 根据算法名称/工作模式/填充模式获取Cipher实例;Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 2. 根据算法名称初始化一个SecretKey实例,密钥必须是指定长度;SecretKey secretKey = new SecretKeySpec(key, "AES");// 3. 使用SerectKey初始化Cipher实例,并设置加密或解密模式;cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 4. 传入明文或密文,获得密文或明文。return cipher.doFinal(message);}public static byte[] decodeMessage(byte[] key, byte[] encodeMessage) throws NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {// 创建密码对象,需要传入算法/工作模式/填充模式Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 根据key的字节内容,"恢复"秘钥对象SecretKey keySpec = new SecretKeySpec(key, "AES");// 初始化秘钥:设置解密模式DECRYPT_MODEcipher.init(Cipher.DECRYPT_MODE, keySpec);// 根据原始内容(字节),进行解密+cipher.update(encodeMessage);byte[] result = cipher.doFinal();return result;}}

public class Demo02 {public static void main(String[] args) throws Exception {// 原文:String message = "我本将心像明月";System.out.println("Message(原始信息): " + message);// 128位密钥 = 16 bytes Key:byte[] key = "1234567890abcdef".getBytes();// 加密:byte[] data = message.getBytes();byte[] encrypted = encrypt(key, data);System.out.println("Encrypted(加密内容): " + Base64.getEncoder().encodeToString(encrypted));// 解密:byte[] decrypted = decrypt(key, encrypted);System.out.println("Decrypted(解密内容): " + new String(decrypted));}// 加密:public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {// 创建密码对象,需要传入算法/工作模式/填充模式Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 根据key的字节内容,"恢复"秘钥对象SecretKey keySpec = new SecretKeySpec(key, "AES");// 初始化秘钥:设置加密模式ENCRYPT_MODEcipher.init(Cipher.ENCRYPT_MODE, keySpec);// 根据原始内容(字节),进行加密return cipher.doFinal(input);}// 解密:public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {// 创建密码对象,需要传入算法/工作模式/填充模式Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 根据key的字节内容,"恢复"秘钥对象SecretKey keySpec = new SecretKeySpec(key, "AES");// 初始化秘钥:设置解密模式DECRYPT_MODEcipher.init(Cipher.DECRYPT_MODE, keySpec);// 根据原始内容(字节),进行解密return cipher.doFinal(input);}
}

Java标准库提供的对称加密接口非常简单,使用时按以下步骤编写代码:

  1. 根据算法名称/工作模式/填充模式获取Cipher实例;
  2. 根据算法名称初始化一个SecretKey实例,密钥必须是指定长度;
  3. 使用SerectKey初始化Cipher实例,并设置加密或解密模式;
  4. 传入明文或密文,获得密文或明文。

相关文章:

Java基础29(编码算法 哈希算法 MD5 SHA—1 HMac 算法 堆成加密算法)

目录 一、编码算法 1. 常见编码 2. URL编码 3. Base64编码 4. 小结 二、哈希算法 1. 哈希碰撞 2. 常用哈希算法 MD5算法 SHA-1算法 自定义HashTools工具类 3. 哈希算法的用途 校验下载文件 存储用户密码 4. 小结 三、Hmac算法 小结&#xff1a; 四、对称加密…...

人脸识别——OpenCV

人脸识别 创建窗口创建按钮设置字体定义标签用于显示图片选择并显示图片检测图片中的人脸退出程序返回主界面 创建窗口 导入tkinter库&#xff0c;创建窗口&#xff0c;设置窗口标题和窗口大小。 import tkinter as tkwin tk.Tk() win.title("人脸识别") win.geom…...

深入探索容器:什么是容器及其在现代软件开发中的作用

深入探索容器&#xff1a;什么是容器及其在现代软件开发中的作用 引言 在今天的软件开发和运维领域&#xff0c;容器技术已经成为了一个不可或缺的工具。从初创企业到大型企业&#xff0c;从Web应用到微服务架构&#xff0c;容器都在发挥着其独特的作用。那么&#xff0c;什么…...

STM32-- GPIO->EXTI->NVIC中断

一、NVIC简介 什么是 NVIC &#xff1f; NVIC 即嵌套向量中断控制器&#xff0c;全称 Nested vectored interrupt controller 。它 是内核的器件&#xff0c;所以它的更多描述可以看内核有关的资料。M3/M4/M7 内核都是支持 256 个中断&#xff0c;其中包含了 16 个系统中…...

【介绍下WebStorm开发插件】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

推荐丨一键申请SSL证书,让网站实现HTTPS访问!

申请HTTPS证书可以简化为以下几个直接步骤&#xff0c;以便您能快速理解和操作&#xff1a; 1. 确定证书类型&#xff1a; - 单域名证书&#xff1a;适用于一个特定域名。 - 通配符证书&#xff1a;适用于同一主域名下的所有子域名。 - 多域名证书&#xff1a;覆盖多个不同的域…...

交叉导轨在医疗设备上的作用!

随着医疗器械行业的需求逐步增长&#xff0c;交叉导轨给医疗器械行业带来了广阔的发展前景。作为重要的精密传动元件&#xff0c;交叉导轨具有寿命长、高精度、高刚性、高耐腐蚀性和高稳定性等优点&#xff0c;满足精密仪器上对产品的高要求使用场景。 在医疗设备领域中交叉导轨…...

【云原生】Docker Compose 使用详解

目录 一、前言 二、Docker Compose 介绍 2.1 Docker Compose概述 2.2 Docker Compose特点 2.3 Docker Compose使用场景 三、Docker Compose 搭建 3.1 安装docker环境 3.2 Docker Compose安装方式一 3.2.1 下载最新版/如果不是最新可替换最新版本 3.2.2 设置权限 3.2.…...

通过LabVIEW提升生产设备自动化水平

现代制造业对生产设备的自动化水平提出了越来越高的要求。使用LabVIEW这一强大的图形化编程环境&#xff0c;可以显著提升生产设备的自动化程度&#xff0c;改善生产效率和产品质量。本文将详细分析如何通过LabVIEW改善生产设备的自动化水平&#xff0c;并提供具体的实施策略与…...

面试题vue+uniapp(个人理解-面试口头答述)未编辑完整....

1.vue2和vue3的区别&#xff08;vue3与vue2的区别&#xff08;你不知道细节全在这&#xff09;_vue2和vue3区别-CSDN博客&#xff09;参考 Vue3 在组合式&#xff08;Composition &#xff09;API&#xff0c;中使用生命周期钩子时需要先引入&#xff0c;而 Vue2 在选项API&am…...

PPP-B2b精密产品使用注意事项及分析

1、因为在使用PPP-B2b进行定轨的时候&#xff0c;发的精密轨道产品是B3频点的&#xff0c;需要改正的卫星质心&#xff08;Com&#xff09;与SP3精密星历对比。 2、PPP-B2b产品吸收了电离层误差&#xff0c;因此电离层提取方面与IGS电离层完全无法对其。 3、由于PPP-B2b产品精…...

C语言(结构体)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…...

Python filter()用法:深入解析与实战应用

Python filter()用法&#xff1a;深入解析与实战应用 在Python编程中&#xff0c;filter() 函数是一个内置的高阶函数&#xff0c;它用于过滤序列&#xff0c;过滤掉不符合条件的元素&#xff0c;返回由符合条件元素组成的新列表。该函数在数据处理和筛选时非常有用&#xff0…...

k8s集群的存储卷、pvc和pv

目录 简介 简介 PV 全称叫做 Persistent Volume&#xff0c;持久化存储卷。它是用来描述或者说用来定义一个存储卷的&#xff0c;这个通常都是由运维工程师来定义。 PVC 的全称是 Persistent Volume Claim&#xff0c;是持久化存储的请求。它是用来描述希望使用什么样的或者说…...

二分搜索树深度优先遍历

二分搜索树深度优先遍历 二分搜索树&#xff08;Binary Search Tree&#xff0c;简称BST&#xff09;是一种特殊的二叉树&#xff0c;它具有以下特性&#xff1a;对于树中的任意节点&#xff0c;其左子树中的所有元素都小于该节点的值&#xff0c;其右子树中的所有元素都大于该…...

ImportError: cannot import name ‘packaging‘ from ‘pkg_resources‘‘

参考自: [Bug]: ImportError: cannot import name packaging from pkg_resources (/usr/local/lib/python3.10/dist-packages/pkg_resources/__init__.py) Issue #15863 AUTOMATIC1111/stable-diffusion-webui GitHub ImportError: cannot import name packaging from pkg…...

灯塔歌曲音乐下载官网

灯塔歌曲音乐下载官网网址&#xff1a;www.dengtamp3.com 灯塔音乐下载上线以“用心服务&#xff0c;认真负责”为核心价值。 我们的团队是一个青春的团队&#xff0c;朝气蓬勃。我们采用最新的服务模式&#xff0c;以网为媒为广大客户提供服务&#xff0c;我们坚持以“用心&a…...

数据结构的归并排序(c语言版)

一.归并排序的基本概念 1.基本概念 归并排序是一种高效的排序算法,它采用了分治的思想。它的基本过程如下: 将待排序的数组分割成两个子数组,直到子数组只有一个元素为止。然后将这些子数组两两归并,得到有序的子数组。不断重复第二步,直到最终得到有序的整个数组。 2.核心…...

ubuntu使用Docker笔记

一、参考资料 1、B站视频 尚硅谷Docker实战教程 2、有心人整理的笔记 Docker笔记&#xff08;周阳版&#xff09; 3、菜鸟教程 Docker 教程 以下是本人的折腾实践。 二、Docker的安装 2.1、使用清华源安装docker&#xff0c;清华源官方教程。 本人是在ubuntu20.04下安装的…...

PHP编程入门:揭开Web开发的神秘面纱

PHP编程入门&#xff1a;揭开Web开发的神秘面纱 在数字化时代&#xff0c;PHP作为一种广泛使用的服务器端脚本语言&#xff0c;为Web开发领域注入了强大的活力。无论你是编程新手还是有一定经验的开发者&#xff0c;掌握PHP编程都将为你开启一扇通往Web开发新世界的大门。接下…...

曲线拟合工具软件(免费)

曲线拟合是数据处理中经常用到的数值方法,本质是使用某一个模型(方程或者方程组)将一系列离散的数据拟合成平滑的曲线或者曲面,数值求解出对应的函数参数,大家可以利用MATLAB的曲线拟合工具箱也可以使用第三方的拟合软件,今天我们介绍Welsim免费的曲线拟合软件 1、MATLA…...

基于L1范数惩罚的稀疏正则化最小二乘心电信号降噪方法(Matlab R2021B)

L1范数正则化方法与Tikhonov正则化方法的最大差异在于采用L1范数正则化通常会得到一个稀疏向量&#xff0c;它的非零系数相对较少&#xff0c;而Tikhonov正则化方法的解通常具有所有的非零系数。即&#xff1a;L2范数正则化方法的解通常是非稀疏的&#xff0c;并且解的结果在一…...

Bitbucket的原理及应用详解(一)

本系列文章简介&#xff1a; 在数字化和全球化的今天&#xff0c;软件开发和项目管理已经成为企业成功的关键因素之一。随着团队规模的扩大和项目的复杂化&#xff0c;如何高效地协同开发、管理代码和确保代码质量成为了开发者和管理者面临的重要挑战。Bitbucket作为一款功能强…...

企业级win10电脑下同时存在Python3.11.7Python3.6.6,其中Python3.6.6是后装的【过程与踩坑复盘】

背景: 需要迁移原始服务器的上的Python3.6.6+Flask项目到一个新服务器上, 新服务器上本身存在一个Python3.11.7, 所以这涉及到了一个电脑需要装多个Python版本的问题 过程: 1-确定新电脑版本【比如是32还是64位】 前面开发人员存留了两个包,是python-3.6.6.exe和pytho…...

泛微开发修炼之旅--03常用数据表结构讲解

文章链接&#xff1a;泛微开发修炼之旅--03常用数据表结构讲解...

MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案

一、找不到my.ini配置文件 MySQL 8 安装或启动过程中&#xff0c;如果系统找不到my.ini文件&#xff0c;通常意味着 MySQL服务器没有找到其配置文件。在Windows系统上&#xff0c;MySQL 8 预期使用my.ini作为配置文件&#xff0c;而不是在某些情况下用到的my.cnf文件。 通过 …...

Android 13 亮度调节代码分析

frameworks\base\packages\SystemUI\res\layout\quick_settings_brightness_dialog.xml 进度条控件 <com.android.systemui.settings.brightness.BrightnessSliderViewxmlns:android"http://schemas.android.com/apk/res/android"android:id"id/brightness…...

基于小波变换和峰值搜索的光谱检测matlab仿真,带GUI界面

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于小波变换和峰值搜索的光谱检测matlab仿真,带GUI界面.对光谱数据的成分进行提取&#xff0c;分析CO2&#xff0c;SO2&#xff0c;CO以及CH4四种成分比例。 2.…...

【初识Objective-C】

Objective-C学习 什么是OCOC的特性OC跑的第一个程序helloworld OC的一些基础知识标识符OC关键字数据类型字符型c字符串为什么NSString类型定义时前面要加和普通的c对象有什么区别 一些基础知识if语句switch语句三种循坏语句for循环&#xff1a;用于固定次数的循环while循环&…...

从功能性磁共振成像(fMRI)数据重建音频

听觉是人类最重要的感官之一&#xff0c;它负责接收外部的听觉刺激&#xff0c;并将这些信息传递给大脑进行处理和理解。研究人员正致力于从神经科学和计算机科学两个领域探索人脑的听觉感知机制。一个关键目标是从人脑中解码神经信息&#xff0c;并重建原始的刺激。常见的大脑…...