加密与安全_探索常用编码算法

文章目录

  • 概述
  • 什么是编码
  • 编码分类
    • ASCII码 (最多只能有128个字符)
    • Unicode (用于表示世界上几乎所有的文字和符号)
    • URL编码 (解决服务器只能识别ASCII字符的问题)
      • 实现:编码_URLEncoder
      • 实现: 解码_URLDecoder
      • 小结
    • Base64编码
      • 实现:编码_Base64.getEncoder()
      • 实现:解码_Base64.getDecoder
      • byte[]数组长度不是3的整数倍
      • Base64.getUrlEncoder()
      • 小结
  • 总结

在这里插入图片描述


概述

在计算机系统中,加密与安全是至关重要的概念。

想象一下,当B想要发送一封邮件给A时,邮件可能在传送过程中遭到黑客的窃听,这就需要防止信息泄露。此外,黑客还可能篡改邮件内容,因此A需要确保她能够辨别出邮件是否被篡改。最后,黑客可能会冒充B发送虚假邮件给A,这需要A有能力辨别真伪

为了应对这些潜在的安全威胁,我们需要采取以下三项措施:

  1. 防止窃听
  2. 防止篡改
  3. 防止伪造

计算机加密技术旨在实现上述目标。现代计算机密码学建立在严格的数学理论基础上,并逐渐发展成为一门科学。对于大多数开发者来说,设计安全的加密算法是一项艰巨的任务,验证加密算法的安全性则更加困难。目前认为安全的加密算法也只是尚未被攻破。因此,为了编写安全的计算机程序,我们应遵循以下原则:

  1. 不要设计自己的加密算法
  2. 不要自行实现已有的加密算法
  3. 不要修改已有的加密算法

接下来,我们将一起探讨最常用的加密算法,以及Java实现。


什么是编码

编码是一种将符号、文字或其他数据转换为特定格式或标准的过程。

编码是计算机科学中的一个重要概念,它指的是将符号、文字或其他数据转换为特定格式或标准的过程。这种转换是为了方便存储、传输和处理数据。编码可以涵盖多种形式,包括数字编码、字符编码、图像编码、音频编码等。

数字编码是将数字转换为计算机可以理解的二进制形式的过程,通常涉及将十进制数字转换为二进制或其他进制的表示形式。

字符编码是将字符映射到数字或比特序列的过程,以便计算机能够处理和存储文本数据。常见的字符编码包括ASCII(美国信息交换标准代码)、Unicode等。

图像编码是将图像数据转换为计算机可识别的格式的过程,常见的图像编码包括JPEG、PNG、GIF等。

音频编码是将声音数据转换为数字形式的过程,以便计算机可以处理和存储音频数据。常见的音频编码包括MP3、AAC、WAV等。

通过编码,我们能够将各种类型的数据转换为计算机可以处理的形式,从而实现数据的存储、传输和处理。

在这里插入图片描述


编码分类

ASCII码 (最多只能有128个字符)

ASCII码(American Standard Code for Information Interchange,美国信息交换标准代码) 就是一种常见的字符编码标准。在ASCII码中,每个字符都被赋予一个唯一的数值表示,通常是一个字节(8位)。

例如,字母’A’的ASCII编码是十六进制的0x41,字母’B’是0x42,字母’C’是0x43,以此类推。ASCII码包含了标准的英文字母、数字、标点符号以及一些控制字符的编码,共计128个字符。

下面是一些常见字符的ASCII编码示例:

字符ASCII编码
A0x41
B0x42
C0x43
D0x44

字母’A’的ASCII编码为0x41,这是因为ASCII编码是一种固定长度的字符编码标准,用一个字节(8位)表示一个字符。在ASCII编码中,大写字母’A’的编码是65,换算成十六进制就是0x41。

ASCII编码是根据英语字母表中的顺序进行编码的,因此大写字母’A’在ASCII编码中是排在字母表的第一个位置,其对应的十进制数值为65,换算成十六进制即为0x41。

ASCII码对照表

