密码学总结(三)

一、数字签名

1.1 数字签名和非对称加密的关系

实际上,数字签名和非对称加密有着非常紧密的联系,简而言之,数字签名就是通过将非对称加密 “反过来用” 而实现的。下面我们来将密钥的使用方式总结成一张表:

私钥 公钥
非对称加密 接收者解密时使用 发送者加密时使用
数字签名 签名者生成签名时使用 验证着验证签名时使用
持有者 个人持有 任何人都可以持有

1.2 数字签名的两种方式

  • 方式一:直接对消息签名
    由于非对称加密算法本来就非常慢,所以使用方式一对消息进行加密会非常耗时,不推荐使用。
  • 方式二:对消息散列值签名
    使用方式二,不必再对整个消息进行加密,而是只要先用单向散列函数求出消息的散列值,然后再将散列值进行加密即可。无论消息多长,生成的散列值的长度都是固定不变得,因此在实际应用中推荐使用第二种方式。

1.3 数字签名的使用步骤

这里还是使用Alice和Bob的故事为例,假设Alice向Bob发起汇款(如下图)。
在这里插入图片描述
第一步:Alice使用单向散列函数计算出消息的散列值;
第二步:Alice用自己的私钥对散列值进行加密(签名);
第三步:Alice将消息和签名发送给Bob;
第四步:Bob使用Alice公钥将接收到的签名进行解密,得到散列值1;
第五步:Bob使用单向散列函数对接收到的消息计算出散列值2;
第六步:Bob将散列值1和散列值2进行对比。如果两个散列值相同,代表消息是由Alice发出;如果两个散列值不相同,代表消息不是由Alice发出;

1.4 通过RSA实现数字签名

  • 数字签名的实现步骤:
    第一步:生成秘钥对,保存到磁盘上;
    第二步:准备原始数据;
    第三步:其进行哈希运算,最终生成一个散列值;
    第四步:使用非对称加密的私钥对散列值进行加密,这个加密过程就称为签名;
    第五步:把签名和原始内容发送给对方;

  • 数据验证的实现步骤:
    第一步:接收原始数据和数字签名;
    第二步:对原始数据进行哈希运算,等到一个新的散列值;
    第三步:使用公钥对签名进行解密,最终得到一个散列值;
    第四步:比较两个散列值,如果相等,则代表发送数据没有被改动过;

示例代码:

// 生成私钥和公钥
func generateKey() {
    
    
	//============== 生成私钥 =============
	// 1.使用rsa中的GenerateKey方法生成私钥
	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
    
    
		panic(err)
	}
	// 2.通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	derText := x509.MarshalPKCS1PrivateKey(privateKey)
	// 3.将私钥字符串设置到pem格式块中
	block := pem.Block{
    
    
		Type: "rsa private key",
		Bytes: derText,
	}
	// 4.通过pem将设置好的数据进行编码, 并写入磁盘文件中
	file, err := os.Create("private.pem")
	if err != nil {
    
    
		panic(err)
	}
	defer file.Close()
	pem.Encode(file, &block)

	//============== 生成公钥 =============
	// 1.从得到的私钥对象中将公钥信息取出
	publicKey := privateKey.PublicKey
	// 2.通过x509标准将得到 的rsa公钥序列化为字符串
	derText, err = x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
    
    
		panic(err)
	}
	// 3.将公钥字符串设置到pem格式块中
	block = pem.Block {
    
    
		Type: "rsa public key",
		Bytes: derText,
	}
	// 4.通过pem将设置好的数据进行编码, 并写入磁盘文件
	file, err = os.Create("public.pem")
	if err != nil {
    
    
		panic(err)
	}
	defer file.Close()
	pem.Encode(file, &block)
}

// 读取密钥文件内容
func ReadKeyFile(keyFile string) []byte {
    
    
	file, err := os.Open(keyFile)
	if err != nil {
    
    
		panic("公钥文件不存在!")
	}
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
    
    
		panic("file.Stat err!")
	}
	buf := make([]byte, fileInfo.Size())
	file.Read(buf)
	return buf
}

// RSA签名
func SignatureRSA(plainText []byte, priKeyFile string) []byte {
    
    
	// 计算签名内容进行哈希运算,得到一个散列值
	res := sha512.Sum512(plainText)
	// 读取私钥文件中的内容
	buf := ReadKeyFile(priKeyFile)
	// 使用pem解码,得到pem.Block结构体
	block, _ := pem.Decode(buf)
	// 使用x509将数据解析成私钥结构体,得到私钥
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
    
    
		panic("x509.ParsePKCS1PrivateKey err!")
	}
	// 使用rsa中的函数对散列值签名
	sigText, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA512, res[0:len(res)])
	if err != nil {
    
    
		panic("rsa.SignPKCS1v15 err!")
	}
	return sigText
}

// 签名验证
func VerifyRSA(plainText, sigText []byte, pubKeyFile string) bool {
    
    
	// 对原始数据进行哈希运算,等到一个新的散列值
	res := sha512.Sum512(plainText)
	// 打开磁盘公钥文件,将公钥文件内容读取出来
	buf := ReadKeyFile(pubKeyFile)
	// 使用pem解码,得到pem.Block结构体
	block, _  := pem.Decode(buf)
	// 使用x509对pem.Block的bytes变量数据进行解析,得到一个接口
	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
    
    
		panic("x509.ParsePKIXPublicKey err!")
	}
	//进行类型断言,得到公钥
	publicKey, ok := pub.(*rsa.PublicKey)
	if !ok {
    
    
		panic("pub is not a public key!")
	}
	// 通过rsa.VerifyPKCS1v15函数进行签名认证
	err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA512, res[:], sigText)
	// 比较散列值
	return err == nil
}

1.5 通过椭圆曲线实现数字签名

椭圆曲线(英语:Elliptic curve cryptography,缩写为 ECC)在密码学中的使用是在1985年由Neal Koblitz和Victor Miller分别独立提出的。ECC的主要优势是在某些情况下,它比其他加密算法使用更小的密钥,提供更高的安全级别。ECC 164位的密钥相当于RSA 1024位密钥提供的保密强度,而且计算量更少,处理速度更快。目前我国居民二代身份证正在使用 256 位的椭圆曲线密码,虚拟货币比特币也选择ECC作为加密算法。

美国FIPS186-2标准, 推荐使用5个素域上的椭圆曲线, 这5个素数模分别是:
P192 = 2192 - 264 - 1
P224 = 2224 - 296 + 1
P256 = 2256 - 2224 + 2192 - 296 -1
P384 = 2384 - 2128 - 296 + 232 -1
P512 = 2512 - 1

  • ECC签名的实现步骤:
    第一步:读取私钥;
    第二步:使用pem进行解码;
    第三步:使用x509对私钥进行还原,得到PrivateKey结构体对象;
    第四步:对原始数据进行哈希计算,得到散列值;
    第五步:使用私钥对散列值进行签名;
