公钥传输问题?
我们知道,通过用非对称加密对对称加密的密钥进行加密然后在网络中传输,解决了对称加密密钥的不安全传输问题,而非对称加密的公钥是不需要保密的,即可以在网络中传输。那么问题来了,公钥在传输的过程中有没有可能被攻击呢?答案是有的,假设攻击者在传输过程中劫持了发送方发送的公钥,用自己的公钥替代了真正的公钥,那么接收方收到的就是假的公钥,这样在密文传输过程中,接收方用的始终是假的公钥,同时劫持者也可以在网络中解密数据,从而达到攻击目的。
这样便引发了一个问题,如何验证公钥?
如何验证公钥?
-
发送方对公钥进行签名
发送方将自己的公钥签名后发送出去,接收方收到后用公钥进行签名验证,很明显,这样做也是不可靠的,原因跟上面提到的一样:公钥无法认证。
为此如果引入第三方认证机构(证书颁发机构(CA))进行中转如何呢? -
发送方自己生成密钥对,交由CA签名并发送给接收方
然后将自己的身份信息和公钥发送给CA,CA用自己的公私钥来签名收到公钥信息,然后发送给接收方,同样,这样做也不能避免发送方发送出来的
数据是可靠的,因为中间人可以对公钥进行替换。 -
申请者向CA发起密钥生成请求,由CA生成密钥并将密钥对发送给申请人,而其他人则需要安装证书才能与申请人进行数据传输
CA生成公钥-私钥对后通过自己的公钥对私钥或者公钥签名后发送给申请人,接收者用CA的公钥验证签名,然后收到数据。这样在整个过程中无论是发送方还是接收方都只需要一次认证即可,而CA的
公钥一般是提前安装在了PC上,所以对于CA的公钥,不存在传输隐患。注意:用于验证签名的CA公钥,我们称之为根证书。由证书颁发机构颁发,并被预先安装在电脑或者软件中。
证书内容
证书内容如下图:
![](https://img.haomeiwen.com/i1246138/3b332ebba42340ac.png)
1. 证书算法: 证书算法指明了使用的签名算法,比如使用SHA-1的RSA或者使用SHA-2的ECDSA,还指明了参数(比如位长度)
2. 颁发者: 证书是谁颁发的
3. 有效期: 为一段时间,指明证书有效期限
4. 主题: 包含证书申请人的身份信息,比如某个人或机构的名字
5. 主题的公钥: 指需要证书保护的公钥,除了公钥本身外,还包含算法和算法参数
6. 签名: 此签名覆盖了证书所有其他的域
注意,每个签名都包含两个公钥算法:一个是受保护的公钥算法,另一个被证书用来签名,且两个算法并无关联
证书申请
命令行生成
代码生成(Golang)
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"io/ioutil"
"math/big"
mRand "math/rand"
"net"
"os"
"time"
)
func main() {
//获取根证书
caBytes, err := ioutil.ReadFile("conf/root.cert")
if err != nil {
return
}
caBlock, _ := pem.Decode(caBytes)
rootCert, err := x509.ParseCertificate(caBlock.Bytes)
if err != nil {
return
}
privateKey, _ := rsa.GenerateKey(rand.Reader, 1024)
cert := x509.Certificate{
SerialNumber: big.NewInt(mRand.Int63()), //证书序列号
Subject: pkix.Name{ //这里填写证书主题
Country: []string{"cn"},
Organization: []string{"cn", "company"},
OrganizationalUnit: []string{"test"},
Locality: []string{"Beijing"},
Province: []string{"Beijing"},
StreetAddress: []string{"ChangAn Street"},
},
NotAfter: time.Now().Add(7 * 24 * time.Hour), //有效期
NotBefore: time.Now(),
BasicConstraintsValid: true, //
IsCA: false,
EmailAddresses: []string{"test@gmail.com"},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
}
//parent如果为自己则表示自签证书,此处表示CA签名的证书,如果是CA签发,则公钥需要是根证书的公钥
//certBytes, err := x509.CreateCertificate(rand.Reader, &cert, &cert, &privateKey.PublicKey, privateKey)
certBytes, err := x509.CreateCertificate(rand.Reader, &cert, rootCert, &rootCert.PublicKey, privateKey)
if err != nil {
return
}
file, err := os.Create("conf/cert.pem")
if err != nil {
return
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
if err = pem.Encode(file, block); err != nil {
return
}
file.Close()
block = &pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
}
file, err = os.Create("conf/private.pem")
if err = pem.Encode(file, block); err != nil {
return
}
file.Close()
}
引用资料
最后
这里只是关于证书的简要介绍,详细了解还需要阅读相关书籍。
原文连接
如有错误,还请指正!
Thanks!
附上代码链接[github.com/pyihe/secret]
网友评论