二进制十进制十六进制字符/缩写解释
00000000000NUL (NULL)空字符
00000001101SOH标题开始
00000010202STX正文开始
00000011303ETX正文结束
00000100404EOT传输结束
00000101505ENQ请求
00000110606ACK回应/响应/收到通知
00000111707BEL响铃
00001000808BS退格
00001001909HT水平制表符
00001010100ALF/NL换行键
00001011110BVT垂直制表符
00001100120CFF/NP换页键
00001101130DCR回车键
00001110140ESO不用切换
00001111150FSI启用切换
000100001610DLE数据链路转义
000100011711DC1/XON设备控制1/传输开始
000100101812DC2设备控制2
000100111913DC3/XOFF设备控制3/传输中断
000101002014DC4设备控制4
000101012115NAK无响应/非正常响应/拒绝接收
000101102216SYN同步空闲
000101112317ETB传输块结束/块传输终止
000110002418CAN取消
000110012519EM已到介质末端/介质存储已满/介质中断
00011010261ASUB替补/替换
00011011271BESC逃离/取消
00011100281CFS文件分割符
00011101291DGS组分隔符/分组符
00011110301ERS记录分离符
00011111311FUS单元分隔符
001000003220(Space)空格
001000013321!
001000103422"
001000113523#
001001003624$
001001013725%
001001103826&
001001113927
001010004028(
001010014129)
00101010422A*
00101011432B+
00101100442C,
00101101452D-
00101110462E.
00101111472F/
0011000048300
0011000149311
0011001050322
0011001151333
0011010052344
0011010153355
0011011054366
0011011155377
0011100056388
0011100157399
00111010583A:
00111011593B;
00111100603C<
00111101613D=
00111110623E>
00111111633F?
010000006440@
010000016541A
010000106642B
010000116743C
010001006844D
010001016945E
010001107046F
010001117147G
010010007248H
010010017349I
01001010744AJ
01001011754BK
01001100764CL
01001101774DM
01001110784EN
01001111794FO
010100008050P
010100018151Q
010100108252R
010100118353S
010101008454T
010101018555U
010101108656V
010101118757W
010110008858X
010110018959Y
01011010905AZ
01011011915B[
01011100925C\
01011101935D]
01011110945E^
01011111955F_
011000009660`
011000019761a
011000109862b
011000119963c
0110010010064d
0110010110165e
0110011010266f
0110011110367g
0110100010468h
0110100110569i
011010101066Aj
011010111076Bk
011011001086Cl
011011011096Dm
011011101106En
011011111116Fo
0111000011270p
0111000111371q
0111001011472r
0111001111573s
0111010011674t
0111010111775u
0111011011876v
0111011111977w
0111100012078x
0111100112179y
011110101227Az
011110111237B{
011111001247C|
011111011257D}
011111101267E~
011111111277FDEL删除

Unicode (用于表示世界上几乎所有的文字和符号)

Unicode是一种广泛使用的字符编码标准,用于表示世界上几乎所有的文字和符号相比于ASCII编码的128个字符,Unicode可以表示更多的字符,包括中文、日文、阿拉伯文等。

中文的Unicode编码示例如下:

汉字Unicode编码UTF-8编码
0x4e2d0xe4b8ad
0x65870xe69687
0x7f160xe7bc96
0x78010xe7a081

另外,UTF-8是一种变长编码,用于将Unicode字符编码成字节序列。对于英文字符,UTF-8使用一个字节表示,而对于中文等Unicode字符,则需要多个字节来表示。例如,汉字’中’的UTF-8编码是0xe4b8ad,它需要3个字节来表示

UTF-8编码的复杂性在于它是一种不定长编码,字符的编码长度取决于Unicode编码的范围。但是,通过给定字符的Unicode编码,可以推算出它在UTF-8编码中所占用的字节数。


URL编码 (解决服务器只能识别ASCII字符的问题)

URL编码是一种用于在URL中传输数据时使用的编码方式。它通常被用于对URL的参数部分进行编码,以确保传输的数据符合URL的规范。举例来说:

如果我们想在URL中传输非ASCII字符,比如中文或日文等,由于许多服务器只能识别ASCII字符,因此我们需要对这些非ASCII字符进行编码。URL编码就是为了解决这个问题而设计的

URL编码的规则如下:

  • 对于A~Z、a~z、0~9以及-、_、.、*这些字符,保持不变;
  • 对于其他字符,首先转换为其对应的UTF-8编码,然后将每个字节表示为%XX的形式。
  • URL编码总是使用大写字母表示

举例来说,如果字符中的UTF-8编码是0xe4b8ad,那么它的URL编码就是%E4%B8%AD

举个例子

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

在这里插入图片描述
其实就是 https://www.artisan.com/s?wd=中文

实现:编码_URLEncoder

package com.artisan.securityalgjava.urlencode;import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class UrlEncoderTest {public static void main(String[] args) throws UnsupportedEncodingException {// 编码String result = URLEncoder.encode("中文!", StandardCharsets.UTF_8.toString());System.out.println(result);}
}

在这里插入图片描述

的URL编码是%E4%B8%AD的URL编码是%E6%96%87!虽然是ASCII字符,也要对其编码为%21

和标准的URL编码稍有不同,URLEncoder把空格字符编码成+,而现在的URL编码标准要求空格被编码为%20, 服务器都可以处理这两种情况


实现: 解码_URLDecoder

URL编码的字符串对其进行解码还原成原始字符串

// 解码
String decode = URLDecoder.decode("%E4%B8%AD%E6%96%87%21", StandardCharsets.UTF_8.toString());
System.out.println(decode);

在这里插入图片描述

小结

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


Base64编码

Base64 编码是一种将二进制数据编码为文本格式的方法,它可以将任意长度的二进制数据转换为纯文本,并且只包含一组特定的字符集,包括 A~Z、a~z、0~9、+、/、=

Base64 编码的原理是将 3 字节的二进制数据按照 6 位一组进行分组,然后将每组 6 位的二进制数转换为对应的整数,再根据整数对应的索引查表,将索引对应的字符拼接起来,得到编码后的字符串。

具体步骤如下:

  1. 将原始二进制数据每 3 个字节分为一组。
  2. 将每组 3 个字节转换为 4 个 6 位的二进制数。
  3. 将每个 6 位的二进制数转换为对应的整数。
  4. 将每个整数使用查表的方式映射到对应的字符集合中的字符。
  5. 将得到的字符拼接成一个字符串作为 Base64 编码结果。

由于 Base64 编码的特性,它常用于在网络上传输数据,例如在电子邮件中传输二进制文件或在网页中嵌入图片等。由于其将二进制数据编码为文本的特点,使得它可以直接作为文本传输,而无需担心编码后的数据会包含特殊字符或控制字符。

举个例子:3个byte数据分别是e4、b8、ad,按 6 bit分组得到39、0b、22、2d

在这里插入图片描述

6位整数的范围总是0~63,所以,能用64个字符表示:字符A~Z对应索引0~25,字符a~z对应索引26~51,字符0~9对应索引52~61,最后两个索引62、63分别用字符+/表示


实现:编码_Base64.getEncoder()

package com.artisan.securityalgjava.base64;import java.util.Arrays;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class Base64Test {public static void main(String[] args) {// 创建一个包含中文字符 "中" 的字节数组byte[] bytes = {(byte) 0xe4, (byte) 0xb8, (byte) 0xad};// 使用 Base64 编码器将字节数组转换为 Base64 字符串String result = Base64.getEncoder().encodeToString(bytes);System.out.println(result);}
}

在这里插入图片描述


实现:解码_Base64.getDecoder

package com.artisan.securityalgjava.base64;import java.util.Arrays;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class Base64Test {public static void main(String[] args) {// 创建一个包含中文字符 "中" 的字节数组byte[] bytes = {(byte) 0xe4, (byte) 0xb8, (byte) 0xad};// 使用 Base64 编码器将字节数组转换为 Base64 字符串String result = Base64.getEncoder().encodeToString(bytes);System.out.println(result);// 使用 Base64 解码器将 Base64 字符串解码为字节数组byte[] decode = Base64.getDecoder().decode(result);System.out.println(Arrays.toString(decode));}
}

将包含中文字符 “中” 的字节数组进行 Base64 编码,然后再解码回原始字节数组,并打印结果。


byte[]数组长度不是3的整数倍

如果输入的byte[]数组长度不是3的整数倍真么办?这种情况下,需要对输入的末尾补一个或两个0x00,编码后,在结尾加一个=表示补充了1个0x00,加两个=表示补充了2个0x00,解码的时候,去掉末尾补充的一个或两个0x00即可

实际上,因为编码后的长度加上=总是4的倍数,所以即使不加=也可以计算出原始输入的byte[]

看代码

import java.util.Arrays;
import java.util.Base64;public class Base64Test {// 定义一个静态方法用于测试 Base64 编码和解码static void testCase() {// 输入的字节数组,包含一个中文字符和一个 ASCII 字符byte[] input = new byte[] { (byte) 0xe4, (byte) 0xb8, (byte) 0xad, 0x21 };// 使用 Base64 编码器将字节数组转换为 Base64 字符串String b64encoded = Base64.getEncoder().encodeToString(input);// 使用 Base64 编码器进行无填充的 Base64 编码String b64encoded2 = Base64.getEncoder().withoutPadding().encodeToString(input);// 打印两种编码结果System.out.println("Base64 编码结果1: " + b64encoded);System.out.println("Base64 编码结果2: " + b64encoded2);// 使用 Base64 解码器将 Base64 字符串解码为字节数组byte[] output = Base64.getDecoder().decode(b64encoded2);// 打印解码后的字节数组System.out.println("解码后的字节数组: " + Arrays.toString(output));}public static void main(String[] args) {// 调用测试方法testCase();}
}

在这里插入图片描述


Base64.getUrlEncoder()

标准的 Base64 编码在某些场景下不适合在 URL 中使用,因为它会包含字符 +/=,而这些字符在 URL 中可能会引起解析错误或歧义。

为了解决这个问题,可以使用一种针对 URL 的 Base64 编码,它对标准的 Base64 编码做了简单的修改,即将 + 替换为 -,将 / 替换为 _,从而避免了在 URL 中可能引起问题的字符。

这种修改后的 Base64 编码仍然可以通过标准的 Base64 解码器进行解码,因为这两种编码方式只是字符替换的差异,不影响原始数据的编码规则和解码逻辑。

static void urlEncoder() {// 创建一个字节数组作为输入数据byte[] input = new byte[]{0x01, 0x02, 0x7f, 0x00};// 使用 URL 安全的 Base64 编码器将字节数组转换为 Base64 字符串String result = Base64.getUrlEncoder().encodeToString(input);System.out.println("URL 编码结果: " + result);// 使用 URL 安全的 Base64 解码器将 Base64 字符串解码为字节数组byte[] decode = Base64.getUrlDecoder().decode(result);System.out.println("解码后的字节数组: " + Arrays.toString(decode));
}

演示了如何使用 URL 安全的 Base64 编码器将字节数组进行编码,以及如何使用相应的解码器将编码后的 Base64 字符串解码回原始的字节数组。URL 安全的 Base64 编码会将 + 替换为 -,将 / 替换为 _,以避免在 URL 中可能引起问题的字符。

0x01, 0x02, 0x7f, 0x00 是十六进制表示法,表示了四个字节的值。在 Java 中,0x 前缀表示后面的数字是十六进制数。

  • 0x01 表示十进制数值为 1
  • 0x02 表示十进制数值为 2
  • 0x7f 表示十进制数值为 127
  • 0x00 表示十进制数值为 0

因此,input 这个字节数组包含了四个字节,分别是 1、2、127 和 0。

在这里插入图片描述


小结

Base64 编码是一种常用的将二进制数据转换为文本数据的方法,适用于需要在文本环境中传输二进制数据的场景,比如电子邮件、XML 数据传输等。

然而, Base64 编码会将原始数据的长度增加约 1/3,这会降低传输效率。因此,在一些对传输效率要求较高的场景下,可能会选择其他更高效的编码方式,比如 Base32、Base48 或 Base58 编码。这些编码方式可以根据实际需求选择字符集合的大小,以权衡编码效率和字符集合大小之间的关系。不过,无论是哪种编码方式,它们都是一种编码算法,而不是加密算法,因为它们不会对数据进行加密,只是将数据转换成不同的形式。


总结

  • URL 编码是一种编码算法,其目的是将任意文本数据编码为 % 前缀表示的文本形式,以便在网络中传输,特别是用于浏览器和服务器之间的通信,以处理一些特殊字符或者非 ASCII 字符。

  • Base64 编码同样是一种编码算法,它将任意二进制数据编码为文本形式,方便在文本环境中传输,但编码后的数据量会增加原始数据的约 1/3。这种编码在很多场景中使用,比如电子邮件、XML 数据传输等,以便在文本协议中传输二进制数据。

虽然它们都是编码算法而不是加密算法,但它们在不同的场景中有着不同的用途和目的。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2815660.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Python3中真真假假True、False、None等含义详解

在Python中&#xff0c;不仅仅和类C一样的真假类似&#xff0c;比如1代表真&#xff0c;0代表假。Python中的真假有着更加广阔的含义范围&#xff0c;Python会把所有的空数据结构视为假&#xff0c;比如 [] (空列表)、 {} &#xff08;空集合&#xff09;、 &#xff08;空字符…

机器学习专项课程03:Unsupervised Learning, Recommenders, Reinforcement Learning笔记 Week01

Week 01 of Unsupervised Learning, Recommenders, Reinforcement Learning 本笔记包含字幕&#xff0c;quiz的答案以及作业的代码&#xff0c;仅供个人学习使用&#xff0c;如有侵权&#xff0c;请联系删除。 课程地址&#xff1a; https://www.coursera.org/learn/unsupervi…

精读《使用 css 变量生成颜色主题》

作者&#xff1a;五灵 本周工作中遇到类似颜色主题的问题&#xff0c;在查资料的时候&#xff0c;看到这个视频&#xff0c;觉得讲得很清楚&#xff0c;而且趣味性丰富&#xff0c;所以想拿出来讲讲这个很有意思的主题。 视频链接&#xff1a; CSSconf EU 2018 | Dag-Inge Aas…

STM32标准库——(12)USART串口协议

1.全双工、半双工及单工通讯 2.同步与异步通讯 在同步通讯中&#xff0c;收发设备双方会使用一根信号线表示时钟信号&#xff0c;在时钟信号的驱动下双方进行协调&#xff0c; 同步数据&#xff0c;见图 同步通讯。 通讯中通常双方会统一规定在时钟信号的上升沿或下降沿对数据线…

循环结构:for循环,while循环,do-while,死循环

文章目录 for循环for案例&#xff1a;累加for循环在开发中的常见应用场景 whilewhile循环案例&#xff1a; for和while的区别&#xff1a;do-while三种循环的区别小结死循环 快捷键 ctrlaltt for循环 看循环执行多少次&#xff0c;就看有效数字有几个 快捷键 fori 示例代码&am…

11.以太网交换机工作原理

目录 一、以太网协议二、以太网交换机原理三、交换机常见问题思考四、同网段数据通信全过程五、跨网段数据通信全过程六、关键知识七、调试命令 前言&#xff1a;在网络中传输数据时需要遵循一些标准&#xff0c;以太网协议定义了数据帧在以太网上的传输标准&#xff0c;了解以…

java多线程编程(学习笔记)入门

一、多线程创建的三种方式 (1)通过继承Thread本身 (2)通过实现runnable接口 (3)通过 Callable 和 Future 创建线程 其中&#xff0c;前两种不能获取到编程的结果&#xff0c;第三种能获取到结果 二、常见的成员方法 方法名称说明String getName()返回此线程的名称void setNam…

练习 2 Web [ACTF2020 新生赛]BackupFile 1

[ACTF2020 新生赛]BackupFile 1 Web常规题目 首先尝试查找常见的前端页面index.php之类的&#xff0c;没找到 题目有个“BackupFile”——备份文件 尝试用工具遍历查找相关的文件 御剑没扫出来&#xff0c;搜索搭建好dirsearch后&#xff0c;扫出来的index.php.bak 扫描工…

DolphinScheduler——介绍及架构设计

目录 一、DolphinScheduler介绍 1.1 概述 1.2 特性 1.2.1 简单易用 1.2.2 丰富的使用场景 1.2.3 High Reliability 1.2.4 High Scalability 1.3 名词解释 1.3.1 名词解释 1.3.2 模块介绍 二、DolphinScheduler架构原理 2.1 系统架构图 2.2 架构说明 2.2.1 Maste…

D3D渲染画面扭曲

今天在项目中渲染出来的画面始终不对&#xff0c;工具PIX显示图元类型输出是对的&#xff0c;但是就是渲染画面不对&#xff0c;顶点着色器的输出就奇形怪状&#xff0c;查了一条才发现是观察投影矩阵的问题。 如果你也是看的D3D龙书&#xff0c;那么在不跟着书上打完代码就直接…

云原生架构技术揭秘:探索容器技术的奥秘

云原生的概念和演进都是围绕云计算的核心价值展开的&#xff0c;比如弹性、自动化、韧性&#xff0c;所以云原生所涵盖的技术领域非常丰富。 随着云计算技术的不断发展&#xff0c;云原生架构已经成为了新一代软件开发的重要趋势。本文将为您介绍云原生架构的相关技术&#xf…

蓝桥杯第十二届电子类单片机组程序设计

目录 前言 蓝桥杯大赛历届真题_蓝桥杯 - 蓝桥云课&#xff08;点击查看&#xff09; 单片机资源数据包_2023&#xff08;点击下载&#xff09; 一、第十二届比赛原题 1.比赛题目 2.题目解读 蓝桥杯第十四届电子类单片机组程序设计_蓝桥杯单片机哪一届最难-CSDN博客 二、…

sylar高性能服务器-日志(P43-P48)内容记录

文章目录 P43&#xff1a;Hook01一、HOOK定义接口函数指针获取接口原始地址 二、测试 P44-P48&#xff1a;Hook02-06一、hook实现基础二、class FdCtx成员变量构造函数initsetTimeoutgetTimeout 三、class FdManager成员变量构造函数get&#xff08;获取/创建文件句柄类&#x…

Python编程实验五:文件的读写操作

目录 一、实验目的与要求 二、实验内容 三、主要程序清单和程序运行结果 第1题 第2题 四、实验结果分析与体会 一、实验目的与要求 &#xff08;1&#xff09;通过本次实验&#xff0c;学生应掌握与文件打开、关闭相关的函数&#xff0c;以及与读写操作相关的常用方法的…

【亚马逊云科技】通过Amazon CloudFront(CDN)快速访问资源

文章目录 前言一、应用场景二、【亚马逊云科技】CloudFront&#xff08;CDN&#xff09;的优势三、入门使用总结 前言 前面有篇文章我们介绍了亚马逊云科技的云存储服务。云存储服务主要用于托管资源&#xff0c;而本篇文章要介绍的CDN则是一种对托管资源的快速访问服务&#…

Py2neo查询neo4j周杰伦数据库中的节点、关系和路径教程

文章目录 py2neo介绍连接Neo4j数据库py2neo查询图数据库neo4j数据概览使用NodeMatcher查询节点使用RelationshipMatcher查询关系 通过执行Cypher语句查询 py2neo介绍 Neo4j是一款开源图数据库&#xff0c;Py2neo提供了使用Python语言访问Neo4j的接口。本文介绍了使用Py2neo的N…

python脚本实现全景站点矩阵转欧拉角

效果 脚本 import re import numpy as np import math import csv from settings import * # 以下是一个示例代码,可以输入3*3旋转矩阵,然后输出旋转角度:# ,输入3*3旋转矩阵# 计算x,y,z旋转角def rotation_matrix_to_euler_angles(R):

使用uniapp开发时自定义tabbar

预览图&#xff1a; 一、配置page.jsong中的tabbar&#xff08;这一步是必须的&#xff0c;因为我们在使用uni.switchTab()时必须要用到&#xff09; "tabBar": {"list": [{"pagePath": "pages/index/index","iconPath": &…

CI/CD笔记.Gitlab系列.`gitlab-ci.yml`中的头部关键字

CI/CD笔记.Gitlab系列 gitlab-ci.yml中的头部关键字 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/article/details/136342897HuaW…

Arduino ESP32下载太慢终极解决办法

打开百度网盘下载你需要的软件包到Arduino15\staging\packages目录下&#xff0c;重新在包管理器中安装即可。 链接&#xff1a;https://pan.baidu.com/s/1LKPKuLxkw9xgCrPxTF6alQ?pwdckms 提取码&#xff1a;ckms 失效请留言 附文件列表&#xff1a; xtensa-esp32-elf-gcc…