How to know which X509 Certificate Signed another Certificate (Java) -
there 3 certificates in example, assume form chain don't know yet of them signed which:
x509certificate c1 = .... x509certificate c2 = .... x509certificate c2 = ....
i know certificate responsible signing other certificate.
the plan "authoritykeyidentifier" , match "subjectkeyidentifier".
import org.bouncycastle.asn1. deroctetstring; private static string decodekey(byte[] e) { deroctetstring octet = new deroctetstring(e); return octet.tostring(); } string subjectkeyid = decodekey(c.getextensionvalue("2.5.29.14")); string authoritykeyid = decodekey(c.getextensionvalue("2.5.29.35"));
im getting following certificates (in order of chain): subject/authority key id pair
values of subjectkeyidentifier , authoritykeyidentifier after decoding:
certificate 1: (end of chain)
#0416041482b7384a93aa9b10ef80bbd954e2f10ffb809cde #04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde
certificate 2: signed certificate 1
#04160414ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3 #04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde
certificate 3: signed certificate 2
(no subjectkeyidentifier - null bytes) #041830168014ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3
formatted , aligned easy reading (same thing 1 on top)
------------------------------------------------------------------------------ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ------------------------------------------------------------------------------ certificate 1 #04 16 04 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de #04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de certificate 2 #04 16 04 14 ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3 #04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de certificate 3 === == == == == == == == == == == no data == == == == == == == == == == == == #04 18 30 16 80 14 ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3
i expecting c3's authoritykeyidentifier equivalent c2's subjectkeyidentifier. not seem case here.
edit: parts of result seem match, have idea on "subjectkeyidentifier" - starts '#04' followed length of contents (in hex). have idea on how decode "subjectkeyidentifier", "authoritykeyidentifier" still big mystery me.
relevant so post
did wrong decoding? why authoritykeyidentifier not matching correctly against subjectkeyidentifier of certificate signed it?
if take @ asn.1 definition of ski , aki in rfc5280 (following links in question) difference becomes obvious:
subjectkeyidentifier ::= keyidentifier authoritykeyidentifier ::= sequence { keyidentifier [0] keyidentifier optional, authoritycertissuer [1] generalnames optional, authoritycertserialnumber [2] certificateserialnumber optional } keyidentifier ::= octet string
so, aki not octet string, sequence of 3 optional elements. 1 of these elements octet string can compared ski.
the distinguished encoding rules (der) determine byte representation of these asn.1 structures. individual bytes of aki extension have following meaning (see a layman's guide subset of asn.1, ber, , der):
04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de 04 octet string 18 length 30 sequence 16 length 80 context-specific primitive tag 0 14 length .. data
the first 2 bytes (04 18) part of extension structure (as explained in related question why doesn't key identifier match?), actual aki extension content starts @ "30 16".
your java code decoding aki should (using bouncy castle):
byte[] extensionvalue = cert.getextensionvalue("2.5.29.35"); byte[] octets = deroctetstring.getinstance(extensionvalue).getoctets(); authoritykeyidentifier authoritykeyidentifier = authoritykeyidentifier.getinstance(octets); byte[] keyidentifier = authoritykeyidentifier.getkeyidentifier(); string keyidentifierhex = new string(hex.encode(keyidentifier));
and decoding ski:
extensionvalue = cert.getextensionvalue("2.5.29.14"); octets = deroctetstring.getinstance(extensionvalue).getoctets(); subjectkeyidentifier subjectkeyidentifier = subjectkeyidentifier.getinstance(octets); keyidentifier = subjectkeyidentifier.getkeyidentifier(); keyidentifierhex = new string(hex.encode(keyidentifier));
also, both extensions optional. if code should work arbitrary certificates, fallback mechanism necessary (like verifying signatures).
Comments
Post a Comment