非对称加密
1. 对称加密的弊端
秘钥分发困难
可以通过非对称加密完成秘钥的分发
https
Alice 和 Bob 通信,Alice 给 bob 发送数据,使用对称加密的方式
生成一个非对称的秘钥对,bob 生成
bob 将公钥发送给 alice
alice 生成一个用于对称加密的秘钥
alice 使用 bob 的公钥就对称加密的秘钥进行加密,并且发送给 bob
bob 使用私钥就数据解密,得到对称加密的秘钥
通信的双方使用写好的秘钥进行对称加密数据加密
2. 非对称加密的秘钥
不存在秘钥分发困难的问题
2.1 场景分析
数据对谁更重要,谁就拿私钥
直观上看:私钥比公钥长
使用第三方工具生成密钥对:公钥文件 xxx.pub xxx
通信流程,信息加密 (A 写数据,发送给 B, 信息只允许 B 读)
A: 公钥
B: 私钥
登录认证 (客户端要登录,连接服务器,向服务器请求个人数据)
客户端:私钥
服务器:公钥
数字签名(表明信息没有受到伪造,确实是信息拥有者发出来的,附在信息原文的后面)
发送信息的人:私钥
收到信息的人:公钥
网银 U 盾
个人:私钥
银行拿公钥
3. 使用 RSA 非对称加密通信流程
要求: Alice 给 bob 发送数据,保证数据信息只有 bob 能看到
4. 生成 RSA 的秘钥对
4.1 一些概念
x509 证书规范、pem、base64
pem 编码规范 - 数据加密
base64 - 对数据编码,可逆
不管原始数据是什么,将原始数据使用 64 个字符来替代
a-z A-Z 0-9 + /
ASN.1 抽象语法标记
PKCS1 标准
4.2 密钥对生成流程
生成私钥操作流程概述
使用 rsa 中的 GenerateKey 方法生成私钥
func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error)
rand.Reader -> import “crypto/rand”
1024 的整数倍 - 建议
通过 x509 标准将得到的 ras 私钥序列化为 ASN.1 的 DER 编码字符串
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte
将私钥字符串设置到 pem 格式块中
初始化一个 pem.Block 块
type Block struct {
Type string // 得自前言的类型(如"RSA PRIVATE KEY")
Headers map[string]string // 可选的头项
Bytes []byte // 内容解码后的数据,一般是DER编码的ASN.1结构
}
通过 pem 将设置好的数据进行编码,并写入磁盘文件中
func Encode(out io.Writer, b *Block) error
out - 准备一个文件指针
生成公钥操作流程
从得到的私钥对象中将公钥信息取出
type PrivateKey
通过 x509 标准将得到 的 rsa 公钥序列化为字符串
func MarshalPKIXPublicKey(pub interface{}) ([]byte, error)
将公钥字符串设置到 pem 格式块中
type Block struct {
Type string // 得自前言的类型(如"RSA PRIVATE KEY")
Headers map[string]string // 可选的头项
Bytes []byte // 内容解码后的数据,一般是DER编码的ASN.1结构
}
通过 pem 将设置好的数据进行编码,并写入磁盘文件
func Encode(out io.Writer, b *Block) error
5. RSA 加解密
5.1 RSA 加密
将公钥文件中的公钥读出,得到使用 pem 编码的字符串
– 读文件
将得到的字符串解码
– pem.Decode
使用 x509 将编码之后的公钥解析出来
– func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
使用得到的公钥通过 rsa 进行数据加密
5.2 RSA 解密
将私钥文件中的私钥读出,得到使用 pem 编码的字符串
将得到的字符串解码
使用 x509 将编码之后的私钥解析出来
使用得到的私钥通过 rsa 进行数据解密
6. 哈希算法
6.1 概念
称谓:单向散列函数,哈希函数,杂凑函数,消息摘要函数
接收的输入:原像
输出:散列值,哈希值,指纹,摘要
6.2 单向散列函数特性
将任意长度的数据转换成固定长度的数据
很强的抗碰撞性
不可逆
MD4/MD5
不安全
散列值长度: 128bit == 16byte
sha1
不安全
散列值长度: 160bit == 20byte
sha2 - 安全
sha224
散列值长度: 224bit == 28byte
sha256
散列值长度: 256== 32byte
sha384
散列值长度: 384bit == 48byte
sha512
散列值长度: 512bit == 64byte
6.3 go 中使用单向散列函数
// 第一种方式, 直接调用sum
// 适用于数据量比较小的情况
func Sum(data []byte) [Size]byte
// 第二种方式
// 1. 创建哈希接口对象
func New() hash.Hash
type Hash interface {
// 通过嵌入的匿名io.Writer接口的Write方法向hash中添加更多数据,永远不返回错误
io.Writer
// 返回添加b到当前的hash值后的新切片,不会改变底层的hash状态
Sum(b []byte) []byte
// 重设hash为无数据输入的状态
Reset()
// 返回Sum会返回的切片的长度
Size() int
// 返回hash底层的块大小;Write方法可以接受任何大小的数据,
// 但提供的数据是块大小的倍数时效率更高
BlockSize() int
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 2. 往创建出的哈希对象中添加数据
hash.Hash.Write([]byte("添加的数据..."))
hash.Hash.Write([]byte("添加的数据..."))
hash.Hash.Write([]byte("添加的数据..."))
hash.Hash.Write([]byte("添加的数据..."))
// 3. 计算结果, md5就是散列值
md5 := hash.Sum(nil);
// 散列值一般是一个二进制的字符串, 有些字符不可见, 需要格式化
// 格式化为16进制的数字串 - 0-9, a-f
func EncodeToString(src []byte) string
// 数据转换完成之后, 长度是原来的2倍
计算一个大文件比如 1G 文件的散列值
使用 udp 的方式分发秘钥,进行一个对称加密的通信
服务器
生成密钥对
公钥发送给客户端
客户端
客户端收到了公钥
生成一个秘钥 - 用于对称加密
使用公钥加密,发送给服务器
复习
概念
加密三要素
明文 / 密文
秘钥
算法
对称加密和非对称加密
对称加密:加解密使用同一个秘钥,1 个
效率高
非…: 密钥对
公钥加密,私钥解密
私钥加密,公钥解密
对称加密中的公开的加密算法
des
分组长度: 8 字节
秘钥长度: 8 字节
3des
分组长度: 8 字节
秘钥长度: 24byte
aes
分组长度: 16 字节
秘钥长度: 16 字节,24 字节,32 字节
在 go 的 api 中只能使用 16 字节
对称加密的分组模式
EBC - 不推荐使用
CBC - 常用的方式
准备的数据:
初始化向量 iv - 字符数组
长度 == 明文分组长度
加解密初始化向量值必须相同
秘钥
根据加密算法定
===========================
OFB - 不推荐使用
CFB - 不推荐使用
CTR - 推荐使用,效率最高
原文来自互联网收集与学习视频的课件整理
防爬虫说明
禁止 学习某地爬虫,知乎爬虫,CSDN 爬虫。
本文,首发在 learnku 社区。
@author
汪春波(www.shxdledu.cn)