I have created a root certificate, an intermediate certificate, and a server certificate:
root (ca.cert.pem)
|
+---intermediate (intermediate/certs/intermediate.cert.pem)
|
+---www.example.com
↳ certificate: (intermediate/certs/www.example.com.cert.pem)
↳ private key: (intermediate/private/www.example.com.key.pem)
I use the private key and public certificate for www.example.com
to create an HTTPS server using Node:
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('intermediate/private/www.example.com.key.pem'),
cert: fs.readFileSync('intermediate/certs/www.example.com.cert.pem')
};
tls.createServer(options, function (s) {
s.write("welcome!\n");
s.pipe(s);
}).listen(8000);
I want to verify that if a client has access to the root certificate (ca.cert.pem
) it can successfully send a secure request to https://www.example.com:8000
.
If I try:
$ curl -v --cacert certs/ca.cert.pem https://www.example.com:8000
It fails with an error message:
* Rebuilt URL to: https://www.example.com:8000/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to www.example.com (127.0.0.1) port 8000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /certs/ca.cert.pem
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* NPN, no overlap, use HTTP1.1
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* stopped the pause stream!
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
However if I create a certificate chain:
$ cat intermediate/certs/intermediate.cert.pem \
certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
And use that as curl's --cacert
, everything works as expected:
$ curl -v --cacert intermediate/certs/ca-chain.cert.pem https://www.example.com:8000
* Rebuilt URL to: https://www.example.com:8000/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to www.example.com (127.0.0.1) port 8000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /intermediate/certs/ca-chain.cert.pem
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* NPN, no overlap, use HTTP1.1
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Unknown (67):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=AU; ST=Victoria; L=Melbourne; O=ACME; OU=ACME Web; CN=www.example.com; [email protected]
* start date: Nov 12 11:32:59 2018 GMT
* expire date: Nov 22 11:32:59 2019 GMT
* common name: www.example.com (matched)
* issuer: C=AU; ST=Victoria; O=ACME; OU=ACME Certificate Authority; CN=ACME Intermediate CA; [email protected]
* SSL certificate verify ok.
> GET / HTTP/1.1
> Host: www.example.com:8000
> User-Agent: curl/7.58.0
> Accept: */*
>
welcome!
GET / HTTP/1.1
Host: www.example.com:8000
User-Agent: curl/7.58.0
Accept: */*
If I am not wrong, similar to browsers, curl should only need the root certificate to verify the signature of the SSL certificate for www.example.com
. So why does curl
expect both of the root and intermediate certificates in order to be able to verify that it is indeed communicating with the correct server?
The PEM files
Here is the content of the PEM files used in this setup (throw away, unencrypted PEM files):
ca.cert.pem
-----BEGIN CERTIFICATE-----
MIIGKDCCBBCgAwIBAgIJAI6dJpvVkggoMA0GCSqGSIb3DQEBCwUAMIGgMQswCQYD
VQQGEwJBVTERMA8GA1UECAwIVmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTEN
MAsGA1UECgwEQUNNRTEjMCEGA1UECwwaQUNNRSBDZXJ0aWZpY2F0ZSBBdXRob3Jp
dHkxFTATBgNVBAMMDEFDTUUgUm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQYWNtZUBl
eGFtcGxlLmNvbTAeFw0xODExMTIxMTAzMzJaFw0zODExMDcxMTAzMzJaMIGgMQsw
CQYDVQQGEwJBVTERMA8GA1UECAwIVmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJu
ZTENMAsGA1UECgwEQUNNRTEjMCEGA1UECwwaQUNNRSBDZXJ0aWZpY2F0ZSBBdXRo
b3JpdHkxFTATBgNVBAMMDEFDTUUgUm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQYWNt
ZUBleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALu1
CZdb6GuJ9Rg/IUr5pp1EDn0d7NzflzH2F4Pe9dSpLqPP7ntW+pPDwWFjEfaz9LUH
yS41GxjPGMDZiQvL8G6gEWKXZkqGoHouzKnaB/49XqKgZoVHLyhwDd4Bj+89tj36
Qsfv+qNAG6Dq7mB9DvJMs/ZvyGb94AbwRuSJYurBbOGmrQjm22wfVCTybGPBrq66
8y2ff0bk9rBDdSI1v4jW0xvF7lztg/sZO/a7Yg1PbcH/B+bPitWf458Xe2MFsL7P
ZqGvvQv9+xuyqbTiBJg1iPiU5FQ6LwI94N99TIHXG2B/j9vxlLOG7jmX55sIY24r
SmHdF6aMkxcp3jiEusx1knbtXZpzJIyB/VBKb9iM2DUMXFw27fSq0WGCEHJjsykF
Aj67IDlU2kcORJHtfTnchyTBrPGf6XewQw2Ah4Q7Ct1wX/8iAWGzm487uOmgaKzJ
YLGN+GQd7EKlKL+XZeGgVNoNdtazogvPnm87wm9RSES0oUYLa29Vl94Ui1oezkD3
z9bBjAGyJOcz5ssYsEEeF9EE4P2t+KnMA+Y5lmS1Nwu6klarXzrSo+nHuF7YcYbT
kIEfFkBmZiKwiprfeAWkEmAP+1MS9xJA+OAwT1zZf/Bb7VHQNJZKTk9l/CnRd2Q4
sMpYAI8dS6bG1+KXk0/cJcxEmS5BCPxZPKNkMKcRAgMBAAGjYzBhMB0GA1UdDgQW
BBSIXku6n3PndN1U4VN/CHaU71sI3TAfBgNVHSMEGDAWgBSIXku6n3PndN1U4VN/
CHaU71sI3TAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
9w0BAQsFAAOCAgEAS1BNWdgbZR/aOvYNxcT1LgypVJ8HrRV/k6v/Lc1uaUdhEIS6
x3Ot+z8KkreaRuHSdeDL8QMwhL/bPVptxrPctx6KzCimuHsVN25zl7mkUlPaxluZ
9E4DGUNTE75lE//4af96CoWoS8QycXuh/RLb+dryMW9CuT7sAEylNxMmoDBCSzen
AZ4mVrVtUG0AnRCyTS+nqCaHN3eiQtR0gRObihhm3JGJtXJzNJOdHjzCggCuSXXv
+/IqihSnL9b5ruGzKdqIInAeTGkZubD32f7CmJUwNlZqsiMCgBbk5IpaPnP5j8gu
Cs2FT6Md5JdlNzQItFa6rPe6YeCKPeeYZl7VEYuSvXgHWnDlOQkzqWHIAypEEkiF
Qm9BdXZhLMBgLtL9QRiiQAPEK4RrBhEUmDBw2csDUJXqzQbnB34j5Dpv2tNO6JsP
54ldknoDoHOj2YaHzGuwh69lrUQbhMvjE8OoCjy09Vk5FPWFU2VjeTacm0CrUtZc
MSmGCJyYsNb10coWvuN7iMfTRc2fsWtMgaOIFzy5pgfNuU6Xaus3IbP4gCD+Kt/B
+q9Vsquj9wun2CVOx8hpnvJvv4Z5nzRjg0KrtHzjDWksPc0WzM0sfUx0dTZtIUbx
luj5eIVgzlxxk2mvM7vScntK13JMSpKr/cZCLWbtLgwj2JIEZLaYMWATYDA=
-----END CERTIFICATE-----
intermediate.cert.pem
-----BEGIN CERTIFICATE-----
MIIGHDCCBASgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAkFV
MREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJTWVsYm91cm5lMQ0wCwYDVQQK
DARBQ01FMSMwIQYDVQQLDBpBQ01FIENlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMG
A1UEAwwMQUNNRSBSb290IENBMR8wHQYJKoZIhvcNAQkBFhBhY21lQGV4YW1wbGUu
Y29tMB4XDTE4MTExMjExMTkzMFoXDTI4MTEwOTExMTkzMFowgZgxCzAJBgNVBAYT
AkFVMREwDwYDVQQIDAhWaWN0b3JpYTENMAsGA1UECgwEQUNNRTEjMCEGA1UECwwa
QUNNRSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHTAbBgNVBAMMFEFDTUUgSW50ZXJt
ZWRpYXRlIENBMSMwIQYJKoZIhvcNAQkBFhRjb250YWN0MkBleGFtcGxlLmNvbTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMTPJPqNRkRTkI7x4q6OWvwa
Mn7nqRYxzCDLLoR1mgaHJWDZ12vsNpcv/JzFem4zBDgQOmX9DAxs++SRVvj6EUjg
mNV3yPMAzAwBjn+fzmRMXcECEsOyPIZpTz6E8i0k8ULaGty0mHa1iPi4m6VYdLAL
OCMSJD9CYanUV6DmXUIBibMOXt+cdLWRIJa+Z4pGpuAkYQFAgy/kdf+H6VHzgdxM
V6+UysbI6vt5qiMf8sxQV1RwG8JoklO6B9XKcF/YCMi7gcwPNvN7utcfr6KyPenX
mSKtxo2PyhLtY+LWrSKqFtASfaR+7fvBDWzyjIleh0lvtu3LyKMFleM6fqhRpBTG
yE4qcCcN5b2TYafB+0kFWLllE/UvePBLOFxuJTquUyY+L5Qrmtt7a++7DNadma2y
LZOPZWTZv7aiC5QnaULpeBMXfGMp2Q9ibtgz0QuNye2KLMLI/SWPqOq/90QOAmow
3sJJDGstxDd6mOwwwPihNTpMHTi6Ac6l5GFBPUGAO5FJI2soC3VPPAiE5d8/N4Ho
VUeCN6ep8WINM6lMVfJqsq4MUeH7ABZdszpN4VTjXvxAgw3KEsiyiuDgDFpbqexJ
y/cJjyD+vR5q9tuk/UTxc0H3evhKJ9QE8gmDQj9ry1VrsWxjrCNXLYwSwnF0Qwy1
r2u4pmjerjcKsknGr/UhAgMBAAGjZjBkMB0GA1UdDgQWBBRVqxMd51KcVmXJ3tYT
9iJLIuHPGDAfBgNVHSMEGDAWgBSIXku6n3PndN1U4VN/CHaU71sI3TASBgNVHRMB
Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA
UlAnA7LUrSUV6X7VtpUkmb/GaCGJGd0GOHEc3VZpHk95vVnC3k9lz0kgUEz2OkKw
apsFAw5yOtjeUUpJmKTev52tuu/NghdQqEk1K9Vn2mlfqf2WV2vzjdlKN0QjUvsu
sQPgbJ8XqZjBWwXi8v/9OWGdVWjXqicTpikniP4l0nBmyWuo22JwUPRNhXzSZJvf
VZngtwYE4PfQ5ExtZ+V+3zaiHiBvGz7iqBQKTDv+/SlpZ9dZjSQu8L9aXcl5W2hN
4e+owW7nYT+6Y5OO1iHYLmJKvsjbSUGlmB6eyo3FR/WvSprhd2aQR9GjTwlmNNSW
JxFwGxQ0h+3ebid0x6QQQY5GBNgBQ0vnvX0ngDzCz/MrMm/uKrpwJDtjitHTruXt
g/YNLbzxg3Ax5Z4SF5ERIw2OYrCFuGFn/g9Od5DDp5MP9pRRq+KEaXpMwphjEoYT
8QX9K3husXVIBluiEqBCb69Fmg5V0DLjsHbH3DFhOSPWfVzw9n7pTgL7eN4EiaxI
YRmd9FQyEMay92zV9EKVRsOwF7JdcifgkFVK1CzwNl+/1/asWiemDoyKvuJGOicT
4g6Nn3OX2/cnCpowEiY1mQjlEqXrW98y3GXDz3T87MZfSm+NZXrJrUkDc1gEMBZh
EiI6fKkieEWpUY5eOiC7LvnZNbgv316+lbfJw47U3vc=
-----END CERTIFICATE-----
www.example.com.cert.pem
-----BEGIN CERTIFICATE-----
MIIGFDCCA/ygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZgxCzAJBgNVBAYTAkFV
MREwDwYDVQQIDAhWaWN0b3JpYTENMAsGA1UECgwEQUNNRTEjMCEGA1UECwwaQUNN
RSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHTAbBgNVBAMMFEFDTUUgSW50ZXJtZWRp
YXRlIENBMSMwIQYJKoZIhvcNAQkBFhRjb250YWN0MkBleGFtcGxlLmNvbTAeFw0x
ODExMTIxMTMyNTlaFw0xOTExMjIxMTMyNTlaMIGQMQswCQYDVQQGEwJBVTERMA8G
A1UECAwIVmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTENMAsGA1UECgwEQUNN
RTERMA8GA1UECwwIQUNNRSBXZWIxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEe
MBwGCSqGSIb3DQEJARYPd2ViQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA2nOpEEXpLRORiuznWCN7FYIiHH+1ZcjAw6qUDDxjodqf
ia3FyyisRs2Y4WVptlT6y+SyQd33lTGvTF2TUSoUZkSMAcO5MzwS3sohK+tLJ4T5
K9Qn0bLhiv74LDU3R37u9/DpnL1AK+JlWfBzATs7/yqAvhlEl1UawcbptQOx6Aff
LYewdFS80aIN+4O5swL4Fo+UPEDV+hKRM/VcNXQRPjdy9bXYMG4+Al/JUYYjdh77
FMojg5TGPOdDbhdo0DdqsC1EjQFbVAnGsY6Wq+1FvoN2CMywFqLv94kngSexBYc5
/ujLRI4/UmDNWVPaQqnbaY5kcAc2xkQVLIjbiifcAQIDAQABo4IBbDCCAWgwCQYD
VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5T
U0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUO6hLePVS
8WAlKXtsXoYrxaitrpowgc4GA1UdIwSBxjCBw4AUVasTHedSnFZlyd7WE/YiSyLh
zxihgaakgaMwgaAxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhWaWN0b3JpYTESMBAG
A1UEBwwJTWVsYm91cm5lMQ0wCwYDVQQKDARBQ01FMSMwIQYDVQQLDBpBQ01FIENl
cnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAwwMQUNNRSBSb290IENBMR8wHQYJ
KoZIhvcNAQkBFhBhY21lQGV4YW1wbGUuY29tggIQADAOBgNVHQ8BAf8EBAMCBaAw
EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAFCsKRB4iSWz
Irjfs2mv/AHOiWM0Jjuup11B22DhEdRB2dYSTd5NOmsNfgMsUJDlfTY8XTxi/Xa6
FIDNu6V1nnhyedSLRGHXwprDDH8i+uWq9JK4cRoaEpiifn1pC24QVPb1atJJGD3E
Edbxw4/xhpi/HX4M3dT09kFopVZ8rkWm+syWY8KNCtYQO8+oq5ObmLP7H1wxrp4h
yohe20gmvfH+L5OkxssEUfLM85IWmxnZzCxe8gVo2A84i3QKK1Rd9FB44/usPWXW
P80/f8yzeq3v+J2LBF2x9ef5ihYfo3HbRw6PQQWXTKQ2Wq+WtcQ4OCaXh1jXPOv9
FzMTCer9l6jyXfZsHnUGx+HCDGltRuY2IlnQ7Pm1DNBuoVBFzUClyPn1/YQKIJ9U
/6F5eBPmaQr7Ky1uxrKe4aHzoviaErYhvU6sdOkEiauSebe6DQpNt85XZPXkT/Zl
jb5gxkyrt0T+W7szqqvY55zPgkH7qMzVD0+PxZTS8oVzmPQpt4lJWMC2u8y3ebTO
qM5sYNA+hZP4GCOzERcUheW/LcHQpNHyRmOtVALT13h4yyKSn4jZrbZlCf0e05Pk
fmcOW4XjwsiTnDWsvGO970+yjTxMZ8mmcvss5EkG9gnd2TJajlSyRD9xk3v4x7HC
t4llpWpmYs7CIl+YYLvaO1ibhnZ8CNRi
-----END CERTIFICATE-----
www.example.com.key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA2nOpEEXpLRORiuznWCN7FYIiHH+1ZcjAw6qUDDxjodqfia3F
yyisRs2Y4WVptlT6y+SyQd33lTGvTF2TUSoUZkSMAcO5MzwS3sohK+tLJ4T5K9Qn
0bLhiv74LDU3R37u9/DpnL1AK+JlWfBzATs7/yqAvhlEl1UawcbptQOx6AffLYew
dFS80aIN+4O5swL4Fo+UPEDV+hKRM/VcNXQRPjdy9bXYMG4+Al/JUYYjdh77FMoj
g5TGPOdDbhdo0DdqsC1EjQFbVAnGsY6Wq+1FvoN2CMywFqLv94kngSexBYc5/ujL
RI4/UmDNWVPaQqnbaY5kcAc2xkQVLIjbiifcAQIDAQABAoIBAGOkH/hZOxuhcmCA
4KEWRf0wh2iiY9ZSdIKLWs4d+YAJHX4KMk8RdUsyWkptHIPbTS4VWa2rllOJ/yCB
CkIaRIXFPGtNoDsbaqwOXIUQ5Q3YnGL+eU8wHapt1Dst5tIItu2HCLfCpvOdZ4dX
os1r/FjORTzwf5XbbsH2fgFf9xUTMlqeTB2VLv2vZs2LfiJfenjwP53JbrYDe0Ve
Kz46NJz6drvJZ3bBYECQbui594d/Nx3ZMHtyzFcnA1g3KORgU30VHSHG1CY9JbO3
E8Cw+izQfZGSbtNOK9U9N7ibyarR4pwQ3LmcXNGqPChDYMN/+LwB+tuBAGOy2uB6
EqwPJsECgYEA7+/0rHCpZF15KKRtFoQe1EQcmx960yT/cp/Bmld3jrrDgqln0skC
C2txrwVdkbAVpZwFKkxv34QX338ihzxniioweplbwRKTMwzOSvwidQc1elGGxEj5
Ce3gwQrd3UsgL4u38SeSKkO7pBqV0zxcA1EN71sDerS4mlOUa1RGglkCgYEA6RN8
XdMioHoiTCiXtNWf536aQmkK/1Wd6WpoHJKEg53c/FQC1jCh4D1lvp6sKOepEhUB
lfaR8ml62iFOzzzPSYwbABoiHzn5z2Lnx5lzjyCIJ4c2byiLJzAtfecjiR1LHnA/
1zBa/fXPOEdr5k2XkYvx/5cRHMHdS1LcsH1j4ekCgYBz1G1TydecohtZaXdYRVP0
uSTuJhZPVC8VkNYPwmXvO24i59E9Sth31ti822Q+brkkh9tefiQLzWMQ+/kZPCnn
41If/WT0Ihl5rZbxUCL6SA6jDDR5EZlYF8RGrQ5KRHg3O8YC302KpcQyBruJjDwH
RdvqTw+w7wmnRu4Bml+nkQKBgQCyH18rQSE0bUJq25bc72mN/BYd7LMn4aGV8ejw
9RRqlal9+SJV2MLNYX6xSAggFrMCC6WzmsV88hmePFhDTqDH/1ffIxmyrZb5ZAfo
ZaCH4H/NXas/FkgKQepyTsO8lPOEpppTdTQE4+dihkqyrdfItp/SCfxc8teRKhlY
k+tSiQKBgQCYMRBErv5O88aJbzePkTdv2xGyp1/p4tkvpwZ6bZDbI2W3YAv89F+K
3yWhzrP5kqNr3aHVChuKu4IFiL8D4NxT9dMqtC3M1OgZ5cD3YXlQBZBp7e5pOv43
AxFqQoilp/4VTcFmzYvKjUE262ekT60hZT7qqAfoI3r2vEF3gd4Kbw==
-----END RSA PRIVATE KEY-----