Class: Sigstore::Internal::X509::Certificate
- Inherits:
-
Object
- Object
- Sigstore::Internal::X509::Certificate
- Extended by:
- Forwardable
- Defined in:
- lib/sigstore/internal/x509.rb
Instance Attribute Summary collapse
-
#openssl ⇒ Object
readonly
Returns the value of attribute openssl.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
- #ca? ⇒ Boolean
- #extension(cls) ⇒ Object
-
#initialize(x509_certificate) ⇒ Certificate
constructor
A new instance of Certificate.
- #leaf? ⇒ Boolean
- #preissuer? ⇒ Boolean
- #tbs_certificate_der ⇒ Object
Constructor Details
#initialize(x509_certificate) ⇒ Certificate
Returns a new instance of Certificate.
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/sigstore/internal/x509.rb', line 96 def initialize(x509_certificate) unless x509_certificate.is_a?(OpenSSL::X509::Certificate) raise ArgumentError, "Invalid certificate: #{x509_certificate.inspect}" end @openssl = x509_certificate raise Error::InvalidCertificate, "invalid X.509 version: #{version.inspect}" if version != 2 # v3 end |
Instance Attribute Details
#openssl ⇒ Object (readonly)
Returns the value of attribute openssl.
94 95 96 |
# File 'lib/sigstore/internal/x509.rb', line 94 def openssl @openssl end |
Class Method Details
.read(certificate_bytes) ⇒ Object
107 108 109 110 111 |
# File 'lib/sigstore/internal/x509.rb', line 107 def self.read(certificate_bytes) new(OpenSSL::X509::Certificate.new(certificate_bytes)) rescue OpenSSL::X509::CertificateError => e raise Error::InvalidCertificate, e. end |
Instance Method Details
#==(other) ⇒ Object
168 169 170 |
# File 'lib/sigstore/internal/x509.rb', line 168 def ==(other) openssl == other.openssl end |
#ca? ⇒ Boolean
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/sigstore/internal/x509.rb', line 190 def ca? basic_constraints = extension(Extension::BasicConstraints) return false unless basic_constraints unless basic_constraints.critical? raise Error::InvalidCertificate, "invalid X.509 certificate: non-critical BasicConstraints in CA" end key_usage = extension(Extension::KeyUsage) raise Error::InvalidCertificate, "no keyUsage in #{openssl.inspect}" unless key_usage ca = basic_constraints.ca key_cert_sign = key_usage.key_cert_sign return true if ca && key_cert_sign return false unless key_cert_sign || ca raise Error::InvalidCertificate, "invalid X.509 certificate: inconsistent CA/KeyCertSign in BasicConstraints/KeyUsage " \ "(#{ca.inspect}, #{key_cert_sign.inspect}):" \ "\n#{openssl.extensions.map(&:to_h).pretty_inspect}" \ "\n#{key_usage.pretty_inspect}" end |
#extension(cls) ⇒ Object
158 159 160 161 162 163 |
# File 'lib/sigstore/internal/x509.rb', line 158 def extension(cls) openssl.extensions.each do |ext| return cls.new(ext) if ext.oid == cls.oid || ext.oid == cls.oid.short_name || ext.oid == cls.oid.oid end nil end |
#leaf? ⇒ Boolean
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/sigstore/internal/x509.rb', line 172 def leaf? return false if ca? key_usage = extension(Extension::KeyUsage) || raise(Error::InvalidCertificate, "no keyUsage in #{openssl.extensions.map(&:to_h)}") unless key_usage.digital_signature raise Error::InvalidCertificate, "invalid certificate for Sigstore purposes: missing digital signature usage: #{key_usage.to_h}" end extended_key_usage = extension(Extension::ExtendedKeyUsage) return false unless extended_key_usage extended_key_usage.code_signing? end |
#preissuer? ⇒ Boolean
216 217 218 219 220 221 |
# File 'lib/sigstore/internal/x509.rb', line 216 def preissuer? extended_key_usage = extension(Extension::ExtendedKeyUsage) return false unless extended_key_usage extended_key_usage.precert? end |
#tbs_certificate_der ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/sigstore/internal/x509.rb', line 113 def tbs_certificate_der if openssl.respond_to?(:tbs_bytes) cert = openssl.dup short_name = Extension::PrecertificateSignedCertificateTimestamps.oid.short_name cert.extensions = cert.extensions.reject! do |ext| ext.oid == short_name end || raise(Error::InvalidCertificate, "No PrecertificateSignedCertificateTimestamps found for the certificate") return cert.tbs_bytes end extension(Extension::PrecertificateSignedCertificateTimestamps) || raise(Error::InvalidCertificate, "No PrecertificateSignedCertificateTimestamps found for the certificate") # This uglyness is needed because there is no way to force modifying an X509 certificate # in a way that it will be serialized with the modifications. seq = OpenSSL::ASN1.decode(to_der) unless seq.is_a?(OpenSSL::ASN1::Sequence) && seq.value.size == 3 raise Error::InvalidCertificate, "invalid X.509 certificate: #{seq.class} #{seq.value.size}" end seq = seq.value[0] unless seq.is_a?(OpenSSL::ASN1::Sequence) raise Error::InvalidCertificate, "invalid X.509 certificate: #{seq.inspect}" end seq.value = seq.value.map! do |v| next v unless v.tag == 3 v.value = v.value.map! do |v2| v2.value = v2.value.map! do |v3| next if v3.first.oid == Extension::PrecertificateSignedCertificateTimestamps.oid.oid v3 end.compact! || raise(Error::InvalidCertificate, "no SCTs found") v2 end v end seq.to_der end |