Module: Ruby::Rego::Builtins::Crypto::Name

Defined in:
lib/ruby/rego/builtins/crypto/certificate_name.rb

Overview

Builds the Go pkix.Name JSON from a certificate’s RDNSequence ASN.1, mirroring Go’s FillFromRDNSequence: the standard attribute OIDs populate the typed fields (Country, Org, … as string arrays; CommonName / SerialNumber as strings), and every attribute also appears in Names[] as OID-int-array, Value. ExtraNames is nil for a parsed name.

Constant Summary collapse

ATTRIBUTE_FIELDS =

Attribute OID -> [pkix.Name field, multi-valued?]. Multi-valued fields are string arrays.

{
  "2.5.4.6" => ["Country", true], "2.5.4.10" => ["Organization", true],
  "2.5.4.11" => ["OrganizationalUnit", true], "2.5.4.7" => ["Locality", true],
  "2.5.4.8" => ["Province", true], "2.5.4.9" => ["StreetAddress", true],
  "2.5.4.17" => ["PostalCode", true], "2.5.4.3" => ["CommonName", false],
  "2.5.4.5" => ["SerialNumber", false]
}.freeze
NAME_FIELDS =
%w[Country Organization OrganizationalUnit Locality Province StreetAddress
PostalCode SerialNumber CommonName Names ExtraNames].freeze

Class Method Summary collapse

Class Method Details

.build(rdn_sequence, lenient: false) ⇒ Hash[String, untyped]

:reek:TooManyStatements – a faithful port of pkix.Name.FillFromRDNSequence’s single pass. rubocop:disable Metrics/AbcSize, Metrics/MethodLength lenient selects the CSR vs certificate handling of a UniversalString attribute value: Go’s ParseCertificateRequest keeps it (Names value null), while ParseCertificate rejects it. :reek:BooleanParameter :reek:NilCheck – lenient is a deliberate CSR/cert mode switch.

Parameters:

  • rdn_sequence (OpenSSL::ASN1::Sequence)

    the Name’s RDNSequence element

Returns:

  • (Hash[String, untyped])


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ruby/rego/builtins/crypto/certificate_name.rb', line 33

def self.build(rdn_sequence, lenient: false)
  # CommonName/SerialNumber are Go `string` fields (zero value ""); the rest are slices (nil).
  name = NAME_FIELDS.to_h { |field| [field, nil] } # : Hash[String, untyped]
  name["CommonName"] = name["SerialNumber"] = ""
  names = [] # : Array[untyped]
  rdn_sequence.value.each do |rdn|
    rdn.value.each do |attribute|
      type_and_value = attribute.value
      oid = type_and_value[0].oid
      value = attribute_value(type_and_value[1], lenient)
      names << { "Type" => CertificateStruct.oid_ints(oid), "Value" => value }
      assign(name, oid, value) unless value.nil?
    end
  end
  # Go's FillFromRDNSequence only appends, so an empty RDNSequence leaves Names a nil slice.
  name["Names"] = names unless names.empty?
  name
end