天天看點

【OpenSSL】使用證書和私鑰導出P12格式個人證書1, 産生CA憑證2, 産生個人證書3, 合并證書和私鑰得到p12格式的個人證書4, 提取個人證書5, 提取個人證書的私鑰6, 提取ca證書

參考上文【OpenSSL】建立證書

1, 産生CA憑證

1.1, 生成ca的私鑰

openssl genrsa -out cakey.pem 2048
           

1.2, 生成ca的自簽名證書請求

openssl req -new -key cakey.pem -subj "/CN=Example Root CA" -out cacsr.pem 
           

1.3, 自簽名ca的證書

openssl x509 -req -in cacsr.pem -signkey cakey.pem -days 999 -out cacert.pem
           

2, 産生個人證書

2.1, 生成個人證書的私鑰

openssl genrsa -out alicekey.pem 2048
           

2.2, 生成個人證書請求

openssl req -new -key alicekey.pem -subj "/[email protected]" -out alicecsr.pem
           

2.3, 簽發個人證書

openssl x509 -req -in alicecsr.pem -CA cacert.pem -CAkey cakey.pem -days 999 -set_serial 01 -out alicecert.pem
           

3, 合并證書和私鑰得到p12格式的個人證書

openssl pkcs12 -export -in alicecert.pem -inkey alicekey.pem -certfile cacert.pem -out alice.p12 
           

4, 提取個人證書

openssl pkcs12 -in alice.p12 -nokeys -clcerts -out alicecert.pem
           

5, 提取個人證書的私鑰

openssl pkcs12 -in alice.p12 -nocerts -out alicekey.pem
           

6, 提取ca證書

openssl pkcs12 -in alice.p12 -nokeys -cacerts -out cacert.pem
           

備注:

1,綁定ca證書的時候,-certfile和-CAfile的差別 http://arstechnica.com/civis/viewtopic.php?p=24680099

You're right, the documentation is confusing (man page here*), but I think I've figured it out, after some testing:
-certfile adds all certificates in that file to the .p12 store (in addition to the input certificate).
-CAfile and -CApath are used to build the "standard CA store" (just as they do for openssl s_client), which is only used with the -chain option, which will add the entire certification chain for the input certificate to the .p12, assuming it can be found in that file and/or directory. Without the -chain option they do nothing.

* Also, most distros supply man pages for the openssl subcommands under the subcommand name, e.g. pkcs(1).
           

see

http://openssl.6102.n7.nabble.com/How-to-include-intermediate-in-pkcs12-td49603.html
           
A lot of things on the Internet are wrong. The OpenSSL man page does not say multiple
occurrences work and I’m pretty sure it never did, nor did the code. In general
OpenSSL commandlines don’t handle repeated options; the few exceptions are noted.
pkcs12 -caname (NOT –cafile) IS one of the few that can be repeated, and possibly
some things on the Internet got that confused. However, the commandlines (at least
usually?) don’t *diagnose* repeated (and overridden) options.

pkcs12 –export gets certs from up to three places:
- the input file (-in if specified else stdin redirected or piped)
- -certfile if specified (once, as you saw)
- the truststore if –CAfile and/or –CApath specified IF NEEDED
 
In other words, any cert in infile or certfile is always in the output, needed or not.
If that set does not provide a complete chain, pkcs12 will try to complete it using
the truststore if specified, but will produce output even if it remains incomplete.
Like other commandlines, and many programs using the library, the truststore
can be a single file with –CAfile (NOT –cafile) or a directory of hashnamed
links or files with –CApath or both.

If the cert you are putting in pkcs12 is under a CA that you trust other peers to use
and thus you have in your truststore, easiest to use it from there. Similarly if your cert
is under an intermediate (or several) that you have in your truststore to allow peers
to use even if the peers don’t send (as they should), easiest to use from there.
Otherwise IMO it’s easiest to just put in infile or –certfile (or a combination),
although the option of temporarily creating or modifying a truststore works.
 
Whether to do your trustore with CAfile or CApath or both is a more general question
and depends partly on whether you use somebody’s package.
For example the curl website supplies the Mozilla truststore in CAfile format;
when I want to use that I don’t bother converting to CApath format.
 
From: [hidden email] [[hidden email]] On Behalf Of Edward Ned Harvey (openssl)
Sent: Tuesday, April 22, 2014 15:31
To: [hidden email]
Subject: *** Spam *** How to include intermediate in pkcs12?

A bunch of things on the internet say to do "-cafile intermediate.pem -cafile root.pem" or "-certfile intermediate.pem -certfile root.pem" and they explicitly say that calling these command-line options more than once is ok and will result in both the certs being included in the final pkcs12...  But I have found this to be untrue.
I have found, that if I concatenate intermediate & root into a single glom file, and then I specify -certfile once for the glom, then my pfx file will include the complete chain.  But if I use -certfile twice, I get no intermediate in my pfx.  And I just wasted more time than I care to describe, figuring this out.
So...  While concatenation/glom is a viable workaround, I'd like to know, what's supposed to work?  And was it a new feature introduced after a certain rev or something?   I have OpenSSL 0.9.8y command-line on Mac OSX, and OpenSSL 1.0.1e command-line on cygwin.  I believe I've seen the same behavior in both.
           

-CAfile 的處理邏輯

/* If chaining get chain from user cert */
        if (chain) {
            int vret;
            STACK_OF(X509) *chain2;
            X509_STORE *store = X509_STORE_new();
            if (!store) {
                BIO_printf(bio_err, "Memory allocation error\n");
                goto export_end;
            }
            if (!X509_STORE_load_locations(store, CAfile, CApath))
                X509_STORE_set_default_paths(store);

            vret = get_cert_chain(ucert, store, &chain2);
            X509_STORE_free(store);

            if (!vret) {
                /* Exclude verified certificate */
                for (i = 1; i < sk_X509_num(chain2); i++)
                    sk_X509_push(certs, sk_X509_value(chain2, i));
                /* Free first certificate */
                X509_free(sk_X509_value(chain2, 0));
                sk_X509_free(chain2);
            } else {
                if (vret >= 0)
                    BIO_printf(bio_err, "Error %s getting chain.\n",
                               X509_verify_cert_error_string(vret));
                else
                    ERR_print_errors(bio_err);
                goto export_end;
            }
        }
           

-certfile的處理邏輯

/* Add any more certificates asked for */
        if (certfile) {
            STACK_OF(X509) *morecerts = NULL;
            if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
                                         NULL, e,
                                         "certificates from certfile")))
                goto export_end;
            while (sk_X509_num(morecerts) > 0)
                sk_X509_push(certs, sk_X509_shift(morecerts));
            sk_X509_free(morecerts);
        }
           

2,-name選項可以設定顯示名稱,否則導入證書的時候,可能會顯示一些亂碼。