密码学概述论 绝地灬酷狼 2023-01-13 10:43 115阅读 0赞 ### 密码学基础 ### * * 一:对称加密: * * 1.1: 对称加密/解密三要素: * 1.2:凯撒密码: * 1.3:对称加密的流程与特点: * 1.4:编码与加密: * 1.5:分组: * 二:对称加密算法: * * 2.1:DES算法: * 2.2:3DES算法: * 2.3:AES算法: * 三:非对称加密: * * 3.1:非对称加密流程与特点: * 3.2: 对称加密存在的问题: * 3.3: 非对称加密的使用场景: * 3.4:OpenSSL生成非对称加密秘钥: * 四:非对称加密算法: * * 4.1:RSA生成公钥和私钥: * 4.2:RSA进行加密和解密 * 4.3: Base64进行编解码: * 4.4:哈希(单向散列函数): * 4.5:MD5加密(哈希): * 4.6:sha运算(哈希): * 4.7:消息认证码(MAC): * 4.8:数字签名: * 4.9:ECC椭圆曲线: * 4.11:数字证书: * 4.12:HTTPS流程分析: ## 一:对称加密: ## ### 1.1: 对称加密/解密三要素: ### * 1: 对称加密三要素: 明文,加密算法, 秘钥。 * 2: 对称解密三要素:密文,解密算法,秘钥。 ### 1.2:凯撒密码: ### * 凯撒密码加密流程: 将小写字母转化成大写字母,然后向右移动指定位数。 * 凯撒密码解密流程:将大写字母,向左移动指定位数,然后转化成小写字母。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70] ### 1.3:对称加密的流程与特点: ### * 流程: * A使用秘钥将明文加密成密文。 * B使用秘钥将密文解密成明文。 * 特点: * 加密过程只有一把秘钥。 * 加密效率比非对称加密高。 * 安全性比非对称加密低。 ### 1.4:编码与加密: ### * 1: 最小单位: bit * 1Byte = 8bit * 1K = 1024B * 1M = 1024K * 1G = 1024M * 1T = 1024G * 1P = 1024T * 编码和解码: * 编码: 由字符的形式变成二进制的形式。 * 解码:由二进制的形式变成字符的形式。 * 加密与解密: * 加密:明文比特—>密文比特。 * 解密:密文比特序列—>明文比特序列。 ### 1.5:分组: ### * 1:明文分组:加密之前的分组。 * 2:密文分组:加密之后的分组。 * 3:明文分组和密文分组是等长的。 * 4: 五中分组模式: * ECB : 电子密码本 * 原理:先将原来的数据进行分组,然后对于分组的数据进行加密。如果分组最后一块有缺失,则会进行数据补充。 * 缺点:加密不安全。原因:如果是对于分组进行加密则同一个数据加密的结果是固定的,则如果我们使用计算机对于指定的数据加密,很容易找到规律,进行破解。 * 例如: AAA加密后是CCC, 我们只要得到CCC数据就知道他就是AAA。 * 特点: * 加密效率高,但是加密不彻底。 * 需要对数据进行分组填充。 * 每个分组独立进行加密,解密。 * 只要有一个分组被破解了,则所有的分组都会被破解了。 * 不使用,GO语言不支持这种分组模式。 * **CBC: 密文分组链接模式**(常用) * 与或非概念: <table> <thead> <tr> <th></th> <th>按位操作符号</th> <th>逻辑操作符号</th> </tr> </thead> <tbody> <tr> <td>与</td> <td>&</td> <td>&&</td> </tr> <tr> <td>或</td> <td>|</td> <td>||</td> </tr> <tr> <td>非</td> <td>-</td> <td>!</td> </tr> </tbody> </table> * 按位操作案例: A:8,0000,1000 B : 9, 0000, 1001 A & B:(与操作:11才是1,其余全0) 0000, 1000 0000, 1001 & 0000, 1000 * 异或加密:(相同为0,不同为1) 0000, 1000 —>明文 0000, 1001 ---->秘钥 XOR ---->异或操作 0000, 0001 ----->密文 * 对于密文,再次进行异或操作,则可恢复成明文。 * CBC模式的流程: * 1:先对于明文进行分组 * 2:使用前一组加密的结果与当前组进行异或操作。 * 3:将异或操作的结果进行加密。 * 4:第一组加密的时候需要提供一个初始化向量(与分组长度相同的) \-![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 1] * CBC加密的特点: * 数据长度根据算法而定。 * 需要提供初始化向量,要求长度必须和分组长度相同。 * 每一个密文都是下一次加密操作的输入。 * 不能并行加密,但是可以并行解密。 * 加密强度高 * 如果数据不足,需要进行填充。 * CFB:密文反馈模式 * 与CBC差不多,只不过是将异或操作与加密操作的顺序倒置了。 * 由于没有对明文直接进行加密,所以分组时,**不需要填充**。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 2] * OFB : 输出反馈模式 * 流程: * 1: 先对初始向量进行加密处理(密码) * 2:分组后每组的数据与密码进行异或操作。 * 特点: * 分组长度取决于加密算法。 * 不断对初始向量的输出进行加密,从而得到数据来源。 * 不需要进行数据填充。 * 图示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 3] * **CTR:计数器模式**(常用) * 加密算法与分组的关系: ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CIchCGIu-1618728907306)(C:\\Users\\11737\\AppData\\Roaming\\Typora\\typora-user-images\\1618064239228.png)\]][img-CIchCGIu-1618728907306_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618064239228.png] * 图示 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 4] * 流程: * 1: 首先使用计数器生成一个8位的随机数,然后看看有几个分组,后面的计数器执行+1操作。 * 2:使用加密算法对计数器进行加密。 * 3:将加密后的密码与明文进行异或操作生成密文。 * CTR与OFB的区别: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 5] ## 二:对称加密算法: ## ### 2.1:DES算法: ### * DES算法介绍: * 将64位比特的明文加密成64位比特密文的对称加密算法。 * 秘钥长度是56比特,少8位的原因是最后一位是校验位。 * 特点:加密的时候先对数据进行分组,每64位 分一组。 * 代码:使用DES算法+CBC分组模式: * DES算法要求:秘钥:8bytes, 分组长度:8bytes * CBC分组模式要求: 初始化向量,长度与密码长度相同:8bytes * 实现加密函数的代码: package main import ( "bytes" "crypto/cipher" "crypto/des" "fmt" ) /* 需求:使用DES算法和CBC分组模式进行加密 DES算法:秘钥8bytes,分组长度:8bytes CBC分组:提供初始化向量:长度与分组长度相同。 */ // 加密分析: /* 1: 创建一个实现DES算法的cipher.Block接口, 这个接口返回一个cipter.Block - func NewCipter(key []byte)(cipter.Block, error) - 包名: des - 参数: 秘钥, 8bytes - 返回值: type Bolck interface { // 返回加密字节快的大小 BlockSize() int // 加密src的第一块数据并写入dst, src和dst是指向同一块内存地址的。 Encrypt(dst, src []byte) // 解密src的第一块数据写入dst, src和dst是指向同一块内存地址的。 Decrypt(dst, src []byte) } 2: 进行数据填充: 3: 引入CBC模式接口,而这个接口返回一个密码分组链接模式的, 底层使用b加密的BlockMode接口,初始化向量iv的长度必须等于b的块尺寸。 func NewCBCEncrypter(b Block, iv []byte) BlockMode - 包名: cipter - 参数1: cipter.Block - 参数2: 初始化向量: initialize vector - 返回值:分组模式, 里面提供加密解密算法。 type BolckMode interface { // 返回加密字节快的大小 BlockSize() int // 加密或者解密数据块, src和dst是指向同一块内存地址的。 CryptBlocks(dst, src []byte) } */ // 输入明文和秘钥, 输出密文 func desCBCEncrypt(src , key []byte) []byte{ fmt.Printf("加密开始, 输入的数据是: %s\n", src) // 1: 创建并返回一个使用DES进行加密的cipter.Block接口 block, err := des.NewCipher(key) if err != nil{ panic(err) } // 2: 进行数据填充 src = paddingInfo(src, block.BlockSize()) // 3: 引入CBC模式: //iv := []byte("12345678") iv := bytes.Repeat([]byte("1"),block.BlockSize()) blockMode := cipher.NewCBCEncrypter(block, iv) // 4: 加密操作: blockMode.CryptBlocks(src/* 加密后的密文*/, src/* 明文*/) fmt.Printf("加密结束, 加密之后的密文是:%x\n",src) return src } * 实现填充: 填充逻辑: * 加密:假设分组位数是8位,则如果剩余一位,则填充7个7, 如果剩余两位,则填充6个6, 如果没有剩余,则填充8个8。 * 解密:首先判断最后一位是多少,如果是8则截取8后八位去掉,如果是7则截取后七位去掉。 * 实现填充代码: * 1: 增加这样的一个函数: // 填充函数,输入明文, 分组长度,输出填充后的数据 func paddingInfo(src []byte , blockSize int) []byte{ // 1: 得到明文长度 length := len(src) // 2: 需要填充的数量 remains := length % blockSize paddingNumber := blockSize - remains // 3:把填充的数值转换成字符 s1 := byte(paddingNumber) // 4: 把字符拼接成数组 s2 := bytes.Repeat([]byte{ s1}, paddingNumber) // 5: 把拼接的数组追加到src的后面 srcNew := append(src, s2...) // 6: 返回新的数组 return srcNew } * 2: 在上面的 数据填充位置进行填充数据 // 2: 进行数据填充 src = paddingInfo(src, block.BlockSize()) * 解密函数: * 1:解密函数编写: func desCBCDecrypt(cipherData, key []byte) []byte { // 1: 创建并返回一个使用DES进行加密的cipter.Block接口 block, err := des.NewCipher(key) if err != nil{ panic(err) } // 2: 引入CBC模式: //iv := []byte("12345678") iv := bytes.Repeat([]byte("1"),block.BlockSize()) blockMode := cipher.NewCBCDecrypter(block, iv) // 3: 进行解密操作: blockMode.CryptBlocks(cipherData/* 解密后的明文*/, cipherData/* 解密前的密文*/) fmt.Printf("解密结束, 解密之后的明文是:%x\n",cipherData) // 4: 去掉最后面的几位 cipherData = unpaddingInfo(cipherData) return cipherData } * 2:去掉最后的多余数据: func unpaddingInfo(plainText []byte) []byte{ // 1: 获取长度 length := len(plainText) if length == 0{ return []byte{ } } // 2: 获取最后一个字符: lastByte := plainText[length - 1] // 3: 将字符串转换成数字 unpaddingNumber := int(lastByte) // 4: 切片获取想要的数据 return plainText[ : length - unpaddingNumber] } * 整体的DES-CBC加密与解密: package main import ( "bytes" "crypto/cipher" "crypto/des" "fmt" ) /* 需求:使用DES算法和CBC分组模式进行加密 DES算法:秘钥8bytes,分组长度:8bytes CBC分组:提供初始化向量:长度与分组长度相同。 */ // 加密分析: /* 1: 创建一个实现DES算法的cipher.Block接口, 这个接口返回一个cipter.Block - func NewCipter(key []byte)(cipter.Block, error) - 包名: des - 参数: 秘钥, 8bytes - 返回值: type Bolck interface { // 返回加密字节快的大小 BlockSize() int // 加密src的第一块数据并写入dst, src和dst是指向同一块内存地址的。 Encrypt(dst, src []byte) // 解密src的第一块数据写入dst, src和dst是指向同一块内存地址的。 Decrypt(dst, src []byte) } 2: 进行数据填充: 3: 引入CBC模式接口,而这个接口返回一个密码分组链接模式的, 底层使用b加密的BlockMode接口,初始化向量iv的长度必须等于b的块尺寸。 func NewCBCEncrypter(b Block, iv []byte) BlockMode - 包名: cipter - 参数1: cipter.Block - 参数2: 初始化向量: initialize vector - 返回值:分组模式, 里面提供加密解密算法。 type BolckMode interface { // 返回加密字节快的大小 BlockSize() int // 加密或者解密数据块, src和dst是指向同一块内存地址的。 CryptBlocks(dst, src []byte) } */ // 输入明文和秘钥, 输出密文 func desCBCEncrypt(src , key []byte) []byte{ fmt.Printf("加密开始, 输入的数据是: %s\n", src) // 1: 创建并返回一个使用DES进行加密的cipter.Block接口 block, err := des.NewCipher(key) if err != nil{ panic(err) } // 2: 进行数据填充 src = paddingInfo(src, block.BlockSize()) // 3: 引入CBC模式: //iv := []byte("12345678") iv := bytes.Repeat([]byte("1"),block.BlockSize()) blockMode := cipher.NewCBCEncrypter(block, iv) // 4: 加密操作: blockMode.CryptBlocks(src/* 加密后的密文*/, src/* 明文*/) fmt.Printf("加密结束, 加密之后的密文是:%x\n",src) return src } // 填充函数,输入明文, 分组长度,输出填充后的数据 func paddingInfo(src []byte , blockSize int) []byte{ // 1: 得到明文长度 length := len(src) // 2: 需要填充的数量 remains := length % blockSize paddingNumber := blockSize - remains // 3:把填充的数值转换成字符 s1 := byte(paddingNumber) // 4: 把字符拼接成数组 s2 := bytes.Repeat([]byte{ s1}, paddingNumber) // 5: 把拼接的数组追加到src的后面 srcNew := append(src, s2...) // 6: 返回新的数组 return srcNew } /* 解密分析: 1: 创建一个实现DES算法的cipher.Block接口, 这个接口返回一个cipter.Block 2: 引入CBC模式接口 3: 进行解密操作 4: 去除填充 */ func desCBCDecrypt(cipherData, key []byte) []byte { // 1: 创建并返回一个使用DES进行加密的cipter.Block接口 block, err := des.NewCipher(key) if err != nil{ panic(err) } // 2: 引入CBC模式: //iv := []byte("12345678") iv := bytes.Repeat([]byte("1"),block.BlockSize()) blockMode := cipher.NewCBCDecrypter(block, iv) // 3: 进行解密操作: blockMode.CryptBlocks(cipherData/* 解密后的明文*/, cipherData/* 解密前的密文*/) fmt.Printf("解密结束, 解密之后的明文是:%x\n",cipherData) // 4: 去掉最后面的几位 cipherData = unpaddingInfo(cipherData) return cipherData } func unpaddingInfo(plainText []byte) []byte{ // 1: 获取长度 length := len(plainText) if length == 0{ return []byte{ } } // 2: 获取最后一个字符: lastByte := plainText[length - 1] // 3: 将字符串转换成数字 unpaddingNumber := int(lastByte) // 4: 切片获取想要的数据 return plainText[ : length - unpaddingNumber] } func main(){ src := []byte("12345678asdadsa") key := []byte("12345678") cipherData := desCBCEncrypt(src, key) fmt.Printf("cipherData: %x\n", cipherData) plainText := desCBCDecrypt(cipherData, key) fmt.Printf("解密后的数据是:%s\n", plainText) } ### 2.2:3DES算法: ### * 1: DES后来被破解的时间越来越短,因此有一种思路就是进行三次加密,提高被破解的时间。 * 2:加密与解密过程: * 加密:明文—>**加密—>解密—>加密**—>密文。 * 中间使用解密的原因是为了兼容之前的DES。 * 加密过程是以解密的方式进行加密,整体还是三次加密。 * 秘钥长度:8B \* 3 = 24B = 24 \* 8 = 192b * 秘钥的分组:与DES算法相同。 * 解密:密文—>解密—>加密—>解密—>明文。 * 3个秘钥: * 如果秘钥1等于秘钥2,或者秘钥2等于秘钥三,则3DES其实就是DES。 * 如果秘钥1与秘钥3相同,相当于两个秘钥。专业名词:3des-EDE2 * 如果三个秘钥都不相同,则专业名词:3des-EDE3。 ### 2.3:AES算法: ### * 3DES存在的问题: * 加密效率很低。 * AES特点: * 秘钥长度可以选择:16b, 24b, 32b。 * 分组长度:16b(是DES的一倍) * 效率高。 * AES-CTR加密代码: * 加密解密分析: * AES秘钥可以选择长度,我们选择16,则秘钥长度也是16。 * CTR不需要提供向量,但是需要提供数字。 * 加密代码: package main import ( "bytes" "crypto/aes" "crypto/cipher" "fmt" ) /* 加密分析: 1: 创建一个cipter.Block接口 2: 选择一个分组模式: CTR 3: 加密 4: 返回加密数据 */ func aesCTREncrypt(src, key []byte) []byte { // 1: 创建一个cipter.Block接口 block, err := aes.NewCipher(key) if err != nil{ panic(err) } // 2: 选择分组模式: iv := bytes.Repeat([]byte("1"), block.BlockSize()) stream := cipher.NewCTR(block, iv) // 3: 进行加密操作: stream.XORKeyStream(src/*密文*/, src/*明文*/) // 4: 返回加密的数据 return src } func main(){ // 1: 准备加密数据 src := []byte("任稻草") // 2: 准备加密秘钥: 秘钥必须16 key := []byte("1234567812345678") // 3: 调用加密函数,得到密文 cipherData := aesCTREncrypt(src, key) fmt.Printf("加密后的数据是:%x\n", cipherData) } * 解密代码: func aesCTRDecrypt(cipherData, key []byte) []byte { // 1: 创建一个cipter.Block接口 block, err := aes.NewCipher(key) if err != nil{ panic(err) } // 2: 选择分组模式: iv := bytes.Repeat([]byte("1"), block.BlockSize()) stream := cipher.NewCTR(block, iv) // 3: 进行解密操作: stream.XORKeyStream(cipherData/*明文*/, cipherData/*密文*/) // 4: 返回加密的数据 return cipherData } func main(){ // 1: 准备加密数据 src := []byte("任稻草") // 2: 准备加密秘钥: 秘钥必须16 key := []byte("1234567812345678") // 3: 调用加密函数,得到密文 cipherData := aesCTREncrypt(src, key) fmt.Printf("加密后的数据是:%x\n", cipherData) // 4: 调用解密函数进行解密 plainText := aesCTRDecrypt(cipherData, key) fmt.Printf("解密后的数据是:%s\n", plainText) } ## 三:非对称加密: ## ### 3.1:非对称加密流程与特点: ### * 流程: * A,B分别产生自己的公钥和私钥。 * A, B双方将自己的公钥发送给对方。 * A与B进行通信:A使用B的公钥进行加密,B使用自己的私钥进行解密。 * B与A进行通信:B使用A的公钥进行加密,A使用自己的私钥进行解密。 * 特点: * 通信双方,都有自己的公钥,私钥。 * 安全性高。 * 加密效率低。 ### 3.2: 对称加密存在的问题: ### * 1: 秘钥管理困难: 对于一个对称加密:A要跟100个分进行通信,则需要管理100个秘钥。我要找到哪个才是咱俩进行通信的才能加解密。而对于非对称加密,我保存的是我自己的私钥和你传给我的公钥,无论我要跟谁发送消息,我只需要使用自己私钥进行加密,而谁跟我交流,我用对应人的公钥解密就可以了。 * 2: 秘钥分发困难: 对于对称加密,我们要保证传输过程中,秘钥不被窃取。而非对称加密,只有窃取双方的公钥,第三个人才只是拥有看信息的权利,也无法进行交流。只有将双方的私钥还要拿到,才能进行加密,伪造信息。 ### 3.3: 非对称加密的使用场景: ### * 1:通信加密 * 2:https * 3:网银的U盾 * 4:github ssh登录 * 5: 签名(哈希 + 非对称加密) ### 3.4:OpenSSL生成非对称加密秘钥: ### * openssl下载: * x下载地址:http://slproweb.com/products/Win32OpenSSL.html ![\- \[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y6x1piMa-1618728907309)(C:\\Users\\11737\\AppData\\Roaming\\Typora\\typora-user-images\\1618312155327.png)\]][- _img-y6x1piMa-1618728907309_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618312155327.png] * 将bin目录加入到windows全局配置来。 * 使用openssl生成公钥和私钥: * 切换到存储公钥和私钥的文件夹。 * windows终端中输入:openssl进入 OpenSSL终端。 * 执行命令生成自己的私钥: genrsa -out rsa\_private\_key.pem * 执行命令根据私钥生成公钥: rsa -in rsa\_private\_key.pem -pubout -out rsa\_public\_key.pem ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 6] ## 四:非对称加密算法: ## ### 4.1:RSA生成公钥和私钥: ### * 1:加密过程 * 1:对加密的明文字符根据字符对应表转化成数字值。 * 2:对数值依次进行E次方处理。 * 3:对N取模。 * 由E和N组成了公钥。 * E: 根据特定的规则,限定了一个区间, 在这个区间内随意选用的。 * N: 素数的乘积 * 2: 解密过程: * 1:对密文进行D次方处理 * 2:对N进行取模 * 3:根据字符表恢复成明文。 * D和N组成我们的私钥: * D: 如何获取D的值才是最难的,因为只有知道是哪两个大素数才能计算出D。 * N:素数的乘积。 * 3:RSA安全的原因: * 基于对大素数进行因式分解(世界公认难题) * 4:Go创建RSA公钥和私钥 * 生成私钥分析: /* 需求: 生成并保存公钥私钥和公钥: 生成私钥分析: 1:使用GenerateKey函数使用随机数生成器random生成一对具有指定字位数的RSA秘钥 func GenerateKey(random io.Reader, bits int)(priv *PrivateKey, err error) - 参数1: 随机数 - 参数2: 秘钥长度 - 返回值: 私钥 2:对于生成的私钥进行编码处理, x509规则,按照这个规则,进行序列化处理, 生成der编码的数据。 MarshalPKIXPublicKey将公钥序列化成PKIX格式DER编码。 func MarshalPKCSPublicKey(pub interface{})([]byte, error) 3:创建一个Block结构,并填入私钥。(目的是生成上面虚线,下面虚线的格式) type Block struct { Type string Headers map[string]string Bytes []byte } 4: 将Pem Block格式写入到磁盘文件中。 */ * 生成公钥分析: /* 1: 通过私钥获取公钥 2:对生成的公钥进行der 3:创建Block结构,将Block结构加入到der编码中 4:将Pem Block数据写入到磁盘文件中。 */ * 生成私钥和公钥代码: package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt" "os" ) const PrivateKeyFile = "./privateKey.pem" const PublicKeyFile = "./PublicKey.pem" func generateKeyPair(bits int) error{ // 1: GenerateKey函数使用随机数生成器random生成RSA私钥 privateKey, err := rsa.GenerateKey(rand.Reader, bits) // 注意这里导包需要导入:"crypto/rand", 不能导入math/rand if err != nil{ return err } // 2: 对于生成的私钥进行编码处理,生成der编码后的数据 priDerText := x509.MarshalPKCS1PrivateKey(privateKey) // 3: 创建一个Block, 把der编码后的数据加入到Block中 block := pem.Block{ Type: "RSA PRIVATE KEY", Headers: nil, Bytes: priDerText, } // 4: 将Block写入到磁盘文件中 filehandler1, err := os.Create(PrivateKeyFile) defer filehandler1.Close() err = pem.Encode(filehandler1, &block) if err != nil{ return err } /* 1: 通过私钥获取公钥 2:对生成的公钥进行der 3:创建Block结构,将Block结构加入到der编码中 4:将Pem Block数据写入到磁盘文件中。 */ // 1: 通过私钥获取公钥,得到的是对象 pubKey := privateKey.PublicKey // 2: 对公钥进行der编码 pubKeyDerText := x509.MarshalPKCS1PublicKey(&pubKey) // 3: 将der后的结构,放入到Block中 block1 := pem.Block{ Type: "RSA Public Key", Headers: nil, Bytes: pubKeyDerText, } // 4: 写入磁盘: filehandler2, err := os.Create(PublicKeyFile) err = pem.Encode(filehandler2, &block1) defer filehandler2.Close() if err != nil{ return err } return nil } func main(){ // 1: 生成私钥 fmt.Printf("生成的私钥") err := generateKeyPair(1024) if err != nil{ fmt.Printf("生成私钥出错了!!") }else{ fmt.Printf("生成私钥成功了!!") } } ### 4.2:RSA进行加密和解密 ### * 公钥加密流程: package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt" "io/ioutil" ) const PrivateKeyFile = "./privateKey.pem" const PublicKeyFile = "./PublicKey.pem" func rsaPubEncrypt(filename string, plainText []byte) (error, []byte) { // 1: 通过公钥文件读取公钥信息 info , err := ioutil.ReadFile(filename) if err != nil{ return err, []byte{ } } // 2: 在读到的Block中获取中间的内容 block , _ := pem.Decode(info) // 返回值1:pem.Block // 返回值2:rest参加是没有没有解码完的数据,存储在这里 // 3: 解码der, 得到公钥 derText := block.Bytes publicKey, err := x509.ParsePKCS1PublicKey(derText) if err != nil{ return err, []byte{ } } // 4: 使用公钥进行加密 // func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) cipherData, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText) if err != nil{ return err, []byte{ } } return nil, cipherData } func main(){ src := []byte("稻草任") err, cipherData := rsaPubEncrypt(PublicKeyFile, src) if err != nil{ fmt.Println("公钥加密失败") } fmt.Printf("公钥加密结果是:%x\n", cipherData) } * 私钥解密流程: func rsaPriKeyDecrypt(filename string, cipherData[]byte) (error, []byte) { // 1: 通过私钥文件读取私钥信息 info , err := ioutil.ReadFile(filename) if err != nil{ return err, []byte{ } } // 2: 在读到的Block中获取中间的内容 block , _ := pem.Decode(info) // 返回值1:pem.Block // 返回值2:rest参加是没有没有解码完的数据,存储在这里 // 3: 解码der, 得到私钥 derText := block.Bytes privateKey, err := x509.ParsePKCS1PrivateKey(derText) if err != nil{ return err, []byte{ } } // 4: 使用私钥进行解密 // func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherData) if err != nil{ return err, []byte{ } } return nil, plainText } func main(){ src := []byte("稻草任") err, cipherData := rsaPubEncrypt(PublicKeyFile, src) if err != nil{ fmt.Println("公钥加密失败") } fmt.Printf("公钥加密结果是:%x\n", cipherData) err, plainText := rsaPriKeyDecrypt(PrivateKeyFile, cipherData) if err != nil{ fmt.Println("私钥解密失败") } fmt.Printf("私钥解密结果是:%s\n", plainText) } ### 4.3: Base64进行编解码: ### * Base64编码原理: * 编码规则: 先将传入的字符---->转换成ASCII码---->每个ASCII码是8位---->以6位为一组得到一个数字---->在编码表中查找对应值,得到编码后的数。 * 如果最后不足怎么办? 一般来说是将三个字节转换成四个字节,但是过程中可能出现剩余情况,此时要补零,并且空余字节用等号代替。所以编码最后如果存在剩余,要么一个等号,要么两个等号。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kNyxMgFx-1618728907312)(C:\\Users\\11737\\AppData\\Roaming\\Typora\\typora-user-images\\1618451681223.png)\]][img-kNyxMgFx-1618728907312_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618451681223.png] * 存在一个编码表: * 普通的字符集(A-Z, a-z, 0-9, +,/) * url专用字符集(A-Z, a-z, 0-9, \_,-) ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 7] * GO语言实现Base64编解码: * 标准的Base64编码: * Url的Base64编码: package main import ( "encoding/base64" "fmt" ) func main(){ info := []byte("我是一夜奈何梁山") // 1: 进行Base64编码 encodeInfo := base64.StdEncoding.EncodeToString(info) fmt.Printf("使用Base64进行编码后的结果是:%s\n",encodeInfo ) // 进行解码: decode_info , err := base64.StdEncoding.DecodeString(encodeInfo) if err != nil{ panic(err) } fmt.Printf("使用Base64进行解码后的结果是:%s\n", decode_info) // 2: 使用Base64url方式进行编码 info2 := []byte("https://www.bilibili.com/video/BV1e4411H7vq?p=49") encodeInfo2 := base64.URLEncoding.EncodeToString(info2) fmt.Printf("使用Base64进行Url编码的结果是:%s\n", encodeInfo2) // 进行解码 decode_info2 , err := base64.URLEncoding.DecodeString(encodeInfo2) fmt.Printf("使用Base64进行Url解码的结果是:%s\n", decode_info2) } ### 4.4:哈希(单向散列函数): ### * 哈希: 可以对输入的内容生成一个唯一的数值。 * 输入的内容不变,输出的内容不变。 * 输入的内容改变一点,输出的内容千差万别。 * 无论输入的内容多大,生成的哈希长度是相等的。 * 哈希运算是对输入的内容进行摘要(指纹), 无法根据哈希值推断出原文。 * 哈希的应用场景: * 1: 检测软件是否篡改。 对于一个软件的下载,我们官方一般提供一个哈希值,当我们下载完成后,可以对安装的exe文件进行哈希运算,得到的值如果跟官网的一致,则传输过程中没有被篡改。 * 2:消息认证码: * 3:伪随机数生成器 * 4:一次性口令: * 5:密码存储: 为了方式密码被盗,数据库一般存储密文(哈希加密后的值) * 6:数字签名: ### 4.5:MD5加密(哈希): ### * 数据量多的时候进行哈希处理: package main import ( "crypto/md5" "fmt" "io" ) func main(){ // 对少量数据进行哈希运算 // 1: 创建一个哈希器 hasher := md5.New() // 2:向哈希中加入数据 io.WriteString(hasher, "hello") io.WriteString(hasher, "word") // 2: 执行SUm操作,得到哈希值 hash := hasher.Sum(nil) fmt.Printf("生成的哈希值是:%x\n", hash) //生成的哈希值是:59284aa85709ddaf3bd246030060f6a2 } 如果 hasher.Sum(nil),中的nil是其他的字节数据例如0x,则会加入到哈希值的前面,根本不影响哈希值。 * 数据量少的时候: package main import ( "crypto/md5" "fmt" ) func main(){ // 1:准备数据 src := []byte("我是一页奈何梁山") // 2:进行哈希运算:返回的是数组类型 hash := md5.Sum(src) fmt.Printf("MD5加密后的哈希值是:%x\n", hash) // MD5加密后的哈希值是:61d6b87120ce5fd3ee27f746ee1a4c90 } ### 4.6:sha运算(哈希): ### * sha类的哈希运算分为两类: sha1, sah2 * 最常用的是sha256(比特币,以太坊) ### 4.7:消息认证码(MAC): ### * 场景分析: A与B进行通信,假设A向B发送了一个消息,B如何才能判断是A发送过来的,并且如何判断A发送过来的信息没有被篡改呢? * 思考: 使用对称加密可以吗? A明文----->加密---->密文----->发送给B---->B解密---->明文 假设发送的是“你好”, 没有篡改解密是“你好”, 假设篡改后解密是“\*\*XX()”乱码,因为是乱码,我们判断被篡改了。但是如果发送的本身就是乱码,解密出来,我如何判断是不是被篡改了呢?我无法进行判断。因此这就需要消息认证(哈希) * 消息认证码如何判断没有消息没有被篡改? * 1: A与B之间协商消息认证码秘钥。 * 2:A将消息经过对称加密秘钥加密,得到密文。 * 3: A将密文经过消息认证码秘钥计算出哈希值 * 4:A将这个哈希值与密文同时发送给B。 * 5:B拿到密文,使用消息验证码秘钥对密文进行哈希得到哈希值, * 6:对比两个哈希值是否相同,判断信息是否被篡改。 * 7:如果哈希值一直说明没有篡改,则使用对称加密秘钥进行解密。 图示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 8] * 消息认证码的用处: * SWIFT: * HTTPS:(重点) * IPSec: * HMAC函数(哈希MAC) package main import ( "crypto/hmac" "crypto/sha512" "fmt" ) // 生成hmac(消息认证码的函数) // 传入字节类型的数据--->返回哈希处理后的结果 func generateHMAC(src []byte, key []byte) []byte { // 1: 创建哈希器 hasher := hmac.New(sha512.New, key) // 2: 将数据加入哈希器中 hasher.Write(src) // 2: 生成哈希值 mac := hasher.Sum(nil) return mac } // 消息认证码的认证: func verifyHMC(src , key, mac1 []byte) bool { // 1: B接收到的数据---src // 2: B接收到的mac1 ---mac1 // 3: 对B到的数据进行哈希处理,得到mac2 mac2 := generateHMAC(src, key) // 4: 对比两个mac值是否相同。 return hmac.Equal(mac1, mac2) } func main(){ // 1: 生成明文和秘钥 src := []byte("我是一夜奈何梁山") key := []byte("1234567890") // 2: 生成mac1 mac1 := generateHMAC(src, key) // 3: 判断消息认证码是否相同 isEqual := verifyHMC(src, key, mac1) if isEqual{ fmt.Println("验证通过,没有被修改") }else{ fmt.Println("验证失败,中间有人被修改了") } } ### 4.8:数字签名: ### * 消息认证存在的问题: * 1:消息认证码的秘钥配送问题。 * 2:无法进行第三方证明。 * 3:无法防止发送方否认。 * 数字签名的流程: * 1:对原文进行哈希运算得到一个哈希值。 * 2:使用私钥对这个哈希值进行处理,得到一个签名。 * 3:将原文和签名一起发送给对方。 * 数字签名的认证流程: * 1:接收到原文,对原文进行哈希处理,得到一个哈希值。 * 2:使用公钥对签名进行解密,得到另外一个哈希值。 * 3:对比两个哈希值,可以知道是否被篡改了。 * 图示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 9] * 解决消息认证的问题: * 无法有效配送秘钥—>数字签名中,不需要协商秘钥,因此没有配送问题。 * 无法进行第三方证明----->任何持有公钥的,都能帮助认证。 * 无法防止发送方否认----->私钥只有发送方有,无法进行抵赖。 ### 4.9:ECC椭圆曲线: ### * 使用ECC椭圆曲线生成秘钥特点: * 1: ECC164位的密钥产生一个安全级,相当于RSA 1024位密钥提供的保密强度 。 * 2: 计算量较小,处理速度更快,存储空间和传输带宽占用较少。 * ECC椭圆曲线生成秘钥的用途: * 1: 居民二代身份证。 * 2:比特币 * 使用ECC椭圆曲线生成公钥和私钥: package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "encoding/pem" "os" ) const EccPrivateKeyFile = "./EccPrivateKey.pem" const EccPublicKeyFile = "./EccPublicKey.pem" func generateEccKeypair(){ // 1: 选择一个椭圆曲线 curve := elliptic.P256() // 2: 使用ecdsa包,创建私钥 privateKey, err := ecdsa.GenerateKey(curve, rand.Reader) if err != nil{ panic(err) } // 3:使用x509进行编码,序列化成DER编码 derText , err:= x509.MarshalECPrivateKey(privateKey) if err != nil{ panic(err) } // 4: 将编码后的DER编码写入Block中 block1 := pem.Block{ Type: "ECC PRIVATE KEY", Headers: nil, Bytes: derText, } // 5:将私钥写入到文件中 fileHander, err := os.Create(EccPrivateKeyFile) // 填充数据 if err != nil{ panic(err) } // 关闭上下文 defer fileHander.Close() // 写入到文件中 err = pem.Encode(fileHander, &block1) if err != nil{ panic(err) } // 1: 根据私钥生成公钥 publicKey := privateKey.PublicKey // 2:进行编码 derText1, err := x509.MarshalPKIXPublicKey(&publicKey) if err != nil{ panic(err) } // 4: 将编码后的DER编码写入Block中 block2 := pem.Block{ Type: "ECC Pubclic KEY", Headers: nil, Bytes: derText1, } // 5:将私钥写入到文件中 fileHander2, err := os.Create(EccPublicKeyFile) // 填充数据 if err != nil{ panic(err) } // 关闭上下文 defer fileHander2.Close() // 写入到文件中 err = pem.Encode(fileHander2, &block2) if err != nil{ panic(err) } } func main(){ generateEccKeypair() } * 使用ECC椭圆曲线: 私钥进行签名,公钥进行认证: * 在GO语言中无法使用ECC进行加解密, 但是支持ECC进行签名。 package main import ( "crypto/ecdsa" "crypto/rand" "crypto/sha256" "crypto/x509" "encoding/pem" "errors" "fmt" "io/ioutil" "math/big" ) const EccPrivateKeyFile = "./EccPrivateKey.pem" const EccPublicKeyFile = "./EccPublicKey.pem" /* 使用私钥进行签名 1:读取私钥,解码 2: 对原文进行哈希,得到哈希值 3:对哈希值使用私钥进行签名 */ // 自定义签名结构: type Signature struct { r *big.Int s *big.Int } // 私钥签名: func eccSignData(filename string, src []byte) (Signature, error) { // 1: 读取私钥,解码 info , err := ioutil.ReadFile(filename) if err != nil{ return Signature{ } , err } block, _ := pem.Decode(info) derText := block.Bytes privateKey , err := x509.ParseECPrivateKey(derText) if err != nil { return Signature{ } , err } // 2: 对原文进行哈希,得到哈希值 hash := sha256.Sum256(src) // 3: 使用私钥对哈希值进行签名 r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:]) if err != nil{ return Signature{ }, err } sig := Signature{ r, s} return sig, nil } /* 1: 读取公钥,解码 2:对原文生成哈希 3:使用公钥进行验证 */ // 公钥认证 func eccVerifySig(filename string, src []byte, sig Signature) error{ // 1:读取公钥 info , err := ioutil.ReadFile(filename) if err != nil { return nil } // 2: 在block中获取被der编码的数据 block , _ := pem.Decode(info) // 3: 解码der,拿到公钥 derText := block.Bytes publicKeyInterface , err := x509.ParsePKIXPublicKey(derText) if err != nil{ return err } publicKey, ok := publicKeyInterface.(*ecdsa.PublicKey) if !ok { return errors.New("断言失败,不是ECDS公钥") } // 4: 对原文进行哈希处理 hash := sha256.Sum256(src) // 5: 使用公钥验证哈希值和两个大数r,s,返回签名是否合法。 isValid := ecdsa.Verify(publicKey, hash[:], sig.r, sig.s) if !isValid{ return errors.New("校验失败") }else{ return nil } } func main(){ // 1: 调用私钥签名函数返回签名 src := []byte("我是一夜奈何梁山") sig , err := eccSignData(EccPrivateKeyFile, src) if err != nil{ panic(err) } fmt.Println("私钥进行的签名是:", sig.r, sig.s) // 2: 进行校验 err = eccVerifySig(EccPublicKeyFile, src, sig) if err != nil{ fmt.Println(err) return } fmt.Println("校验成功!!") } ### 4.11:数字证书: ### * 为什么需要数字证书? * 非对称加密首先要进行公钥交换,那么我怎么才能确定,我拿到的是你的公钥,而不是被篡改的公钥呢? * 图示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 10] * 解决方案:引入第三方认证机构CA ### 4.12:HTTPS流程分析: ### * HTTPS = HTTP +SSL * SSL : * CA颁发过程: * 1: 服务器提供者生成公钥和私钥,将公钥发送给CA机构。 * 2:CA机构也会有自己的私钥和公钥,CA使用自己的私钥对服务器的公钥进行数字签名。 * 3:CA机构将数字证书发送给服务器。 * CA认证过程: * 1:浏览器给服务器发送请求, 服务器将数字证书发送给浏览器。 * 2:客户端的浏览器安装了知名CA机构的根证书,包含了CA机构的公钥, 浏览器对服务器的证书进行验证。 * 3:如果验证成功,则表示网站可信,如果认证失败则提示警告。 * HTTPS通信的过程: * 1:CA认证过程 * 2:如果证书有效,则浏览器将自己支持的加密算法发送给服务器,同时生成一个对称加密秘钥,使用服务器的公钥,对对称加密秘钥进行加密,然后发送给服务器。 * 3:服务器使用自己的私钥,对密文进行解密,得到对称加密秘钥。 * 4:以后双方通信都使用对称加密秘钥进行加密与解密。 * windows下查看CA证书: * 过程图示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 11] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 12] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70]: /images/20221022/23f3a15b1eb345579d46ab1cd6b328fb.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 1]: /images/20221022/7ae17319bb45401593b4db1dd6128383.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 2]: /images/20221022/9c8fc63473714bc29eedcfe31a089c77.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 3]: /images/20221022/99266c447fae460ea1513d4c060484c3.png [img-CIchCGIu-1618728907306_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618064239228.png]: /images/20221022/5a26874d34414d5187f5955a1c8cc96e.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 4]: /images/20221022/07963d6cb97045bcbf52d143616a8c5a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 5]: /images/20221022/d44019ae3aca48c196b4116a4de05cb1.png [- _img-y6x1piMa-1618728907309_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618312155327.png]: /images/20221022/354f6b21607749f0b8e79431ac389b45.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 6]: /images/20221022/2177cd3ed56b407d998e740e98eccc6a.png [img-kNyxMgFx-1618728907312_C_Users_11737_AppData_Roaming_Typora_typora-user-images_1618451681223.png]: /images/20221022/192c66eec4b74f679202f35759c6c521.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 7]: /images/20221022/18822a1860c5419ea699ca226f34cde7.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 8]: /images/20221022/27c2b358d67e48ec9126e669d62702b3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 9]: /images/20221022/133e9dc5cd914b0f8f2c9f92f173ee50.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 10]: /images/20221022/da7eea48cd6e46d692f82b736410d977.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 11]: /images/20221022/75f5b9c4c12b4fc8b342515f773f22a1.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzQxNzU3_size_16_color_FFFFFF_t_70 12]: /images/20221022/2065664d3d7643f18bd27faf5912544f.png
相关 应用密码学密码学_密码学中的围栏密码 应用密码学密码学 In Rail Fence Cipher, given a plain-text message and a numeric key then cipher 以你之姓@/ 2023年03月05日 10:59/ 0 赞/ 165 阅读
相关 应用密码学密码学_密码学的类型 ![da0837b3d2e0c2255ba100321a3344e0.png][] 应用密码学密码学 “Cryptography is the standard of en 妖狐艹你老母/ 2022年12月07日 12:59/ 0 赞/ 299 阅读
相关 爬虫概述论 目录 一:windows环境下进入虚拟环境 二: requests模块的基本使用 2.1: requests模块请求对象: 旧城等待,/ 2022年10月30日 05:15/ 0 赞/ 253 阅读
相关 XML学概述 1.xml概述 1.1xml:xml一种数据存储格式,这种数据存储格式在存储数据内容的同时,还能够保存数据之间的关系 1.2xml保存数据的方法:xml利用标签来保存数 清疚/ 2022年08月07日 06:40/ 0 赞/ 169 阅读
相关 密码学基础 读书的很大一个目的就在于理解与记忆,技术类图书尤为如此。近期学习了密码学的相关知识,在这里沿着书中给出的线索,简述密码学基础。参考书籍——《图解密码技术》。 此前,先认识几个 忘是亡心i/ 2022年03月21日 02:49/ 0 赞/ 307 阅读
相关 密码学1 [![wKiom1ajtL2zl6QLAACQwqS7N\_E321.jpg][wKiom1ajtL2zl6QLAACQwqS7N_E321.jpg]][wKiom1 喜欢ヅ旅行/ 2022年01月12日 18:17/ 0 赞/ 349 阅读
相关 密码学总结 CTF中那些脑洞大开的编码和加密 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到类似这样的问题:表哥,你知道这是什么加密吗?其实CTF中脑洞密 清疚/ 2021年10月29日 08:52/ 0 赞/ 1636 阅读
相关 密码学笔记 1.加密方法可以分为两大类。一类是单钥加密(private key cryptography),还有一类叫做双钥加密(public key cryptography)。前者的加 妖狐艹你老母/ 2021年09月26日 12:52/ 0 赞/ 354 阅读
还没有评论,来说两句吧...