Unity 证书校验

一:证书校验的流程

在TLS/SSL握手阶段,完整的证书校验流程如下:

  1. 客户端发送ClientHello消息,包含支持的TLS版本、加密套件等信息
  2. 服务端响应ServerHello消息,并附带完整的证书链(通常包括叶子证书和中间证书)
  3. 客户端操作系统或应用内置的信任库会进行以下校验:
    • 证书链完整性验证:检查中间证书是否由可信根证书签发
    • 有效期检查:确认证书在有效期内
    • 域名匹配:验证证书中的CN或SAN字段是否包含请求的域名
    • CRL/OCSP检查(可选):查询证书吊销状态
  4. 若任一校验失败,客户端将终止连接并抛出安全警告

二:系统默认的证书校验

操作系统默认会执行多层校验:

  • 基础校验:
    • 证书格式合规性检查
    • 签名算法强度验证
    • 有效期检查(Not Before/Not After)
  • 中级校验:
    • 证书链验证(从叶子证书到根证书的完整链路)
    • 主机名验证(支持精确匹配和通配符匹配)
  • 高级校验(可选配置):
    • 证书透明度(CT)日志验证
    • 证书策略(CP/CPS)检查

三:服务端返回的证书信息

现代Web服务器返回的证书包通常包含:

  • 主证书(叶子证书):
    • 包含服务器公钥
    • 明确绑定的域名(CN/SAN)
    • 由中间CA签发
  • 中间证书(Intermediate CA):
    • 用于构建证书链
    • 由根CA签发
  • 扩展信息(可选):
    • OCSP响应
    • SCT(证书透明度)证明

根证书通常不包含在服务器响应中,因为主流操作系统和浏览器都内置了常见根证书库。

四:证书层级关系详解

典型的三层证书体系:

  1. 根证书(Root CA):
    • 自签名证书
    • 预装在操作系统/浏览器中
    • 示例:DigiCert Global Root CA
  2. 中间证书(Intermediate CA):
    • 由根证书签发
    • 可以签发多个叶子证书
    • 示例:DigiCert SHA2 Secure Server CA
  3. 叶子证书(End-entity):
    • 绑定具体域名
    • 包含服务器公钥
    • 示例:api.example.com的SSL证书

这种层级设计既保证了安全性(根证书离线存储),又提供了灵活性(中间证书可轮换)。

五:证书类型识别方法

可通过以下字段区分证书类型:

  • 根证书:

    复制代码
    Issuer: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
    Subject: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US

    (Issuer和Subject相同)

  • 中间证书:

    复制代码
    Issuer: CN=DigiCert Global Root CA
    Subject: CN=DigiCert SHA2 Secure Server CA

    (Issuer指向根证书,Subject为中间CA名称)

六:证书校验技术详解

DER(Distinguished Encoding Rules):

  • ASN.1的二进制编码格式
  • 浏览器实际传输的证书格式
  • 查看方法:openssl x509 -in cert.crt -inform der -text

指纹校验(Certificate Fingerprint):

复制代码
// 计算示例:
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(cert.getEncoded());
String fingerprint = bytesToHex(digest); // 转换为HEX字符串

特点:

  • 证书任何改动都会改变指纹
  • 适用于严格固定证书场景

SPKI(Subject Public Key Info)Pin:

复制代码
# 计算示例:
from hashlib import sha256
import base64

pubkey = cert.public_key().public_bytes(
    encoding=serialization.Encoding.DER,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)
pin = base64.b64encode(sha256(pubkey).digest())

优势:

  • 允许证书轮换(只要公钥不变)
  • 兼容证书自动续期

七:证书校验最佳实践

生产环境推荐组合方案:

  1. 基础层:系统默认校验(证书链+域名)
  2. 增强层:SPKI Pin(防止中间人攻击)
  3. 监控层:证书透明度校验(预防错误签发)
  1. Unity证书校验实现

增强型校验示例:

复制代码
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

class CustomCertificateHandler : CertificateHandler
{
    // 可信指纹库(可配置多个备份证书)
    private static readonly HashSet<string> TRUSTED_FINGERPRINTS = new()
    {
        "E3:5D:28:41:...", // 主证书
        "A1:B2:C3:D4:..."  // 备用证书
    };

    protected override bool ValidateCertificate(byte[] certificateData)
    {
        #if UNITY_EDITOR || DEVELOPMENT_BUILD
            return true; // 开发环境跳过校验
        #endif

        try {
            using var cert = new X509Certificate2(certificateData);
            
            // 基础校验
            if (DateTime.Now < cert.NotBefore || DateTime.Now > cert.NotAfter)
                return false;

            // 增强校验
            var fingerprint = cert.GetCertHashString(HashAlgorithmName.SHA256);
            return TRUSTED_FINGERPRINTS.Contains(fingerprint);
        }
        catch {
            return false;
        }
    }
}

实现建议:

  • 使用哈希集合支持多证书
  • 添加有效期二次验证
  • 区分开发/生产环境
  • 错误处理机制
相关推荐
mxwin4 小时前
Unity Shader 切线空间数据是如何计算出来的
unity·游戏引擎·shader
mxwin7 小时前
Unity Shader 法线贴图跟切线空间有什么关系
unity·游戏引擎·贴图·shader
mxwin7 小时前
Unity Shader 贴图和采样的关系 如何保证贴图清晰
unity·游戏引擎·贴图·shader
心前阳光9 小时前
Unity之使用火山引擎实现文字提问流式回复
unity·游戏引擎·火山引擎
mxwin12 小时前
Unity Shader 什么是球谐光照 原理是什么
unity·游戏引擎·shader
心前阳光12 小时前
Unity之使用火山引擎实现语音识别
unity·语音识别·火山引擎
心前阳光12 小时前
Unity之使用火山引擎实现流式语音合成
unity·游戏引擎·火山引擎
心前阳光13 小时前
Unity之使用火山引擎实现音频剪辑提问,流式语音回复
unity·音视频·火山引擎