Kubernetes 证书支持哪些椭圆曲线?

Posted

技术标签:

【中文标题】Kubernetes 证书支持哪些椭圆曲线?【英文标题】:Which of the Elliptic Curves are supported for the Rancher Kubernetes certificates? 【发布时间】:2021-08-31 20:40:12 【问题描述】:

问题

我用secp256k1生成了密钥和证书,运行rke v1.2.8版本,得到如下错误:

FATA[0000] Failed to read certificates from dir [/home/max/cluster_certs]: failed to read certificate [kube-apiserver-requestheader-ca.pem]: x509: unsupported elliptic curve

kubectl version:

Client Version: version.InfoMajor:"1", Minor:"21", GitVersion:"v1.21.1", GitCommit:"5e58841cce77d4bc13713ad2b91fa0d961e69192", GitTreeState:"clean", BuildDate:"2021-05-12T14:18:45Z", GoVersion:"go1.16.4", Compiler:"gc", Platform:"linux/amd64"

我通过以下方式生成了根 CA 密钥和证书:

openssl ecparam -name secp256k1 -genkey -noout -out ca-pvt.pem -rand random.bin -writerand random.bin
openssl req -config .\openssl.cnf -x509 -sha256 -new -nodes -key ca-pvt.pem -days 10227 -out ca-cert.cer -rand random.bin -writerand random.bin

然后我用它来签署由我的 Kubernetes Rancher cluster.yml 中的 rke cert generate-csr 生成的 CSR。

批准 CSR 的命令行如下:

openssl ca -config openssl.cnf -batch -in %1 -out %2 -create_serial -notext -rand random.bin -writerand random.bin

问题

如果secp256k1 产生x509: unsupported elliptic curve 错误消息,Kubernetes 目前支持哪些曲线用于证书?

附言

我也试过prime256v1,也称为secp256r1。与secp256k1 相比,它进一步发展,但仍然出现错误。

有了prime256v1,RKE 没有抱怨x509: unsupported elliptic curve

相反,它给出了错误panic: interface conversion: interface is *ecdsa.PrivateKey, not *rsa.PrivateKey。以下是完整的错误信息:

这是完整的错误信息:

DEBU[0000] Certificate file [./cluster_certs/kube-apiserver-requestheader-ca.pem] content is greater than 0 
panic: interface conversion: interface  is *ecdsa.PrivateKey, not *rsa.PrivateKey 
goroutine 1 [running]: github.com/rancher/rke/pki.getKeyFromFile(0x7ffe6294c74e, 0xf, 0xc00105cb10, 0x27, 0x8, 0xc00105cb10, 0x27) 
/go/src/github.com/rancher/rke/pki/util.go:656 +0x212

【问题讨论】:

嗨@MaximMasiutin,您是否尝试将您的曲线更改为secp256r1?主要区别在于 secp256k1 是 Koblitz 曲线,而 secp256r1 不是。众所周知,Koblitz 曲线比其他曲线弱一些。 你也可以试试曲线prime256v1 @MikołajGłodziak - 你是对的,如果我指定“secp256r1”,OpenSSL 会给出以下消息:using curve name prime256v1 instead of secp256r1。 OpenSSL 支持“secp256r1”,它只是称为“prime256v1”。查看 RFC 5480 中的第 2.1.1.1 节,其中“secp192r1”曲线称为“prime192v1”,“secp256r1”曲线称为“prime256v1”。 您的问题现在解决了吗? 我已经安装了一个带有RSA的集群,所以我现在需要设置一个测试环境来测试EC曲线(ECDSA)而不是RSA,以便更快地运行。我会尽快通知你。 【参考方案1】:

如果secp256k1 产生x509: unsupported elliptic curve 错误消息,Kubernetes 目前支持哪些曲线用于证书?

为了回答这个问题,我将直接查看source code。你可以在那里找到错误unsupported elliptic curve:

case *ecdsa.PublicKey:
        publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
        oid, ok := oidFromNamedCurve(pub.Curve)
        if !ok 
            return nil, pkix.AlgorithmIdentifier, errors.New("x509: unsupported elliptic curve")
        

这里有两个函数负责处理曲线:

元帅:
// Marshal converts a point on the curve into the uncompressed form specified in
// section 4.3.6 of ANSI X9.62.
func Marshal(curve Curve, x, y *big.Int) []byte 
    byteLen := (curve.Params().BitSize + 7) / 8

    ret := make([]byte, 1+2*byteLen)
    ret[0] = 4 // uncompressed point

    x.FillBytes(ret[1 : 1+byteLen])
    y.FillBytes(ret[1+byteLen : 1+2*byteLen])

    return ret

oidFromNamedCurve:
// OIDFromNamedCurve returns the OID used to specify the use of the given
// elliptic curve.
func OIDFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) 
    switch curve 
    case elliptic.P224():
        return OIDNamedCurveP224, true
    case elliptic.P256():
        return OIDNamedCurveP256, true
    case elliptic.P384():
        return OIDNamedCurveP384, true
    case elliptic.P521():
        return OIDNamedCurveP521, true
    case secp192r1():
        return OIDNamedCurveP192, true
    

    return nil, false

因此,最终的答案在 switch 中。支持的椭圆曲线有:

elliptic.P224 elliptic.P256 elliptic.P384 elliptic.P521 secp192r1

您需要将曲线更改为secp256r1。主要区别在于 secp256k1 是 Koblitz 曲线,而 secp256r1 不是。众所周知,Koblitz 曲线比其他曲线弱一些。

OpenSSL 支持“secp256r1”,它只是称为“prime256v1”。查看 RFC 5480 中的第 2.1.1.1 节,其中“secp192r1”曲线称为“prime192v1”,“secp256r1”曲线称为“prime256v1”。

【讨论】:

ECDSA 密钥似乎不被支持。我尝试使用 ECDSA 制作 CA 密钥文件(kube-service-account-token-key.pem 和 kube-apiserver-requestheader-ca-key.pem - 两者具有相同的内容)并得到以下错误: DEBU[0000] 证书文件 [./cluster_certs/kube-apiserver-requestheader-ca.pem] 内容大于 0 panic: interface conversion: interface is *ecdsa.PrivateKey, not * rsa.PrivateKey goroutine 1 [运行]: github.com/rancher/rke/pki.getKeyFromFile(0x7ffe6294c74e, 0xf, 0xc00105cb10, 0x27, 0x8, 0xc00105cb10, 0x27) /go/src/github.com/rancher/rke/pki/ util.go:656 +0x212 但是,当我使用 RSA 生成 CA 密钥(kube-service-account-token-key.pem 和 kube-apiserver-requestheader-ca-key.pem)时,除了算法 - 它有效。 我已经给你一个源代码的链接。在我的回答所基于的同一个函数中,您会找到line:return nil, pkix.AlgorithmIdentifier, errors.New("x509: only RSA and ECDSA public keys supported")。支持基于此 ECDSA 密钥。

以上是关于Kubernetes 证书支持哪些椭圆曲线?的主要内容,如果未能解决你的问题,请参考以下文章

最近的 Java 升级导致椭圆曲线服务器证书的 TLS 握手失败?

为 TLS 禁用除 secp256 之外的所有椭圆曲线?

ECC椭圆曲线加密

抛物线 椭圆 双曲线的光学性质是啥?怎样证明

抛物线 椭圆 双曲线的光学性质是啥?怎样证明?

椭圆曲线加密