Get certificate expiry date from the embedded.mobileprovision provisioning profile - ios

I need to get the expiry date of our iOS enterprise certificate used in an ipa's embedded.mobileprovision file using the command line.
I've got this so far:
security cms -D -i Payload/*.app/embedded.mobileprovision > tmp.plist && /usr/libexec/PlistBuddy -c 'Print :DeveloperCertificates' tmp.plist | base64 -d - | openssl x509 -inform DER -noout -text
The response:
Apr 22 12:28:47 c01892 base64[14721] <Info>: Read 510 bytes.
Apr 22 12:28:47 c01892 base64[14721] <Info>: Wrote 680 bytes.
Apr 22 12:28:47 c01892 base64[14721] <Info>: Read 510 bytes.
Apr 22 12:28:47 c01892 base64[14721] <Info>: Wrote 680 bytes.
Apr 22 12:28:47 c01892 base64[14721] <Info>: Read 440 bytes.
Apr 22 12:28:47 c01892 base64[14721] <Info>: Wrote 588 bytes.
unable to load certificate
14722:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:/SourceCache/OpenSSL098/ OpenSSL098-52.20.2/src/crypto/asn1/tasn_dec.c:1323:
14722:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:/SourceCache/ OpenSSL098/OpenSSL098-52.20.2/src/crypto/asn1/tasn_dec.c:379:Type=X509
The openssl command works on our certificate file just fine:
openssl x509 -inform DER -noout -text -in "iPhone Distribution: XXXX.cer"
So what I am missing is getting the certificate out of the embedded.mobileprovision, decode it and save it to a file or pass it by piping.
If I split the sommand up, we get the following:
a. Get the certificate out of the embedded.mobileprovision:
security cms -D -i Payload/*.app/embedded.mobileprovision > tmp.plist && /usr/libexec/PlistBuddy -c 'Print :DeveloperCertificates' tmp.plist > encodedcert.b64
b. Decode the retrieved base64 to a .cer file:
base64 -d encodedcert.b64 certificate.cer
c. Read it with openssl:
openssl x509 -inform DER -noout -text -in certificate.cer
Unfortunatly, the generated certificate.cer file by my base64 command is zero bytes long...
Who can help me out further?

I've successfully been able to get to the certificate information.
The problem was that my PlistBuddy command was wrong. I should have used 'DeveloperCertificates:0' instead of ':DeveloperCertificates'.
I also did not need the base64 stuff.
So the working commandline to get the info from the enterprise certificate in an embedded.mobileprovision profile is
security cms -D -i Payload/*.app/embedded.mobileprovision > tmp.plist && /usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' tmp.plist | openssl x509 -inform DER -noout -enddate
Split up into three parts:
Get a plist from the embedded.mobileprovision:
security cms -D -i Payload/*.app/embedded.mobileprovision > tmp.plist
Get the first certificate from the plist:
/usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' tmp.plist |
Read the certificate passed through the pipe and extract the enddate (-text instead of -enddate gives you the entire certificate information):
openssl x509 -inform DER -noout -enddate
Edit: Here is the command without a temporary plist file:
/usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' /dev/stdin <<< $(security cms -D -i Payload/*.app/embedded.mobileprovision) | openssl x509 -inform DER -noout -enddate

Related

GnuPG v2 store how to export the keys in. secring.gpg and pubring.gpg file from pubring.kbx file

I am trying to use the imported GPG keys in my workflow but it seems I could never export the private keys out of this.
I am using GitHub actions https://github.com/marketplace/actions/import-gpg to import private key and passphrase loaded them via secrets and per below output I could see the keys were imported good. I need to use this for signing my helm chart.
Run crazy-max/ghaction-import-gpg#v5
with:
gpg_private_key: ***
passphrase: ***
git_user_signingkey: true
git_commit_gpgsign: true
git_config_global: false
git_tag_gpgsign: false
git_push_gpgsign: if-asked
workdir: .
GnuPG info
Version : 2.2.27 (libgcrypt 1.9.4)
Libdir : /usr/lib/x86_64-linux-gnu/gnupg
Libexecdir : /usr/lib/gunning
Datadir : /usr/share/gnupg
Homedir : /home/runner/.gnupg
GPG private key info
Fingerprint : xxxxxxxxxxxxxxxxxxxx
KeyID : xxxxxxxxxxxxxxxxxxxx
Name : bot
Email : bot#example.com
CreationTime : Thu Jan 12 2023 05:56:57 GMT+0000 (Coordinated Universal Time)
Fingerprint to use
xxxxxxxxxxxxxxxxxxxx
Importing GPG private key
gpg: directory '/home/runner/.gnupg' created
gpg: keybox '/home/runner/.gnupg/pubring.kbx' created
gpg: /home/runner/.gnupg/trustdb.gpg: trustdb created
gpg: key xxxxxxxxxxxxxxxxxxxx: public key "bot <bot#example.com>" imported
gpg: key xxxxxxxxxxxxxxxxxxxx: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
Configuring GnuPG agent
Getting keygrips
Presetting passphrase for xxxxxxxxxxxxxxxxxxxx
Setting outputs
fingerprint=xxxxxxxxxxxxxxxxxxxx
keyid= xxxxxxxxxxxxxxxxxxxx
name=bot
email=bot#example.com
Setting GPG signing keyID for this Git repository
I could verify the new format file is there on filesystem , In next step I am trying to export these keys via commands
-rw-r--r-- 1 runner docker 70 Jan 18 00:50 gpg-agent.conf
drwx------ 2 runner docker 4096 Jan 18 00:50 private-keys-v1.d
-rw-r--r-- 1 runner docker 1347 Jan 18 00:50 pubring.kbx
-rw------- 1 runner docker 32 Jan 18 00:50 pubring.kbx~
-rw------- 1 runner docker 1200 Jan 18 00:50 trustdb.gpg
/home/runner/.gnupg/pubring.kbx
-------------------------------
sec rsa4096 2023-01-12 [SC] [expires: 2025-01-11]
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
uid [ unknown] bot <bot#example.com>
Now I am trying to export these keys and I could generate pubring.gpg but the moment I try to export secret key It gives error.
$ gpg --export >~/.gnupg/pubring.gpg -------------> Works
$ gpg --export-secret-keys >~/.gnupg/secring.gpg. --------> Doesn't work
gpg: key xxxxxxxxxxxxxx: error receiving key from agent: No such file or directory - skipped
gpg: WARNING: nothing exported
Error: Process completed with exit code 2.
I couldn't understand why secret key can't be imported out of pubring.kbx file.
Appreciate help.

openssl ocsp Responder Error: unauthorized (6)

I want to verify whether the Apple p12 certificate is revoked.
Verify through OpenSSL, but the failure rate
Responder Error: unauthorized (6)
openssl s_client -connect ocsp.apple.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-------END/p' > cert.pem
openssl s_client -showcerts -connect ocsp.apple.com:443 < /dev/null 2>&1 | sed -n '/-----BEGIN/,/-----END/p' > chain.pem
openssl x509 -noout -ocsp_uri -in cert.pem
openssl ocsp -issuer chain.pem -cert cert.pem -text -url http://ocsp.apple.com/ocsp03-apevsecc1g101 -header "HOST" "ocsp.apple.com"
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 99A13D5E339D6899F2F62D3449CA0FB7AD56A71D
Issuer Key Hash: 45F2A8DA2EF4DD5AE49E079E4B7B289B3BB20B31
Serial Number: 5E652F93666E7A5B3966551A0C167BAA
Request Extensions:
OCSP Nonce:
0410AB2982A627A49BA9AC9E06A9C4FE28B2
Responder Error: unauthorized (6)
chain.pem can only contain the intermediate and root certificates. The way you invoked openssl it brought in the entire chain. So: remove your certificate from chain.pem and try again.
For what it's worth (or future instances) here was my solution:
Note: I was sending the response to a Microsoft OCSP responder.
Fix: I had to define the -CAfile and -no_nonce parameters.
openssl ocsp -no_nonce -issuer ca_chain.cer -CAfile ca_chain.cer -cert test.cer -text -url http://ocsp.myorg.com/ocsp
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 555D0C30ACDDA1D39CAFB5C0B33BD73475C903D8
Issuer Key Hash: 3E8B5EE3BF6D026D69F3005CCE08BE60C245F3EE
Serial Number: 3E002C0FFFDA2BE9708A43E3270000002C0FFF
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C012856C236D6AA6EC5F835AC25F17EBECB8BC10
Produced At: Nov 8 05:36:39 2022 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 555D0C30ACDDA1D39CAFB5C0B33BD73475C903D8
Issuer Key Hash: 3E8B5EE3BF6D026D69F3005CCE08BE60C245F3EE
Serial Number: 3E002C0FFFDA2BE9708A43E3270000002C0FFF
Cert Status: revoked
Revocation Time: Oct 27 21:26:12 2022 GMT
Revocation Reason: cessationOfOperation (0x5)
This Update: Nov 8 00:50:02 2022 GMT
Next Update: Nov 8 17:10:02 2022 GMT

Grep from a certificate

I can view the openSSL certifcate with this command
openssl x509 -text -in myCertificate.pem
I just wanted to see when the cert will expire only. The line which I want to read is,
Not After : Jul 28 14:09:57 2015 GMT
I tried using the grep command but it doesn't display anything.
grep "After" myCertificate.pem
Is there a way that I can read only that line of the certificate??
Thanks in advance
The short way is to use -enddate -noout (print the notAfter value, and don't re-output the cert PEM contents)
$ openssl x509 -in github.cer -enddate -noout
notAfter=Apr 12 12:00:00 2016 GMT
In order to use grep you need to continue using the -text option, because the phrase "Not After" doesn't appear in the cert, it's just an encoded representation. And then combine that with the pipe (|) operation:
$ openssl x509 -in github.cer -text -noout | grep After
Not After : Apr 12 12:00:00 2016 GMT

thin rails server/eventmachine on windows does not work with custom certificate

After building my own eventmachine/thin with SSL support on windows (Install OpenSSL with Ruby for eventmachine on Windows 7 x86) I got another problem with SSL certificate: when I use build-in self-signed one thin works fine but it does not respond to any request while using corporate certificate
Here is my path for obtaining the certificate:
I generated private key with puttygen (ssl-private.key)
I generated CSR using following command:
openssl req -out ssl.csr -key ssl-private.key -new
I sent CSR to CA and received P7B file
I converted P7B using following command:
openssl pkcs7 -inform DER -outform PEM -in cert.p7b -print_certs > cert.crt
What could go wrong here?
What have I checked:
openssl rsa -in ssl-private.key -check
says "RSA key ok"
openssl x509 -in cert.crt -text -noout
says
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
***
Signature Algorithm: sha1WithRSAEncryption
Issuer: ***
Validity
Not Before: Feb 16 08:47:25 2004 GMT
Not After : Feb 16 08:55:36 2024 GMT
Subject: ***
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
***
Exponent: 3 (0x3)
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
***
1.3.6.1.4.1.311.21.1:
...
Signature Algorithm: sha1WithRSAEncryption
***
while the same check made on self-signed cert, created using
openssl genrsa -des3 -out server.orig.key 2048
openssl rsa -in server.orig.key -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
says
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
***
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=PL, ST=-, O=Internet Widgits Pty Ltd, CN=test.org
Validity
Not Before: Jun 24 14:42:07 2015 GMT
Not After : Jun 23 14:42:07 2016 GMT
Subject: C=PL, ST=-, O=Internet Widgits Pty Ltd, CN=test.org
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
***
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
***
ok some change: I have changed certs order in crt file so that final cert is not last but first and the result is different: chrome drops an error of NET::ERR_CERT_INVALID, IE similar and both does not navigate further
openssl s_client output (looks ok, *** Root CA 1 is trusted in windows):
Loading 'screen' into random state - done
CONNECTED(000001E8)
depth=1 DC = com, DC = ***, CN = *** Enterprise CA 1
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:/C=***/ST=***/O=***/CN=***.com
i:/DC=com/DC=***/CN=*** Enterprise CA 1
1 s:/DC=com/DC=***/CN=*** Enterprise CA 1
i:/DC=com/DC=***/CN=*** Root CA 1
---
Server certificate
-----BEGIN CERTIFICATE-----
***
-----END CERTIFICATE-----
subject=/C=***/ST=***/O=***/CN=***.com
issuer=/DC=com/DC=***/CN=*** Enterprise CA 1
---
No client certificate CA names sent
---
SSL handshake has read 3404 bytes and written 665 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-GCM-SHA384
Session-ID: ***
Session-ID-ctx:
Master-Key: ***
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket: ***
Start Time: 1435319943
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
read:errno=0
I have made a simple https server (lib/emtestssl):
require 'rubygems'
require 'bundler/setup'
Bundler.require
class ServerHandler < EM::Connection
def post_init
puts "post_init"
start_tls :private_key_file => 'private.key', :cert_chain_file => 'comb.crt', :verify_peer => false
end
def receive_data(data)
puts "Received data in server: #{data}"
send_data("HTTP/1.1 200 OK\n\nHello world!")
close_connection_after_writing
end
end
EventMachine.run do
puts 'Starting server...'
EventMachine.start_server('145.245.202.233', 443, ServerHandler)
end
it works fine without tls, with tls browser won't allow to connect :(
as per http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html#verify private key and certificate do match
it looks like (patched) eventmachine is completely fine: i have taken key/cert pair from existing server and (after a url mismatch warning from the browser) it works fine
after comparing the certificates it looks like my CA has failed and brought me a cert with wrong properties: working one is described as Server Authentication (1.3.6.1.5.5.7.3.1) while failing one is Client Authentication (1.3.6.1.5.5.7.3.2)
i will issue another csr and charge them for lost day... :/
maybe one important discovery is an order of certificates within cert file: one must go from the final cert to the root being at the end of the chain

