<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div class="moz-cite-prefix">On 25.12.20 00:35, 定平袁 wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CABYODQ9r0NhEoh=ANJXyZn1o1-SudeAEarCxPQWWBcga=4iCtA@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">
<div><a class="gmail_plusreply"
id="m_1380141081388625801plusReplyChip-2"
href="mailto:dev@ddvo.net" target="_blank"
moz-do-not-send="true">@David von Oheimb</a> I will update
to a new version and try again.</div>
</div>
</blockquote>
<p>Good. Ideally try also a current 3.0.0 alpha release because
there have been some changes to cert chain building and
verification recently.<br>
<br>
</p>
<blockquote type="cite"
cite="mid:CABYODQ9r0NhEoh=ANJXyZn1o1-SudeAEarCxPQWWBcga=4iCtA@mail.gmail.com">
<div dir="ltr">
<div> To append cert is to make sure new cert and old cert both
exist in trust store, thus when server switches cert, it can
be trusted by client.<br>
</div>
</div>
</blockquote>
Understood, but my point was on a different aspect:<br>
The chain building will take the first matching cert, so if you want
to prefer the new cert, it must be in the list *before* the old one
-<br>
in other words, prepend the new cert to the list rather than
appending to it.<br>
<br>
<blockquote type="cite"
cite="mid:CABYODQ9r0NhEoh=ANJXyZn1o1-SudeAEarCxPQWWBcga=4iCtA@mail.gmail.com">
<div dir="ltr">
<div>
<div>@Jochen actually, the certs have different SN, which
indeed is not consistent with the man doc</div>
</div>
</div>
</blockquote>
<p>Different certs with the same issuer indeed <b>must</b> have
different SNs (except in the special case I mention below). <br>
See also RFC 5280 section 4.1.2.2 <a moz-do-not-send="true"
href="https://tools.ietf.org/html/rfc5280#section-4.1.2.2">https://tools.ietf.org/html/rfc5280#section-4.1.2.2</a>:<br>
</p>
<pre class="newpage"> It MUST be unique for each certificate issued by a given CA
(i.e., the issuer name and serial number identify a unique certificate). </pre>
<p><br>
Yet there is a different inconsistency in what you write:</p>
<blockquote type="cite"
cite="mid:CABYODQ9r0NhEoh=ANJXyZn1o1-SudeAEarCxPQWWBcga=4iCtA@mail.gmail.com">
<div dir="ltr">
<div>
<div>The thing that confuses me is that CURL (compiled with
gnutls) and Golang works. <br>
</div>
<div>below is my ca.crt file, I am not sure where it went
wrong, maybe just my wrong behavior?</div>
</div>
</div>
</blockquote>
You refer to them as CA certs, but they are not: they do no have a
basicConstraints field with the cA bit set.<br>
And as far as I understand your scenario, they are not used to issue
other certs but by some (TLS) server,<br>
so they really are end-entity (EE) certs, not CA certs, and it looks
like this is correct in your application scenario.<br>
<br>
Directly trusted self-issued EE certs (which may be self-signed or
not) are a special situation.<br>
This has been clarified in RFC 6818 (which updates RFC 5280) <a
moz-do-not-send="true"
href="https://tools.ietf.org/html/rfc6818#section-2">https://tools.ietf.org/html/rfc6818#section-2</a>:<br>
<pre class="newpage">| Consistent with <a href="https://tools.ietf.org/html/rfc6818#section-3.4.61">Section 3.4.61</a> of X.509 (11/2008) [<a href="https://tools.ietf.org/html/rfc6818#ref-X.509">X.509</a>], we note
| that use of self-issued certificates and self-signed certificates
| issued by entities other than CAs are outside the scope of this
| specification. Thus, for example, a web server or client might
| generate a self-signed certificate to identify itself. These
| certificates and how a relying party uses them to authenticate
| asserted identities are both outside the scope of <a href="https://tools.ietf.org/html/rfc5280">RFC 5280</a>.</pre>
So the path building and verification, as well as other checks
defined RFC 5280, does not apply to them at all!<br>
They are essentially just a convenient container for a public key,
where it is optional to check expiration etc.<br>
<p><br>
Unfortunately, when using such certs for TLS connections etc.,
still verification is done on them, which may fail.<br>
After renaming your ca.crt file to ee.crt for clarity and
extracting the first cert in ee1.crt and the second one in
ee2.crt,<br>
when verifying these directly trusted certs one gets the problem
you reported:<br>
<br>
openssl verify -x509_strict -trusted ee.crt ee1.crt<br>
ee1.crt: OK<br>
</p>
<p>openssl verify -x509_strict -trusted ee.crt ee2.crt<br>
C = US, ST = CA, L = Palo Alto, O = VMware, CN =
nsxmanager.pks.vmware.local<br>
error 18 at 0 depth lookup: self signed certificate<br>
error ee2.crt: verification failed<br>
</p>
<p>So as I wrote before, unfortunately the path building picks up
the first matching cert from ee.crt,<br>
which is the one in ee1.crt (i.e., your old one), and does not try
the second one (i.e., your new one).<br>
This happens also with the latest OpenSSL pre-3.0.0 master.<br>
</p>
<p><br>
A solution is to add both the subjectKeyIdentifier and
authorityKeyIdentifier extensions to your certs,<br>
for instance like this:<br>
</p>
<p>echo >ee.cnf "<br>
prompt = no<br>
distinguished_name = my_server<br>
x509_extensions = my_exts<br>
[my_server]<br>
commonName = test<br>
[my_exts]<br>
basicConstraints = CA:false<br>
subjectKeyIdentifier=hash<br>
authorityKeyIdentifier = keyid"<br>
</p>
<p>openssl req -config ee.cnf -new -x509 -out ee1.crt -nodes -keyout
ee1.pem<br>
openssl req -config ee.cnf -new -x509 -out ee2.crt -nodes -keyout
ee2.pem<br>
cat ee1.crt ee2.crt >ee.crt</p>
<p>The subjectKeyIdentifier and authorityKeyIdentifier extensions
are generally recommend<br>
(and actually required to add for certs that are RFC 5280
compliant) <br>
because they help for correct chain building, and indeed also in
this case they do:<br>
</p>
<p>openssl verify -x509_strict -trusted ee.crt ee1.crt<br>
ee1.crt: OK<br>
openssl verify -x509_strict -trusted ee.crt ee2.crt<br>
ee2.crt: OK<br>
<br>
</p>
<p>Regards,</p>
<p> David<br>
</p>
<br>
</body>
</html>