Search code examples
javasslkeystorestring-matchingjks

List specific information of all LEAF certificates from java store JKS


I wish to list only the signed certificates for our application and not the chain signing certificate from a java store i.e <jdk_home>/jre/lib/security/cacerts or any such JKS store.

The idea that comes to mind is I will grab the value of CN= from the Owner: and check if it is present under Issuer: anywhere in the entire store. If found then it is not the signed cert but the signer's cert.

keytool -v -list -keystore cacerts -storepass "changeit"

Output:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 107 entries

*******************************************
*******************************************


Alias name: verisignuniversalrootca [jdk]
Creation date: Aug 25, 2016
Entry type: trustedCertEntry

Owner: CN=VeriSign Universal Root Certification Authority, OU="(c) 2008 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
Issuer: CN=VeriSign Universal Root Certification Authority, OU="(c) 2008 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
Serial number: 401ac46421b31321030ebbe4121ac51d
Valid from: Tue Apr 01 19:00:00 CDT 2008 until: Tue Dec 01 17:59:59 CST 2037
Certificate fingerprints:
         SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
         SHA256: 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions:

#1: ObjectId: 1.3.6.1.5.5.7.1.12 Criticality=false
0000: 30 5F A1 5D A0 5B 30 59   30 57 30 55 16 09 69 6D  0_.].[0Y0W0U..im
0010: 61 67 65 2F 67 69 66 30   21 30 1F 30 07 06 05 2B  age/gif0!0.0...+
0020: 0E 03 02 1A 04 14 8F E5   D3 1A 86 AC 8D 8E 6B C3  ..............k.
0030: CF 80 6A D4 48 18 2C 7B   19 2E 30 25 16 23 68 74  ..j.H.,...0%.#ht
0040: 74 70 3A 2F 2F 6C 6F 67   6F 2E 76 65 72 69 73 69  tp://logo.verisi
0050: 67 6E 2E 63 6F 6D 2F 76   73 6C 6F 67 6F 2E 67 69  gn.com/vslogo.gi
0060: 66                                                 f


#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

#3: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  Key_CertSign
  Crl_Sign
]

#4: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: B6 77 FA 69 48 47 9F 53   12 D5 C2 EA 07 32 76 07  .w.iHG.S.....2v.
0010: D1 97 07 19                                        ....
]
]



*******************************************
*******************************************


Alias name: xrampglobalca [jdk]
Creation date: Aug 25, 2016
Entry type: trustedCertEntry

Owner: CN=XRamp Global Certification Authority, O=XRamp Security Services Inc, OU=www.xrampsecurity.com, C=US
Issuer: CN=XRamp Global Certification Authority, O=XRamp Security Services Inc, OU=www.xrampsecurity.com, C=US
Serial number: 50946cec18ead59c4dd597ef758fa0ad
Valid from: Mon Nov 01 11:14:04 CST 2004 until: Sun Dec 31 23:37:19 CST 2034
Certificate fingerprints:
         SHA1: B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
         SHA256: CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions:

#1: ObjectId: 1.3.6.1.4.1.311.20.2 Criticality=false

i need to 2 step solution ...

Step 1: Identify the value of Owner: CN= for all Alias name: and consider only if that value of CN= which is not the value of Issuer: CN=

Step 2: Once identified the Alias name from Step 1, I wish to get the below details for that Alias

`Alias name: ` value
`Owner: CN=` value 
`Signature algorithm name:` value
`Subject Public Key Algorithm:` value
`Valid from:` value
`until:` value

Expected output:

verisignuniversalrootca [jdk]
VeriSign Universal Root Certification Authority
SHA256withRSA
2048-bit RSA key
Tue Apr 01 19:00:00 CDT 2008
Tue Dec 01 17:59:59 CST 2037

Note: the above is just a sample data which is incomplete.

You can choose <jdk_home>/jre/lib/security/cacerts on your systems for a more realistic and reproducible example.

I tried the below so far but it look its growing unclean so i m asking experts.

keytool -v -list -keystore cacerts -storepass "changeit" | awk '/Alias name:/ {print $3} /Owner: CN=/ {print substr($0, index($0,$4))}' | awk -F, '{print $1}'

I tried to convert cacerts to pkcs12 format and then print all client certs using openssl but it does not display all client cert information.

Convert to PKCS12:

keytool -importkeystore -srckeystore cacerts -srcstorepass "changeit" -destkeystore my_cert.p12 -deststoretype PKCS12 -deststorepass "changeit" -noprompt

Display Client certs:

openssl pkcs12 -in /home/wladmin/my_cert.p12 -passin pass:'changeit' -passout pass:'changeit' -info -nokeys -clcerts -legacy