Changing password on p12 file

I was forwarded a p12 file from a client with the push cert.
Can I change the password of this p12 file without any ramifications and if yes, can I use something like this:
openssl pkcs12 -in Certificates.p12 -out temp.pem -passin pass: -passout
pass:temppassword
openssl pkcs12 -export -in temp.pem -out Certificates-final.p12 -passin
pass:temppassword -passout pass:newpa­ssword
rm -rf temp.pem
I found this on this website here
No you cannot do so without ramifications.
Exporting PKCS#12 contents with openssl will lose information which won't be restored upon re-creation of the PKCS#12.
Whether that metadata is important to you will depend on your PKCS#12 contents and your use-case.
There does not seem to be a way of simply "changing the password of the container" with openssl. (However, you can use Java's keytool to do this, as I explain later.)
TL;DR: use this instead of your openssl command:
keytool -importkeystore -srckeystore source.p12 -srcstoretype PKCS12 -srcstorepass:file ssp -destkeystore dest.p12 -deststoretype PKCS12 -deststorepass:file dsp -destkeypass:file dsp
OpenSSL
Here is a comparison between a re-created PKCS#12 and it's original,
from an old (and invalid) german tax login keystore I had for testing.
In my case a PKCS#12 re-created in this way was no longer valid/working for the intended application (certificate-based login) so I had to find a different solution.
Short overview (the original, then the re-created file):
$ openssl pkcs12 -info -in Certificates.p12 -noout
Enter Import Password:
MAC:sha1 Iteration 1024
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 1024
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 1024
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 1024
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
$ openssl pkcs12 -info -in Certificates-final.p12 -noout
Enter Import Password:
MAC:sha1 Iteration 2048
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
And now a diff between the original exported PEM file contents, and the re-exported PEM of the re-created PKCS#12.
(I have redacted some base64 lines and also re-ordered the PEM data in the output
to make the diff shorter and the changes more obvious.)
You can see the original had two private keys (a signaturekey and an encryptionkey) while the new one only has one, as well as lost metadata on the Certificate bags.
Also note how the localKeyID's have been changed:
$ openssl pkcs12 -in Certificates.p12 -out temp.pem
$ openssl pkcs12 -in Certificates-final.p12 -out temp2.pem
$ diff -up temp.pem temp2.pem
--- temp.pem
+++ temp2.pem
## -1,74 +1,38 ##
Bag Attributes
- friendlyName: encryptionkey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 47 44
+ localKeyID: DD 42 1D 23 0E 11 BB D7 0D 54 B7 10 D0 C6 F5 40 B6 B5 2C A4
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIpJIbNX5suS8CAggA
-MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECEUOqFMc2ya4BIIEyKcSq/QtaSQe
-KaGI+xHwWXmJ8kPova4Ypjy9ELFYH/qpOlfyvE2NUE8sTPfMmTGZfVgmzajZiAkv
-2bGbJJqotmBnX7Kq4R+p8rAsMNQeyc6Hz6HOFHB2u51m/+v6U89BnxZjzYPfBLrL
-mtEJJoEKLrwjh4lCZuEQjQ==
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIStmsb0FWO6ECAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECFnnIOcMl607BIIEyJeDvQMny+9a
+g38QaURLMHGW1ZcSl1SQL3aISeF9OOVNDT6SdpH9ta+ZiBL47KYYRmzb/mrkAk8w
+xEdaY/v8/l4zo86XS3ZXX9/59rieb3YAm6GfyTAYyAwU+xMz0FHPtWjN0sWKFamx
+49Gel9yYCtfc9oRKdvaBuQ==
-----END ENCRYPTED PRIVATE KEY-----
Bag Attributes
- friendlyName: signaturekey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 41 41
-Key Attributes: <No Attributes>
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIw8wbVkc1YxICAggA
-MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECCUFgpxoljgKBIIEyCIseTm0Y7uL
-6IaAqRqwPxb64iBLLN9E/XOkA5ZAzO4MgSsZieZQfpXLJPdTdnKx9WauzpDGVfs5
-p+i5Dmrl9olI2wEOCGdoG7YzzVh4SoTAf/4v9yJRylCXREoYDdK/EM09Am1XWRVa
-fqNaWVRO/1vfv7Rgc2Mwbw==
------END ENCRYPTED PRIVATE KEY-----
-Bag Attributes
- friendlyName: encryptionkey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 47 44
+ localKeyID: DD 42 1D 23 0E 11 BB D7 0D 54 B7 10 D0 C6 F5 40 B6 B5 2C A4
subject=/serialNumber=991954729C/CN=991954729
issuer=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
-----BEGIN CERTIFICATE-----
## -96,8 +60,7 ## QmpEFSHJxYXOtyar3x9Viad9r9KtcVViJxe/cpVE
u4rfbLegLqZsXPVlY+6+k/vokTD9Oc0IdXHNk1u1dSTUc4rvxohZAxKW+5/EoLar
+AajwQNu5CmFz76Y6tDOS7XqUFkdu6JNMvBfuFNAng2GXwo/l8LsstAz/w==
-----END CERTIFICATE-----
-Bag Attributes
- friendlyName: CN=ElsterIdNrSoftCA,OU=CA,O=Elster,C=DE
+Bag Attributes: <No Attributes>
subject=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
issuer=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
-----BEGIN CERTIFICATE-----
## -126,8 +89,7 ## SxtMZZVZ6RuHLwfz+QYJ+uKghjImnZ7Gy93+S1yD
FwWQnJ1RBEUTIwMI9rrIGH5R4sUzfeS6YvJOCTcO372IC1CKRpx3odvLFR+FYM7/
nO/mlyfpTHkJrRm1IavqyBq0rUKbTUP7
-----END CERTIFICATE-----
-Bag Attributes
- friendlyName: CN=ElsterRootCA,OU=RootCA,O=Elster,C=DE
+Bag Attributes: <No Attributes>
subject=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
issuer=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
-----BEGIN CERTIFICATE-----
## -156,9 +118,7 ## EgzvybfTPjUTXr4G1FZyAJkUAw4EdHZ8K2fIijy6
VThgfYVrIfjKr00WsIW1QC3aWWCfgs19UjeLOPtydDgsU+UBAZg/fFTKYwQpx1Jg
n8L8DNLudrfbsj6m7Ir39fVi634a+v9k
-----END CERTIFICATE-----
-Bag Attributes
- friendlyName: signaturekey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 41 41
+Bag Attributes: <No Attributes>
subject=/serialNumber=991954729A/CN=991954729
issuer=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
-----BEGIN CERTIFICATE-----
## -186,8 +146,7 ## vByFoXLDf57jp0k2wGws31IBsPDmzlhlwziMstzk
u4rfbLegLqZsXPVlY+6+k/vokTD9Oc0IdXHNk1u1dSTUc4rvxohZAxKW+5/EoLar
zH7xfL59iS81Ok7F3kyWroq7Y6L5iG3+aXEVJyA9FfuGY2dKSVliqNQzEA==
-----END CERTIFICATE-----
-Bag Attributes
- friendlyName: CN=ElsterIdNrSoftCA,OU=CA,O=Elster,C=DE
+Bag Attributes: <No Attributes>
subject=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
issuer=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
-----BEGIN CERTIFICATE-----
## -216,8 +175,7 ## SxtMZZVZ6RuHLwfz+QYJ+uKghjImnZ7Gy93+S1yD
jftsxZFkkWV/2zx5Lw/pTruKSlWx4bSC9oWB9Tk1w10ST80JsVCFoeezonHq8zLF
nO/mlyfpTHkJrRm1IavqyBq0rUKbTUP7
-----END CERTIFICATE-----
-Bag Attributes
- friendlyName: CN=ElsterRootCA,OU=RootCA,O=Elster,C=DE
+Bag Attributes: <No Attributes>
subject=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
issuer=/C=DE/O=Elster/OU=RootCA/CN=ElsterRootCA
-----BEGIN CERTIFICATE-----
Besides the lost metadata, losing a private key on import here, seems actually quite problematic to me.
So make certain to test your new PKCS#12, and possibly back up your old one in a safe location!
Tested with
$ openssl version
OpenSSL 1.1.0f 25 May 2017
keytool
keytool is a key and certificate management utility and is part of the Java JRE, for managing Java's keystore. In this case I use OpenJDK's version.
You might find this (on Linux) as /usr/bin/keytool, or in your Java installation, e.g. at /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/keytool.
With keytool you can change only the container password (keystore password),
without touching any keys inside (which is probably not what you want, though):
$ keytool -list -storetype pkcs12 -keystore Certificates.p12
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 2 entries
encryptionkey, Jan 1, 2012, PrivateKeyEntry,
Certificate fingerprint (SHA1): DD:42:1D:23:0E:11:BB:D7:0D:54:B7:10:D0:C6:F5:40:B6:B5:2C:A4
signaturekey, Jan 1, 2012, PrivateKeyEntry,
Certificate fingerprint (SHA1): 18:F6:3F:FA:29:79:08:18:34:9A:99:CA:B7:47:AD:B0:36:49:A2:EB
Now we change the container password:
This overwrites the old file
$ keytool -storetype pkcs12 -keystore Certificates.p12 -storepasswd
Enter keystore password:
New keystore password:
Re-enter new keystore password:
And compare the results:
$ keytool -list -storetype pkcs12 -keystore Certificates.p12
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 2 entries
encryptionkey, Jan 1, 2012, PrivateKeyEntry,
Certificate fingerprint (SHA1): DD:42:1D:23:0E:11:BB:D7:0D:54:B7:10:D0:C6:F5:40:B6:B5:2C:A4
signaturekey, Jan 1, 2012, PrivateKeyEntry,
Certificate fingerprint (SHA1): 18:F6:3F:FA:29:79:08:18:34:9A:99:CA:B7:47:AD:B0:36:49:A2:EB
$ openssl pkcs12 -info -in Certificates.p12 -noout
Enter Import Password:
MAC:sha1 Iteration 100000
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 1024
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 1024
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 50000
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
So keytool upgraded the iteration count, but the key alias information (encryptionkey/signaturekey) and file order in the container has been retained.
Note, however, that this only changes the password of the PKCS#12 keystore,
it does not touch the passwords of any encrypted private keys.
This is useful if you use PKCS#12 to store different keys with different encryption passphrases.
But it also means that you need to remember all of them, and you can no longer export these keys using openssl, as openssl can only handle keys that share the same password as the PKCS#12 container:
$ openssl pkcs12 -in Certificates.p12 -out temp0.pem
Enter Import Password:
Error outputting keys and certificates
140661347983616:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:535:
140661347983616:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:../crypto/pkcs12/p12_decr.c:63:
140661347983616:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:../crypto/pkcs12/p12_decr.c:94:
You can then only export certificates from this file, using -nokeys:
$ openssl pkcs12 -in Certificates.p12 -out temp0.pem -nokeys
Finally, to actually change the keystore/container password and the encrypted key password(s) inside
(WHICH IS most likely WHAT YOU WANT), you can use this magic invocation:
$ keytool -importkeystore \
-srckeystore "${SRCFILE}" -srcstoretype PKCS12 -srcstorepass:file ssp \
-destkeystore "${DSTFILE}" -deststoretype PKCS12 -deststorepass:file dsp -destkeypass:file dsp
Importing keystore Certificates.p12 to Certificates-final.p12...
Entry for alias encryptionkey successfully imported.
Entry for alias signaturekey successfully imported.
Import command completed: 2 entries successfully imported, 0 entries failed or cancelled
$ rm ssp dsp
Where SRCFILE and DSTFILE are your PKCS#12 files respectively, and ssp and dsp
are files that you safely wrote your source- and dest-passphrases to, earlier (keytool can also read from environment variables using :env instead of :file.
And you can pass the passphrases on the commandline, but remember that that is unsafest and logged in your shell history.)
After now having re-created the PKCS#12, you can verify that the metadata and order of the contents was preserved:
$ keytool -list -storetype pkcs12 -keystore Certificates-final.p12
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 2 entries
encryptionkey, Jun 17, 2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): DD:42:1D:23:0E:11:BB:D7:0D:54:B7:10:D0:C6:F5:40:B6:B5:2C:A4
signaturekey, Jun 17, 2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): 18:F6:3F:FA:29:79:08:18:34:9A:99:CA:B7:47:AD:B0:36:49:A2:EB
$ openssl pkcs12 -info -in Certificates-final.p12 -noout
Enter Import Password:
MAC:sha1 Iteration 100000
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 50000
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 50000
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 50000
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
$ openssl pkcs12 -in Certificates-final.p12 -out temp3.pem
Enter Import Password:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
(again, I have redacted some base64 lines of the PEM for brevity)
$ diff -up temp.pem temp3.pem
--- temp.pem
+++ temp3.pem
## -1,74 +1,74 ##
Bag Attributes
friendlyName: encryptionkey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 47 44
+ localKeyID: 54 4B 6A 30 42 67 45 62 39 32 65 75 33 40 45 47 47 42
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI/f7cW8Pvi6MCAggA
-MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECErznPIoMLg5BIIEyImqsql6iZH7
-I+ig1yWIlimEVNmSlgT1klEFnR83b8rIohq4cvX8lcrCs/5POc22023zlHx8dSnB
-+3OxV/uoGIwU3IhXlNb41dt3fF349dbnwJrDcv4Fw3lfc0v2Wl3P1b17P9/LJeUa
-EmmUy4UHQU2THwLQctyD1A==
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI9UYIDREjVVYCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECLWYUFhHE9lJBIIEyOIA+7TqLJ+V
+lpHBcm4GIwfiEuCRHBBxHg1QGeEN7MHW5imXe4ktFPlYJFU5jCZeHVyP+mkEEiNL
+PbozodEkdGweAGnpE2+wbOQOl67q+XdICgqRZAosjBUSnBOFYH0Lk8Gr/n0NNrdR
+yohBYL8PfeKyAzL4wKm5hQ==
-----END ENCRYPTED PRIVATE KEY-----
Bag Attributes
friendlyName: signaturekey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 41 41
+ localKeyID: 54 4B 6A 30 42 67 45 62 39 32 65 75 33 40 45 46 43 40
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI8VzhkYDa8/oCAggA
-MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECIP5tmyQb2b/BIIEyNGpbxkv286e
-5gjectU9q6yecwP6/w2jGLN3jNwsUN3+3Zn92BRoPKsn5j5WryP4G/mu0QJnLmFM
-Cy92Cu41oUeR+q9ePmj+Z1Tjj//8uq4D5F0wZhcPjnhNqdnENfLxkt+CGywoX25A
-4Ia+Pt5EmZmx9vpca4j13Q==
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIN7z1PFx1ONACAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECFI18ERY6QXpBIIEyIDmBKgCkqbK
+HF9qm8etjBpoyuBtElaNNyeQA9QwYCD2I0vYsPVcOGRE8VO6LmmFXIvx/KcK8rxi
+QSb4K6eM2VcrZqBqw6hHONi5/CkxYQpBcHCLOH+V/CR4i2BHu7pl/JdAIx/7emMX
+ul0+m+zoGCHlpWuOkCSe+A==
-----END ENCRYPTED PRIVATE KEY-----
Bag Attributes
friendlyName: encryptionkey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 47 44
+ localKeyID: 54 4B 6A 30 42 67 45 62 39 32 65 75 33 40 45 47 47 42
subject=/serialNumber=991954729C/CN=991954729
issuer=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
-----BEGIN CERTIFICATE-----
## -158,7 +158,7 ## n8L8DNLudrfbsj6m7Ir39fVi634a+v9k
-----END CERTIFICATE-----
Bag Attributes
friendlyName: signaturekey
- localKeyID: 54 4B 6A 30 42 67 43 63 35 33 6D 7A 30 45 44 47 41 41
+ localKeyID: 54 4B 6A 30 42 67 45 62 39 32 65 75 33 40 45 46 43 40
subject=/serialNumber=991954729A/CN=991954729
issuer=/C=DE/O=Elster/OU=CA/CN=ElsterIdNrSoftCA
-----BEGIN CERTIFICATE-----
And we see that the private keys have been re-encrypted (updated timestamp shown by keytool), but compared to openssl's output, this time, aside from the change in iteration count, only the localKeyID has changed.
Everything is still in there, and in the original order. Much better!
Whether that is close enough to the original file, again, depends on your use-case.
The upgraded iteration count better protects against brute-force attacks
on the keys, but could potentially be fatal if you need to use them with an
old Browser or OS which can't handle such high iteration counts.
(Since those are of the IE 4.0 and WinNT age, however, this should not be a problem in most cases.)
Using this procedure with keytool, I could change the password of my PKCS#12 keys in a way that was still useable and valid for my application.
I just stumbled across this page. Does it work?
To avoid dead links here is the contents of the blog post:
With following procedure you can change your password on an .pfx certificate using openssl.
Export you current certificate to a passwordless pem type:
[user#hostname]>openssl pkcs12 -in mycert.pfx -out tmpmycert.pem -nodes
Enter Import Password:
MAC verified OK
Convert the passwordless pem to a new pfx file with password:
[user#hostname]openssl pkcs12 -export -out mycert2.pfx -in tmpmycert.pem
Enter Export Password:
Verifying - Enter Export Password:
Remove the temporary file:
[user#hostname]rm tmpmycert.pem
Now you are done and can use the new mycert2.pfx file with your new password.
There will be no problem.
PFX is an encrypted container, changing the password of the container will have no effect on the certificates inside the container.
Using keytool there is no need to export anything and you won't lose any information. keytool can be used to change both passwords (keystore and private key). The key (excuse the pun) here is to change to password of the private key first. Otherwise, if the keystore password is different than the private key, keytool will not be able to change the password of the private key.
First change the password of the private key:
keytool -keystore <your.p12> -keypasswd -alias <alias_of_private_key>
Then change the password of the keystore:
keytool -keystore <your.p12> -storepasswd
That's all there is to it.
(Note: This method will still modify the iteration count the same way that #nyov's method does.)
Use the IKEYMAN tool for changing the password for the .p12 and key file.

Resources