Module: Acme::Client::Util
Constant Summary collapse
- LINK_MATCH =
/<(.*?)>\s?;\s?rel="([\w-]+)"/
Instance Method Summary collapse
-
#ari_certificate_identifier(certificate) ⇒ Object
Generates a certificate identifier for ACME Renewal Information (ARI) as per RFC 9773.
-
#decode_link_headers(link_header) ⇒ Object
See RFC 8288 - tools.ietf.org/html/rfc8288#section-3.
-
#set_public_key(obj, priv) ⇒ Object
Sets public key on CSR or cert.
- #urlsafe_base64(data) ⇒ Object
Instance Method Details
#ari_certificate_identifier(certificate) ⇒ Object
Generates a certificate identifier for ACME Renewal Information (ARI) as per RFC 9773. The identifier is constructed by extracting the Authority Key Identifier (AKI) from the certificate extension, and the DER-encoded serial number (without tag and length bytes). Both values are base64url-encoded and concatenated with a period separator.
certificate - An OpenSSL::X509::Certificate instance or PEM string.
Returns a string in the format: base64url(AKI).base64url(serial)
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/acme/client/util.rb', line 44 def ari_certificate_identifier(certificate) cert = if certificate.is_a?(OpenSSL::X509::Certificate) certificate else OpenSSL::X509::Certificate.new(certificate) end aki_ext = cert.extensions.find { |ext| ext.oid == 'authorityKeyIdentifier' } raise ArgumentError, 'Certificate does not have an Authority Key Identifier extension' unless aki_ext aki_value = aki_ext.value hex_string = if aki_value =~ /keyid:([0-9A-Fa-f:]+)/ $1 elsif aki_value =~ /^[0-9A-Fa-f:]+$/ aki_value else raise ArgumentError, 'Could not parse Authority Key Identifier' end key_identifier = hex_string.split(':').map { |hex| hex.to_i(16).chr }.join serial_der = OpenSSL::ASN1::Integer.new(cert.serial).to_der serial_value = OpenSSL::ASN1.decode(serial_der).value.to_s(2) aki_b64 = urlsafe_base64(key_identifier) serial_b64 = urlsafe_base64(serial_value) "#{aki_b64}.#{serial_b64}" end |
#decode_link_headers(link_header) ⇒ Object
See RFC 8288 - tools.ietf.org/html/rfc8288#section-3
11 12 13 14 15 16 17 |
# File 'lib/acme/client/util.rb', line 11 def decode_link_headers(link_header) link_header.split(',').each_with_object({}) { |entry, hash| _, link, name = *entry.match(LINK_MATCH) hash[name] ||= [] hash[name].push(link) } end |
#set_public_key(obj, priv) ⇒ Object
Sets public key on CSR or cert.
obj - An OpenSSL::X509::Certificate or OpenSSL::X509::Request instance. priv - An OpenSSL::PKey::EC or OpenSSL::PKey::RSA instance.
Returns nothing.
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/acme/client/util.rb', line 25 def set_public_key(obj, priv) case priv when OpenSSL::PKey::EC obj.public_key = priv when OpenSSL::PKey::RSA obj.public_key = priv.public_key else raise ArgumentError, 'priv must be EC or RSA' end end |
#urlsafe_base64(data) ⇒ Object
4 5 6 |
# File 'lib/acme/client/util.rb', line 4 def urlsafe_base64(data) Base64.urlsafe_encode64(data).sub(/[\s=]*\z/, '') end |