MAC: sha256, Iteration 10000
MAC length: 32, salt length: 20
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 10000, PRF hmacWithSHA256
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag
Certificate bag

Kindly suggest.


Solution

  • I have created a cacerts.jks on my local with the help of this Oracle Documentation.

    I have executed this keytool command given below to demonstrate what I had in my JKS file for reference:

    ➜  ~ keytool -v -list -keystore cacerts.jks -storepass "changeit"
    Keystore type: PKCS12
    Keystore provider: SUN
    
    Your keystore contains 2 entries
    
    Alias name: alias-1
    Creation date: 27-Aug-2024
    Entry type: trustedCertEntry
    
    Owner: CN=localhost-1, OU=localhost-1, O=localhost-1, L=localhost-1, ST=localhost-1, C=L1
    Issuer: CN=localhost, OU=localhost, O=localhost, L=localhost, ST=localhost, C=LO
    Serial number: cdc993ae62b5af06
    Valid from: Mon Aug 26 12:48:12 IST 2024 until: Sun Nov 24 12:48:12 IST 2024
    Certificate fingerprints:
         SHA1: 7A:CA:34:2B:A1:93:78:01:DC:C2:44:49:65:B2:7E:19:46:4C:0D:5F
         SHA256: 47:71:55:78:C1:BC:B9:E8:D1:B2:35:47:D9:0D:07:1D:76:2B:1F:52:63:C5:D1:73:F8:9C:AE:F6:BE:6E:C8:04
    Signature algorithm name: SHA384withRSA
    Subject Public Key Algorithm: 3072-bit RSA key
    Version: 3
    
    Extensions:
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 16 29 19 7A A7 C8 64 1D   B2 6B E0 C7 79 0C 19 51  .).z..d..k..y..Q
    0010: 25 14 FA 33                                        %..3
    ]
    ]
    
    
    
    *******************************************
    *******************************************
    
    
    Alias name: server-alias
    Creation date: 27-Aug-2024
    Entry type: trustedCertEntry
    
    Owner: CN=localhost, OU=localhost, O=localhost, L=localhost, ST=localhost, C=LO
    Issuer: CN=localhost-1, OU=localhost-1, O=localhost-1, L=localhost-1, ST=localhost-1, C=L1
    Serial number: be304468d71fdc68
    Valid from: Mon Aug 26 12:24:54 IST 2024 until: Sun Nov 24 12:24:54 IST 2024
    Certificate fingerprints:
         SHA1: 18:BD:21:E0:A0:9A:E4:20:39:CA:F5:2F:C3:F5:D3:0F:B4:D5:EA:2B
         SHA256: 4D:6F:1E:27:1B:9C:04:58:87:B2:52:04:03:35:C1:30:63:3F:5C:0F:53:44:42:3E:CD:10:E3:65:7D:E0:3A:DC
    Signature algorithm name: SHA384withRSA
    Subject Public Key Algorithm: 3072-bit RSA key
    Version: 3
    
    Extensions:
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: C6 73 77 B3 9E E2 5C 84   B8 3C C6 D0 E2 38 C9 F9  .sw...\..<...8..
    0010: 93 9C 71 D4                                        ..q.
    ]
    ]
    
    
    
    *******************************************
    *******************************************
    

    Solution:

    Use this script given below:

    #!/bin/bash
    
    aliases=($(keytool -v -list -keystore cacerts.jks -storepass "changeit" | grep 'Alias name:' | awk -F: '{print $2}'))
    for i in "${aliases[@]}"; do
        cn_owner=$(keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==5 {print $2}' | sed 's/,//g' | awk -F= '{print $2}')
        cn_issuer=$(keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==6 {print $2}' | sed 's/,//g' | awk -F= '{print $2}')
        if [ $cn_owner == $cn_issuer ]; then
            continue
        else
            echo $i
            echo $cn_owner
            keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==8 {print $3, $4, $5, $6, $7, $8}'
            keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==8 {print $10, $11, $12, $13, $14, $15}'
            keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==12 {print $4}'
            keytool -v -list -keystore cacerts.jks -storepass "changeit" -alias $i | awk 'NR==13 {print $5, $6, $7}'
        fi
        echo "---------"
    done
    

    Output on my local:

    alias-1
    localhost-1
    Mon Aug 26 12:48:12 IST 2024
    Sun Nov 24 12:48:12 IST 2024
    SHA384withRSA
    3072-bit RSA key
    ---------
    server-alias
    localhost
    Mon Aug 26 12:24:54 IST 2024
    Sun Nov 24 12:24:54 IST 2024
    SHA384withRSA
    3072-bit RSA key
    ---------
    

    I have converted my JKS file to PKCS12 file using keytool command given below:

    keytool -importkeystore -srckeystore cacerts.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore cacerts.p12 -deststorepass "changeit" -noprompt
    

    You have to use this openssl command to see all client certificate information:

    openssl pkcs12 -in cacerts.p12 -passin pass:'changeit' -passout pass:'changeit'
    

    Output on my local:

    ➜  ~ openssl pkcs12 -in cacerts.p12 -passin pass:'changeit' -passout pass:'changeit' -info
    MAC: sha256, Iteration 10000
    MAC length: 32, salt length: 20
    PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 10000, PRF hmacWithSHA256
    Certificate bag
    Bag Attributes
        friendlyName: server-alias
        2.16.840.1.113894.746875.1.1: <Unsupported tag 6>
    subject=C = LO, ST = localhost, L = localhost, O = localhost, OU = localhost, CN = localhost
    issuer=C = L1, ST = localhost-1, L = localhost-1, O = localhost-1, OU = localhost-1, CN = localhost-1
    -----BEGIN CERTIFICATE-----
    MIIEhjCCAu6gAwIBAgIJAL4wRGjXH9xoMA0GCSqGSIb3DQEBDAUAMHExCzAJBgNV
    BAYTAkxPMRIwEAYDVQQIEwlsb2NhbGhvc3QxEjAQBgNVBAcTCWxvY2FsaG9zdDES
    MBAGA1UEChMJbG9jYWxob3N0MRIwEAYDVQQLEwlsb2NhbGhvc3QxEjAQBgNVBAMT
    CWxvY2FsaG9zdDAeFw0yNDA4MjYwNjU0NTRaFw0yNDExMjQwNjU0NTRaMHExCzAJ
    BgNVBAYTAkxPMRIwEAYDVQQIEwlsb2NhbGhvc3QxEjAQBgNVBAcTCWxvY2FsaG9z
    dDESMBAGA1UEChMJbG9jYWxob3N0MRIwEAYDVQQLEwlsb2NhbGhvc3QxEjAQBgNV
    BAMTCWxvY2FsaG9zdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALlE
    Ls2zeRJ6GWXbyKY413L6T0jYIsngE8TUwb2kW3VnHRzpBY68Uzkg2McBLgGkBBgV
    E1UzkHqaKNANQUcCQAdsvsKepHyiVike1CuZa5bGfT5lhAszfQBLelQOR1Q6pgJG
    wn9ZzzV+ZK5cBs4JXgj++eOwBJgPSQGwQpFyaoASFJ9IdRysx9y6Yp0TwGhFZLKx
    103SYEywVbEedhxgd9c7raoxP+KMuoT16Y47QWv14AtVF7S6+Ey+526GS+J42aQF
    FIPcCmUi8BXL/9xWHKVpcDeXtXXHVuSphfKOM5H/vae5ylD7Qn/WKadfPUY5zOA0
    6OY7TMCkFCa7COwgpUEQkytH/SK35Rq2D596DWLReIH02xP7tLuNV+W2cfjWf07i
    vICwGnu/ObUHcWrdMX8l5j4lNd1h6c8VIOLXVc7DWEWFs/TjZchD1r46Um2iqG5v
    6RugGJG//EGbCJVir5MhXvFgrDrDtz+gcnlEZVdvVm9WgBvhanNI6Z4TfmTEiQID
    AQABoyEwHzAdBgNVHQ4EFgQUxnN3s57iXIS4PMbQ4jjJ+ZOccdQwDQYJKoZIhvcN
    AQEMBQADggGBAF8J5zvk6iqWBWCwqGW6II4cuGaquqIEWW8vLR2NGWDLgttXh/eu
    JOGVFS19Ibcfyjvhh4hPt7Vt2Vq99mqrVa4V4BQpa46/23IEtVZ1gBvgLr0qkVdV
    xBvNCSgl8x3kWenDfspU4X3CsNIACmO4fLGIRb9aNIYY2LRmbX6LxW24dGfcP/GK
    xreXlmcDl8whCduLkh1C+0j0ZiENXRrGtYKzTP4tA6xmwIyDoSzRpQhCXXxe8doz
    Qlf65utEDvXaw5m/Aqd26Ten9A0KQVPjBUj9eYholDgpC5ojqU8MxaS/L+TxfYAa
    NsXDial0ky64L2lFQmNk2kB99ZfNjiINKEmw3d0qzkzFvAz6SflW+cr6jM7CyirA
    M4aQ3uqmlAaIPUjudKprGJpSWOVRx+CWqcs20hTOStK0G/lFDzccqaSeno0ZbuzR
    gnzfwKd4qleaebMZUGFXEabZIC7jEHsL3D4JtvZ8mmPMML/bQiLd2dvs+252nIyl
    v7qGYhT+ki+jzg==
    -----END CERTIFICATE-----
    Certificate bag
    Bag Attributes
        friendlyName: alias-1
        2.16.840.1.113894.746875.1.1: <Unsupported tag 6>
    subject=C = L1, ST = localhost-1, L = localhost-1, O = localhost-1, OU = localhost-1, CN = localhost-1
    issuer=C = LO, ST = localhost, L = localhost, O = localhost, OU = localhost, CN = localhost
    -----BEGIN CERTIFICATE-----
    MIIEnDCCAwSgAwIBAgIJAM3Jk65ita8GMA0GCSqGSIb3DQEBDAUAMHwxCzAJBgNV
    BAYTAkwxMRUwEwYDVQQIDAxsb2NhbGhvc3QtMVwxFDASBgNVBAcTC2xvY2FsaG9z
    dC0xMRQwEgYDVQQKEwtsb2NhbGhvc3QtMTEUMBIGA1UECxMLbG9jYWxob3N0LTEx
    FDASBgNVBAMTC2xvY2FsaG9zdC0xMB4XDTI0MDgyNjA3MTgxMloXDTI0MTEyNDA3
    MTgxMlowfDELMAkGA1UEBhMCTDExFTATBgNVBAgMDGxvY2FsaG9zdC0xXDEUMBIG
    A1UEBxMLbG9jYWxob3N0LTExFDASBgNVBAoTC2xvY2FsaG9zdC0xMRQwEgYDVQQL
    Ewtsb2NhbGhvc3QtMTEUMBIGA1UEAxMLbG9jYWxob3N0LTEwggGiMA0GCSqGSIb3
    DQEBAQUAA4IBjwAwggGKAoIBgQC9REFp1mlnyQBhgp2b0IdEBjRKZLyJGipjnZmF
    k1nd4SOjmY6RnxDXAnuJnxObWXEywPrpahUOF9y2no4RdnpkP2BsEjmVJXP6+g2X
    KDjWzqC5VaOrxJjQiHknXziV+34bS9V0M6g3fQKV/TeySIRJa7L+pfikp/C6agIz
    tOjjMTvHh+LpOQriwXgLYZhiHClWGR1SRQULY3O2SyqJ1hubz2k+TuruwvLyBuPt
    cfiy1GxU45YDiJlKVmoa5mkbjck3bsNfjjpCnS9Q8CARun/HE20OAKsTCBcHCc4S
    ZknxGrUHd+V8jBWk+c2qirDn0RCEXXlzQw8i035ONe9FkfI1/Yo2CRVhO0Obna7w
    OTytZsPC7sfw1mm0kLJydz4ZWzrZk9+3R1uKCUrtJOjBYB4pOOafGCWRuoWd6Y6P
    isQoFxq1MZIOreoc9Qwy/D6iyQgrrujryQCG8opCTcL40/Zo+OceT/wDmXUR+GBp
    9rGymc/NlmvXVvdER8mPEzZVx5kCAwEAAaMhMB8wHQYDVR0OBBYEFBYpGXqnyGQd
    smvgx3kMGVElFPozMA0GCSqGSIb3DQEBDAUAA4IBgQBcBU7DA5970AmX0HvtC5zh
    bvYrNAqRFm6iIJakol6GEQIyvPtPb3MA7FtwTkCnhLD1zAM1C+xIyL85G1Ww2B7A
    /CdWI5dSvA9hQve69dYI/zHiyMJDcDcclQNrV1S+kaUii/VtVhXMKYMK7GtwF/3d
    rr4Jy7eDPzIRxWHyA+sd2Y7ZtwNhuNXuZTa5veCrbO3FfdO6ygLhSY5CFtY8KBn7
    8Knb9JpxJF+/pSPMC+sk46b0OsWH6IojQlZvkh8BCbla9/RgpnwKxkebjZcVqaP7
    KWgVL36/EtdWzdgPPxnV139ZI3zGq9syioTLhZ+/3i4MWmuIy6KDHUCKC1s6quy2
    FKg00a+eu49bfmNBSG3vAfXC71sXH6C4zwSpX1tVzOzQ9yOLl7Fc6+Ya/bb3xIY2
    kkfBJedpwi4lQQqIdG99uL0IhzdoMEC2JjwdVdhSmmhuQzWk8Z2brr2amxNJy6gi
    94v1bPnKQppQC4kZ1by913/bUzgyRd8X2QVN3vPu2HM=
    -----END CERTIFICATE-----