I am attempting to use a client certificate with curl. If I use a curl binary built against openssl or libressl, it works without issue. If I use a curl built with libnss, then it refuses to load the key with a SEC_ERROR_BAD_KEY
error. Is it possible to use this type of key with curl+libnss?
The private key in question is an EC key. The key file I am using looks like one that can be generated with the openssl ecparam -name prime256v1 | openssl ecparam -genkey
command. This example key is the same type of key that I am working with (but is not my actual key for obvious reasons). This is not a passphrase-protected key.
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDNhB9ml7mqEB0hHZpXkvG+TtAYKMpY87JsYdGzERmCVoAoGCCqGSM49
AwEHoUQDQgAEE/vPWzL6zPAkYQWGGJFnQwEJ6otQsI9Crqhek9KuvNRtFh73IJbp
U9NgcqNnRZf9vwaS8VWTBViDcufIsyuaxg==
-----END EC PRIVATE KEY-----
The known working command with a curl (from the ubuntu 18.04 repository)
$ curl --version
curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
Release-Date: 2018-01-24
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL
$ curl -v --cacert ./ca.pem --cert ./cert.pem --key ./key.pem https://192.168.73.51:443/_ping
* Trying 192.168.73.51...
* TCP_NODELAY set
* Connected to 192.168.73.51 (192.168.73.51) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: ./ca.pem
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: OU=ucp; CN=system:ucp:w581z5f7ny14uuz2zqvdvlmgy
* start date: Sep 12 18:45:00 2019 GMT
* expire date: Dec 11 18:45:00 2019 GMT
* subjectAltName: host "192.168.73.51" matched cert's IP address!
* issuer: CN=UCP Client Root CA
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55da2b525580)
Here's the same command with the same ca.pem, cert.pem, and key.pem files, but with a centos 7 curl+libnss binary:
$ curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.36 zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
$ curl -v --cacert ./ca.pem --cert ./cert.pem --key ./key.pem https://192.168.73.51:443/_ping
* About to connect() to 192.168.73.51 port 443 (#0)
* Trying 192.168.73.51...
* Connected to 192.168.73.51 (192.168.73.51) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: ./ca.pem
CApath: none
* unable to load client key: -8178 (SEC_ERROR_BAD_KEY)
* NSS error -8178 (SEC_ERROR_BAD_KEY)
* Peer's public key is invalid.
* Closing connection 0
curl: (58) unable to load client key: -8178 (SEC_ERROR_BAD_KEY)