/**
 * ECC签名
 * 参数1:需要签名的数据
 * 参数2:私钥文件
 * 返回值:椭圆曲线的坐标
 * /
func EccSignature(plainText []byte, priKeyFile string) (rText, sText []byte) {
	// 1.打开私钥文件,读取私钥
	buf := ReadKey(priKeyFile)
	// 2.使用pem进行解码
	block, _ := pem.Decode(buf)
	// 3.使用x509对私钥进行还原
	privateKey, err := x509.ParseECPrivateKey(block.Bytes)
	if err != nil {
		panic("x509.ParseECPrivateKey err!")
	}
	// 4.对原始数据进行哈希计算,得到散列值
	hashText := sha1.Sum(plainText)
	// 5.进行数字签名
	r, s, err := ecdsa.Sign(rand.Reader, privateKey, hashText[:])
	if err != nil {
		panic("ecdsa.Sign err!")
	}
	// 6.对r,s进行格式化
	rText, err = r.MarshalText()
	if err != nil {
		panic("r.MarshalText err!")
	}
	sText, err = s.MarshalText()
	if err != nil {
		panic("s.MarshalText err!")
	}
	return
}
  • ECC验证的实现步骤:
    第一步:读取公钥;
    第二步:使用pem进行解码;
    第三步:使用x509对公钥还原,得到公钥结构体对象;
    第四步:对原始数据进行哈希运算,得到散列值;
    第五步:执行签名验证;
/**
 * ECC签名验证
 * 参数1:认证的数据
 * 参数2和参数3:格式化后的椭圆曲线坐标
 * 参数4:公钥文件
 * 返回值:验证结果,true代表验证成功,false代表验证失败
 * /
func E
func EccVerify(plainText, rText, sText []byte, pubKeyFile string) bool {
	// 1.打开公钥文件,读取公钥
	buf := ReadKey(pubKeyFile)
	// 2.pem解码
	block, _ := pem.Decode(buf)
	// 3.使用x509对公钥还原
	key, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		panic("x509.ParsePKIXPublicKey err!")
	}
	publicKey, ok := key.(*ecdsa.PublicKey)
	if !ok {
		panic("key is not a ecdsa public key.")
	}
	// 4.对原始数据进行哈希运算
	hashText := sha1.Sum(plainText)
	// 5.签名认证
	var r, s big.Int
	// 把rText、sText转换成big.Int数据
	r.UnmarshalJSON(rText)
	s.UnmarshalJSON(sText)
	return ecdsa.Verify(publicKey, hashText[:], &r, &s)
}

测试:

func GenerateKey() {
    
    
	//---------------- 生成私钥 --------------
	// 1.使用ecdsa生成密钥对
	privateKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
	if err != nil {
    
    
		panic("ecdsa.GenerateKey err!")
	}
	// 2.使用x509进行序列化
	derText, err := x509.MarshalECPrivateKey(privateKey)
	if err != nil {
    
    
		panic("x509.MarshalECPrivateKey err!")
	}
	// 3.将derText写入pem.Block块中
	block := pem.Block{
    
    
		Type:    "ecdsa private key",
		Bytes: derText,
	}
	// 4.使用pem编码
	file, err := os.Create("ecc_private.pem")
	if err != nil {
    
    
		panic("os.Create err!")
	}
	defer file.Close()
	pem.Encode(file, &block)

	//---------------- 生成公钥 --------------
	// 1.得到公钥
	publicKey := privateKey.PublicKey
	// 2.使用x509对公钥进行序列化
	derText, err = x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
    
    
		panic("x509.MarshalPKIXPublicKey err!")
	}
	// 3.将derText放入pem.Block块中
	block = pem.Block{
    
    
		Type : "ecdsa public key",
		Bytes : derText,
	}
	// 4.使用pem编码
	file, err = os.Create("ecc_public.pem")
	if err != nil {
    
    
		panic("os.Create err!")
	}
	defer file.Close()
	pem.Encode(file, &block)
}

// 读取密钥文件内容
func ReadKey(keyFile string) []byte {
    
    
	file, err := os.Open(keyFile)
	if err != nil {
    
    
		panic("文件不存在!")
	}
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
    
    
		panic("file.Stat err!")
	}
	buf := make([]byte, fileInfo.Size())
	file.Read(buf)
	return buf
}

// 测试
func main() {
    
    
	GenerateKey()
	src := []byte("hello world")
	rText, sText := EccSignature(src, "ecc_private.pem")
	isSucc := EccVerify(src, rText, sText, "ecc_public.pem")
	fmt.Printf("签名认证是否成功:%t\n", isSucc)
}

二、证书

正确使用数字签名的一大前提是用于验证签名的公钥必须属于真正的发送者。即便数字签名算法再强大,如果你得到的公钥是伪造的,那么数字签名也会完全失效。为了能够确认自己得到的公钥是否合法,我们需要使用证书。

2.1 什么是证书

所谓证书,就是将公钥当作一条消息,由一个可信的第三方(比如ca)对其签名后所得到的文件。可以这样理解:
证 书 = 公 钥 + 数 字 签 名 证书 = 公钥 + 数字签名 =+

证书与驾照很相似,里面记有姓名、组织、邮箱地址等个人信息,以及属于此人的公钥,并由认证机构(比如ca)施加数字签名。只要看到证书,我们就可以知道认证机构认定该公钥的确属于此人。

可能很多人都没听说过认证机构,认证机构就是能够认定 “公钥确实属于此人",并能够生成数字签名的个人或者组织。认证机构中有国际性组织和政府所设立的组织,也有通过提供认证服务来盈利的一般企业。其中,全球最大的PKI/CA运营商是世界上最早出现的数字证书认证机构。

2.2 证书的应用场景

下图展示了Alice向Bob发送密文的场景,在生成密文时所使用的Bob的公钥是通过认证机构获取的。
在这里插入图片描述
第一步:Bob生成秘钥对;
第二步:Bob在认证机构Trent注册自己的公钥;
第三步:认证机构Trent用自己的私钥对Bob的公钥施加数字签名,并生成证书;
第四步:Alice下载证书,证书里面包含了Trent认证机构的数字签名和Bob的公钥;
第五步:Alice使用认证机构的公钥验证数字签名,确认Bob的公钥的合法性;
第六步:Alice用Bob的公钥加密消息得到密文后,把密文发送给Bob;
第七步:Bob使用自己的私钥对密文进行解密,得到Alice发送的消息;

2.3 证书标准规范x.509

X.509是密码学里公钥证书的格式标准,它是由ITU(国际电信联盟)和ISO(国际标准化组织)共同制定的规范。X.509 证书己应用在包括TLS/SSL在内的众多 Internet协议里,同时它也在很多非在线应用场景里使用,比如电子签名服务。一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。X.509标准定义了证书中应该包含哪些信息,并描述了这些信息的数据格式。一般来说,一个数字证书内容可能包括基本数据(版本、序列号) 、所签名对象信息( 签名算法类型、签发者信息、有效期、被签发人、签发的公开密钥)、CA的数字签名等等。

2.3.1 证书规范

目前X.509有不同的版本,例如 X.509 V2和x.509 v3都是目前比较新的版本,它们都是在原有版本(X.509 V1)的基础上进行功能的扩充。其中每一个版本都必须包含以下信息:

  • 版本号:
    用来区分X.509的不同版本号。

  • 序列号:
    CA给每个证书分配的唯一的编号,用来追踪和撤销证书。只要拥有签发者信息和序列号,就可以唯一标识一个证书,最大不能过20个字节。

  • 签名算法:
    用来指定用CA签发证书时所使用的签名算法(如sha256-with-RSA-Encryption、ccdsa-with-SHA2S6)。

  • 颁发者:
    发证书单位的标识信息。

  • 有效期:
    证书有效的时间包括两个日期:证书开始生效期和证书失效的日期和时间。在所指定的这两个时间之间有效。

  • 主体:
    证书拥有者的标识信息。如 “C=CN,ST=Beijing, L=Beijing, O=org.example.com,CN=ca.org。example.com ”。

  • 主体的公钥信息:
    包括被证明有效的公钥和使用这个公钥的方法名称。

  • 颁发者的唯一号:
    代表颁发者的唯一信息,仅2、3版本支持。

  • 主体的唯一号
    代表拥有证书实体的唯一信息,仅2,3版本支持。

  • x.509的扩展:

    • Subject Key Identifier:实体的秘钥标识符,区分实体的多对秘钥;
    • Basic Constraints:指明是否属于CA;
    • Authority Key Identifier:证书颁发者的公钥标识符;
    • CRL Distribution Points:撤销文件的颁发地址;
    • Key Usage:证书的用途或功能信息。

此外,证书的颁发者还需要对证书内容利用自己的私钥添加签名, 以防止别人对证书的内容进行篡改。

2.3.2 证书格式

X.509规范中一般推荐使用PEM(Privacy Enhanced Mail)格式来存储证书相关的文件。证书文件的文件名后缀一般为 .crt 或 .cer 。对应私钥文件的文件名后缀一般为 .key。证书请求文件的文件名后綴为 .csr 。有时候也统一用pem作为文件名后缀。

下面展示一个pem格式的证书文件内容:

-----BEGIN CERTIFICATE-----
MIIDyjCCArKgAwIBAgIQdZfkKrISoINLporOrZLXPTANBgkqhkiG9w0BAQsFADBn
MSswKQYDVQQLDCJDcmVhdGVkIGJ5IGh0dHA6Ly93d3cuZmlkZGxlcjIuY29tMRUw
EwYDVQQKDAxET19OT1RfVFJVU1QxITAfBgNVBAMMGERPX05PVF9UUlVTVF9GaWRk
bGVyUm9vdDAeFw0xNzA0MTExNjQ4MzhaFw0yMzA0MTExNjQ4MzhaMFoxKzApBgNV
BAsMIkNyZWF0ZWQgYnkgaHR0cDovL3d3dy5maWRkbGVyMi5jb20xFTATBgNVBAoM
DERPX05PVF9UUlVTVDEUMBIGA1UEAwwLKi5iYWlkdS5jb20wggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDX0AM198jxwRoKgwWsd9oj5vI0and9v9SB9Chl
gZEu6G9ZA0C7BucsBzJ2bl0Mf6qq0Iee1DfeydfEKyTmBKTafgb2DoQE3OHZjy0B
QTJrsOdf5s636W5gJp4f7CUYYA/3e1nxr/+AuG44Idlsi17TWodVKjsQhjzH+bK6
8ukQZyel1SgBeQOivzxXe0rhXzrocoeKZFmUxLkUpm+/mX1syDTdaCmQ6LT4KYYi
soKe4f+r2tLbUzPKxtk2F1v3ZLOjiRdzCOA27e5n88zdAFrCmMB4teG/azCSAH3g
Yb6vaAGaOnKyDLGunW51sSesWBpHceJnMfrhwxCjiv707JZtAgMBAAGjfzB9MA4G
A1UdDwEB/wQEAwIEsDATBgNVHSUEDDAKBggrBgEFBQcDATAWBgNVHREEDzANggsq
LmJhaWR1LmNvbTAfBgNVHSMEGDAWgBQ9UIffUQSuwWGOm+o74JffZJNadjAdBgNV
HQ4EFgQUQh8IksZqcMVmKrIibTHLbAgLRGgwDQYJKoZIhvcNAQELBQADggEBAC5Y
JndwXpm0W+9SUlQhAUSE9LZh+DzcSmlCWtBk+SKBwmAegbfNSf6CgCh0VY6iIhbn
GlszqgAOAqVMxAEDlR/YJTOlAUXFw8KICsWdvE01xtHqhk1tCK154Otci60Wu+tz
1t8999GPbJskecbRDGRDSA/gQGZJuL0rnmIuz3macSVn6tH7NwdoNeN68Uj3Qyt5
orYv1IFm8t55224ga8ac1y90hK4R5HcvN71aIjMKrikgynK0E+g45QypHRIe/z0S
/1W/6rqTgfN6OWc0c15hPeJbTtkntB5Fqd0sfsnKkW6jPsKQ+z/+vZ5XqzdlFupQ
29F14ei8ZHl9aLIHP5s=
-----END CERTIFICATE-----

PEM格式采用文本方式进行存储。一般包括首尾标记和内容块,内容块采用Base64进行编码。

通过对证书数据还原,可以得到以下内容:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            10:e6:fc:62:b7:41:8a:d5:00:5e:45:b6
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA-SHA256-G2
        Validity
            Not Before: Nov 21 08:00:00 2016 GMT
            Not After : Nov 22 07:59:59 2017 GMT
        Subject: C=US, ST=California, L=San Francisco, O=Wikimedia Foundation, Inc., CN=*.wikipedia.org
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub: 
                    04:c9:22:69:31:8a:d6:6c:ea:da:c3:7f:2c:ac:a5:
                    af:c0:02:ea:81:cb:65:b9:fd:0c:6d:46:5b:c9:1e:
                    ed:b2:ac:2a:1b:4a:ec:80:7b:e7:1a:51:e0:df:f7:
                    c7:4a:20:7b:91:4b:20:07:21:ce:cf:68:65:8c:c6:
                    9d:3b:ef:d5:c1
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Agreement
            Authority Information Access: 
                CA Issuers - URI:http://secure.globalsign.com/cacert/gsorganizationvalsha2g2r1.crt
                OCSP - URI:http://ocsp2.globalsign.com/gsorganizationvalsha2g2

            X509v3 Certificate Policies: 
                Policy: 1.3.6.1.4.1.4146.1.20
                  CPS: https://www.globalsign.com/repository/
                Policy: 2.23.140.1.2.2

            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 CRL Distribution Points: 

                Full Name:
                  URI:http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl

            X509v3 Subject Alternative Name: 
                DNS:*.wikipedia.org, DNS:*.m.mediawiki.org, DNS:*.m.wikibooks.org, DNS:*.m.wikidata.org, DNS:*.m.wikimedia.org, DNS:*.m.wikimediafoundation.org, DNS:*.m.wikinews.org, DNS:*.m.wikipedia.org, DNS:*.m.wikiquote.org, DNS:*.m.wikisource.org, DNS:*.m.wikiversity.org, DNS:*.m.wikivoyage.org, DNS:*.m.wiktionary.org, DNS:*.mediawiki.org, DNS:*.planet.wikimedia.org, DNS:*.wikibooks.org, DNS:*.wikidata.org, DNS:*.wikimedia.org, DNS:*.wikimediafoundation.org, DNS:*.wikinews.org, DNS:*.wikiquote.org, DNS:*.wikisource.org, DNS:*.wikiversity.org, DNS:*.wikivoyage.org, DNS:*.wiktionary.org, DNS:*.wmfusercontent.org, DNS:*.zero.wikipedia.org, DNS:mediawiki.org, DNS:w.wiki, DNS:wikibooks.org, DNS:wikidata.org, DNS:wikimedia.org, DNS:wikimediafoundation.org, DNS:wikinews.org, DNS:wikiquote.org, DNS:wikisource.org, DNS:wikiversity.org, DNS:wikivoyage.org, DNS:wiktionary.org, DNS:wmfusercontent.org, DNS:wikipedia.org
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Subject Key Identifier: 
                28:2A:26:2A:57:8B:3B:CE:B4:D6:AB:54:EF:D7:38:21:2C:49:5C:36
            X509v3 Authority Key Identifier: 
                keyid:96:DE:61:F1:BD:1C:16:29:53:1C:C0:CC:7D:3B:83:00:40:E6:1A:7C

    Signature Algorithm: sha256WithRSAEncryption
         8b:c3:ed:d1:9d:39:6f:af:40:72:bd:1e:18:5e:30:54:23:35:
         ...

2.3.3 CA证书

CA是Certificate Authority的缩写,也叫“证书授权中心”,它是负责管理和签发证书的第三方机构。一般来说,CA必须是所有行业和所有公众都信任的、认可的。因此它必须具有足够的权威性。

2.3.3.1 CA证书

CA 证书,顾名思义,就是CA颁发的证书。任何人都可以找工具制作证书。但是自己制作的证书不具有权威性,因此不会得到别人的认可。

2.3.3.2 证书信任链

多个证书之间可以建立信任关系。比如说,通过一个证书可以证明另一个证书也是真实可信的。而且,证书之间的信任关系是可以嵌套的。比如C 信任 A和B,A 信任 A1和A2,B 信任B1和B2,以此类推,这个叫做证书的信任链(如下图)。
在这里插入图片描述
处于最顶端的证书称为“根证书”。除了根证书,其它证书都要依靠上一级的证书来证明自己是可靠的。根证书是整个证书体系安全的根本。如果某个证书体系中的根证书出了问题,那么被根证书所信任的其它证书,也就不再可信了。

2.3.3.3 证书的作用

  • 验证网站是否可信
    通常,我们如果访问某些敏感的网页(比如用户登录的页面),其协议都会使用 HTTPS 而不是 HTTP。HTTPS 协议除了有加密的机制,还有一套证书的机制。通过证书来确保,某个站点确实就是某个站点。有了证书之后,当你的浏览器在访问某个 HTTPS 网站时,会验证该站点上的 CA 证书(类似于验证介绍信的公章)。如果浏览器发现该证书没有问题(证书被某个根证书信任、证书上绑定的域名和该网站的域名一致、证书没有过期),那么页面就直接打开;否则的话,浏览器会给出一个警告,告诉你该网站的证书存在某某问题。

  • 验证某个文件是否可信
    通过证书来制作文件的数字签名可以用来验证某个文件是否被篡改。

2.4 公钥基础设施(PKI)

仅制定证书的规范还不足以支持公钥的实际运用,我们还需要很多其他的规范,例如证书应该由谁来颁发,如何颁发,私钥泄露时应该如何作废证书,计算机之间的数据交换应采用怎样的格式等。

2.4.1 什么是公钥基础设施

公钥基础设施(Public-Key Infrastructure,简称KPI)是为了能够更有效地运用公钥而制定的一系列规范的总称。例如,RSA公司所制定的PKCS系列规范也是PKI的一种,而互联网规格RFC中也有很多与PKI相关的文档。此外,X.509这样的规范也是PKI的一种。在开发PKI程序时所使用的由各个公司编写的API接口和规格设计书也是PKI的相关规格。

国家、地方政府、医院、图书馆等公共组织和团体可以成立认证机构来实现PKI,公司也可以出于业务需要在内部实现PKI,甚至个人也可以以实验为目的来构建PKI。

2.4.2 PKI的组成

PKI的组成要素如下图所示:
在这里插入图片描述

  • 用户:使用PKI的人。用户包含两种:一种是希望使用PKI注册自己的公钥的人(如bob);另外一种是希望使用已注册的公钥的人(如Alice);
  • 认证机构CA:对证书进行管理的人(如Trent);
  • 仓库:仓库也叫作证书目录,是一个保存证书的数据库,PKI用户在需要的时候可以从仓库里面获取证书;

三、SSL/TLS

SSL(Secure Socket Layer)与TLS(Transport Layer Security)是世界上应用最广泛的密码通信方法。使用SSL/TLS可以对通信对象进行认证,还可以确保通信内容的机密性。比如说在网上银行中输人银行卡的账号时,浏览器就会使用SSL/TLS进行密码通信。

SSL/TLS中综合运用了之前所学习过的对称密码、消息认证码、公钥密码、数字签名、伪随机数生成器等密码技术。严格来说,SSL与TLS是不同的,TLS相当于是SSL的后续版本。但是大部分时候SSL和TLS是兼备的,因此通常统一写作SSL/TLS。

3.1 SSL/TLS的主要作用

  • 认证用户和服务器,保证各自的数据都发送到正确的位置上去;
  • 对发送的数据进行加密,保护数据;
  • 保证数据在发送过程中的完整性;

3.2 http和https协议

SSL/TLS是建立在数据传输层上的一层加密,它能够保证上层信息传输的安全。我们知道HTTP是不安全的,浏览器通过HTTP协议向服务端发送数据,数据是通过明文方式直接发送给服务端。于是,我们可以使用SSL/TLS作为对通信进行加密的协议,然后在此之上承載HTTP(如下图)。
在这里插入图片描述
通过将两种协议进行叠加,我们就可以对HTTP的通信进行加密,从而防止窃听。通过SSL/TLS进行通信时,URL不是以http://开头,而是以https://开头。

SSL/TLS除了可以承载HTTP通信以外,还可以承载其他许多协议。例如,发送邮件时使用的SMTP和接收邮件时使用的POP3都可以用SSL/TLS进行承载。在这样的情况下,SSL/TLS就可以对收发的邮件进行保护。用SSL/TLS承载HTTP、SMTP和POP3的结构如下图所示:
在这里插入图片描述

3.3 https的传输过程

在这里插入图片描述
第一步:客户端发起https请求,连接到服务端的443端口;
第二步:服务器将公钥和数字签名(证书)发送给客户端;
第三步:客户端开始解析证书,并对证书的合法性进行校验(比如公钥是否有效,证书是否过期等);
第四步:如果证书没有问题,那么客户端则通过随机数生成器,通过证书对生成的随机数进行非对称加密,并将加密后的密文发送给服务器;
第五步:服务器使用私钥对其进行非对称解密后,得到随机数;
第六步:服务器把响应数据通过该随机数进行对称加密后,发送给客户端;
第七步:客户端用之前生成的随机数对响应数据局进行解密后,得到明文;

3.4 http和https的区别

  1. http不需要证书,而https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用;
  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议;
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443;
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输;

3.5 https的优缺点

  • https的优点:
  1. 使用https协议能够确保数据发送到正确的客户端或服务器;
  2. https协议是由ssl+http协议所构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性;
  3. https是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本;
  4. 权值相同的站点,采用https协议的页面更加安全,排名上会优先对待。
  • https的缺点:
  1. https协议握手阶段比较费时,会延长页面的加载时间;
  2. https连接缓存不如http高效;
  3. ssl/tls证书需要钱,功能越强大的证书费用越高;
  4. ssl/tls证书通常需要绑定IP,不能在同一IP上绑定多个域名;
  5. https协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。还有一点,ssl证书的信用链体系并不安全,特别是在某些国家可以控制ca根证书的情况下,中间人攻击一样可行;

猜你喜欢

转载自blog.csdn.net/zhongliwen1981/article/details/104748514
今日推荐