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.