跳到主要内容
ecdsa.com
Go crypto/x509Go

错误信息

x509: certificate specifies an incompatible key usage

也可能输出为

  • tls: failed to verify certificate: x509: certificate specifies an incompatible key usage

TLS 客户端会加上“tls: failed to verify certificate: ”前缀;验证客户端证书的 Go 服务器会记录“http: TLS handshake error from <addr>: tls: failed to verify certificate: x509: certificate specifies an incompatible key usage”。

Go crypto/x509 — CertificateInvalidError (IncompatibleUsage): extendedKeyUsage does not allow this role

含义

证书链是受信任的,但证书的 extendedKeyUsage(或者中间证书的 extendedKeyUsage,Go 也会检查它)不允许证书承担当前的角色:服务器证书缺少 serverAuth,或者双向 TLS 中的客户端证书缺少 clientAuth。Go 严格执行 EKU 检查;其他一些 TLS 实现更宽松,因此同一张证书在别处可能可以正常使用。

原因

修复方法

  1. 1.

    查看每张证书的 extendedKeyUsage

    检查叶子证书和每张中间证书;你需要的用途必须在整条路径上都被允许。

    bash
    # Leaf and intermediates: which purposes do they allow?
    openssl x509 -in server.pem -noout -ext extendedKeyUsage,keyUsage
    #   TLS Web Server Authentication = serverAuth, TLS Web Client Authentication = clientAuth
  2. 2.

    使用正确的 EKU 重新签发

    服务器证书使用 serverAuth,客户端证书使用 clientAuth(如果一张证书确实必须同时承担两种角色,就两者都加上)。

    bash
    # Server certificates need serverAuth; for mutual TLS client certificates need clientAuth
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com" -addext "extendedKeyUsage=serverAuth"
  3. 3.

    双向 TLS:签发带 clientAuth 的客户端证书

    设置了 RequireAndVerifyClientCert 的 Go 服务器会检查客户端证书的 EKU 中是否有 clientAuth。

    go
    // Go server verifying client certificates: they need clientAuth (or no EKU at all)
    cfg := &tls.Config{
    	ClientAuth: tls.RequireAndVerifyClientCert,
    	ClientCAs:  clientCAPool,
    }

相关错误

浏览完整的签名错误库