如何用JavaScript手动验证自建CA签发的SSL自签名证书签名?
如何验证自签名服务器证书
你的理解完全没错——服务器证书(server.cert)确实是由CA私钥签名生成的,验证环节也确实需要用到包含CA公钥的ca.crt。我给你拆解成原理逻辑和实操步骤两部分,帮你把整个流程理清楚:
核心验证逻辑(先搞懂为什么这么做)
本质上就是反向还原签名的过程:
- 从
server.cert里提取出待签名的明文内容(行业里叫TBS证书,包含服务器公钥、有效期、域名信息等核心内容),用和签名时一致的哈希算法(比如SHA256)计算它的哈希值,记为明文哈希。 - 从
server.cert里提取出CA的签名值,用ca.crt里的CA公钥对这个签名值解密,得到CA当初签名时计算的哈希值,记为解密哈希。 - 对比两个哈希值:如果完全一致,就证明证书没有被篡改,且确实是由你信任的这个CA私钥签发的——验证通过。
手动验证实操(用OpenSSL命令行)
如果想动手实操验证,用OpenSSL工具最直接,步骤如下:
步骤1:提取证书明文并计算哈希
先导出证书里的待签名部分,再计算哈希:
# 导出待签名的证书明文(DER格式)到临时文件 openssl x509 -in server.cert -outform der -out tbs.der -noout -text -certopt no_signature # 用SHA256计算哈希(如果签名时用的是SHA1,就把sha256换成sha1) openssl dgst -sha256 tbs.der
得到的十六进制字符串就是明文哈希。
步骤2:提取签名值并用CA公钥解密
接下来提取证书里的签名,再用CA公钥解密出原始哈希:
# 提取证书的签名值(DER格式)到临时文件 openssl x509 -in server.cert -outform der -out signature.der -noout -text -certopt no_cert,no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_subject,no_pubkey,no_sigdump,no_aux # 用CA公钥解密签名,得到原始哈希文件 openssl rsautl -verify -in signature.der -inkey ca.crt -pubin -out decrypted_hash.bin # 把解密后的哈希转成十六进制方便对比 xxd -p decrypted_hash.bin
得到的十六进制字符串就是解密哈希。
步骤3:对比两个哈希值
把步骤1和步骤2得到的十六进制字符串对比,如果完全一致,就说明这个服务器证书是合法的。
补充:客户端自动验证的逻辑
如果是在代码或者浏览器里做自动验证,底层逻辑和上面完全一致:客户端会先检查本地是否信任对应的CA(也就是有没有导入ca.crt),然后自动执行哈希计算、签名解密、哈希对比,同时还会额外检查证书的有效期、主题是否匹配服务器域名等细节。
内容的提问来源于stack exchange,提问作者toto
相关产品推荐
相关产品推荐

