<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>