Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

access to raw public key, or keyid #163

Open
mcr opened this issue Oct 24, 2017 · 2 comments
Open

access to raw public key, or keyid #163

mcr opened this issue Oct 24, 2017 · 2 comments

Comments

@mcr
Copy link
Contributor

mcr commented Oct 24, 2017

RFC5280, section 4.2.1.2 defines keyid as the SHA1 of the subjectPublicKey encoding.

OpenSSL::PKey::EC's to_text 

reveals the public key info via an OpenSSL method that produces text. This is the input that we need for the SHA1, and I guess I could decode the text back to binary if I had to, but this seems really wrong....
While there is some code in openssl/crypto/x509v3/v3_skey.c that calculates what I want, it's buried inside an extension definition, and can't (AFAIK) be used directly.

I can get what I want via:
a1 = OpenSSL::ASN1.decode(pubkey.to_der)
a1.value[1].value

but that just seems wrong. Is there another way to pull the encoded public key out?
Should getting this keyid be ruby or C code?

@mcr
Copy link
Contributor Author

mcr commented Oct 24, 2017

RFC5280 has an example, which is available at:
https://csrc.nist.gov/projects/pki-testing/sample-certificates-and-crls

you want example C.2. Download it as rfc5280_cert2.cer.

Start an irb:

> cert = OpenSSL::X509::Certificate.new(IO::read("rfc5280_cert2.cer"))                            
                                                                                              
2.4.1 :005 > cert.extensions[1].to_s                                                              
 => "subjectKeyIdentifier =                                                                  
17:7B:92:30:FF:44:D6:66:E1:90:10:22:6C:16:4F:C0:8E:41:DD:6D"                                      

(matches line 7930 of rfc5280, so this is the right object)

2.4.1 :013 > der = cert.public_key.to_der                                                         
2.4.1 :014 > asn1 = OpenSSL::ASN1.decode(der)                                                     
2.4.1 :015 > rawpubkey = nil                                                                      
 => nil                                                                                           
 2.4.1 :016 > asn1.value.each {|v|                                                                
 2.4.1 :017 >           if v.tag == 3                                                             
 2.4.1 :018?>             rawpubkey = v.value                                                     
 2.4.1 :019?>           end                                                                       
 2.4.1 :020?>       }                                                                             
                                                                                                  
2.4.1 :039 > Digest::SHA1.digest(rawpubkey).unpack("H*")                                          
 => ["177b9230ff44d666e19010226c164fc08e41dd6d"]                                                  

YEAH. So getting it out of openssl/ruby-openssl is a bit daft, but it works and gives the right answer. Should this be added as ruby code until we find a better way to get it out of the OpenSSL API?

@rhenium
Copy link
Member

rhenium commented Oct 28, 2017

With the current Ruby/OpenSSL, it has to be extracted from the output of a_public_pkey.to_der. If what you need is to (re)calculate just the SHA-1 for a subject key identifier, you might be able to use OpenSSL::X509::ExtensionFactory.

cert = OpenSSL::X509::Certificate.new
cert.public_key = ...
ef = OpenSSL::X509::ExtensionFactory.new(nil, cert)
p ext = ef.create_extension("subjectKeyIdentifier", "hash")

Actually, OpenSSL provides X509_get0_pubkey_bitstr() function that does the job. It's possible to add a binding to that, but I wonder what use case this would benefit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants