<h1>Problem</h1>
<p>I have generated keys and certificates by OpenSSL with the secp256k1, run <code>rke</code> version v1.2.8 from the Rancher Kubernetes Engine (RKE), and got the following error:</p>
<pre><code>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
</code></pre>
<p><code>kubectl version</code>:</p>
<pre><code>Client Version: version.Info{Major:&quot;1&quot;, Minor:&quot;21&quot;, GitVersion:&quot;v1.21.1&quot;, GitCommit:&quot;5e58841cce77d4bc13713ad2b91fa0d961e69192&quot;, GitTreeState:&quot;clean&quot;, BuildDate:&quot;2021-05-12T14:18:45Z&quot;, GoVersion:&quot;go1.16.4&quot;, Compiler:&quot;gc&quot;, Platform:&quot;linux/amd64&quot;}
</code></pre>
<p>I have generated the root CA key and certificate the following way:</p>
<pre><code>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
</code></pre>
<p>Then I used it to sign the CSRs generated by <code>rke cert generate-csr</code> from my Kubernetes Rancher <code>cluster.yml</code>.</p>
<p>The command line to approve a CSR was the following:</p>
<pre><code>openssl ca -config openssl.cnf -batch -in %1 -out %2 -create_serial -notext -rand random.bin -writerand random.bin
</code></pre>
<h1>Question</h1>
<p>Which curves are supported today by Kubernetes for the certificates if <code>secp256k1</code> yields the <code>x509: unsupported elliptic curve</code> error message?</p>
<h1>P.S.</h1>
<p>I have also tried the <code>prime256v1</code>, also known as <code>secp256r1</code>. It progressed further comparing to <code>secp256k1</code>, but still got an error.</p>
<p>With  <code>prime256v1</code>, RKE did not complain <code>x509: unsupported elliptic curve</code>.</p>
<p>Instead, it gave an error <code>panic: interface conversion: interface {} is *ecdsa.PrivateKey, not *rsa.PrivateKey</code>. Here is the full error message:</p>
<p>Here is the full error message:</p>
<pre><code>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
</code></pre>

Maxim Masiutin
<blockquote>
<p>Which curves are supported today by Kubernetes for the certificates if <code>secp256k1</code> yields the <code>x509: unsupported elliptic curve</code> error message?</p>
</blockquote>
<p>To try to answer this question I will look directly at the <a href="https://go.googlesource.com/go/+/8bf6e09f4cbb0242039dd4602f1f2d58e30e0f26/src/crypto/x509/x509.go" rel="noreferrer">source code</a>. You can find there lines, that gives an error <code>unsupported elliptic curve</code>:</p>
<pre><code>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(&quot;x509: unsupported elliptic curve&quot;)
        }
</code></pre>
<p>There are two functions here that are responsible for processing the curve:</p>
<ul>
<li>Marshal:</li>
</ul>
<pre><code>// 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
}
</code></pre>
<ul>
<li>oidFromNamedCurve:</li>
</ul>
<pre><code>// 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
}
</code></pre>
<p>The final answer is therefore in the switch. Supported elliptic curves are:</p>
<ul>
<li><a href="https://golang.org/pkg/crypto/elliptic/#P224" rel="noreferrer">elliptic.P224</a></li>
<li><a href="https://golang.org/pkg/crypto/elliptic/#P521" rel="noreferrer">elliptic.P256</a></li>
<li><a href="https://golang.org/pkg/crypto/elliptic/#P384" rel="noreferrer">elliptic.P384</a></li>
<li><a href="https://golang.org/pkg/crypto/elliptic/#P521" rel="noreferrer">elliptic.P521</a></li>
<li>secp192r1</li>
</ul>
<p>You need to  change your curve to <code>secp256r1</code>. The main difference is that <code>secp256k1</code> is a Koblitz curve, while <code>secp256r1</code> is not. Koblitz curves are known to be a few bits weaker than other curves.</p>
<blockquote>
<p>OpenSSL supports &quot;secp256r1&quot;, it is just called &quot;prime256v1&quot;. Check section 2.1.1.1 in RFC 5480, where the &quot;secp192r1&quot; curve is called &quot;prime192v1&quot; and the &quot;secp256r1&quot; curve is called &quot;prime256v1&quot;.</p>
</blockquote>
