lib/yoti/util/anchor_processor.rb in yoti-1.4.0 vs lib/yoti/util/anchor_processor.rb in yoti-1.5.0
- old
+ new
@@ -1,61 +1,98 @@
require 'openssl'
require 'date'
module Yoti
+ #
# Parse attribute anchors
+ #
class AnchorProcessor
+ #
+ # @param [Array<Yoti::Protobuf::Attrpubapi::Anchor>]
+ #
def initialize(anchors_list)
@anchors_list = anchors_list
@get_next = false
end
+ #
+ # Extract matching Attribute Anchors from list.
+ #
+ # @return [Array<Yoti::Anchor>]
+ #
def process
- result_data = { 'sources' => [], 'verifiers' => [] }
- anchor_types = self.anchor_types
+ result_data = ANCHOR_LIST_KEYS.map { |key, _value| [key, []] }.to_h
@anchors_list.each do |anchor|
x509_certs_list = convert_certs_list_to_X509(anchor.origin_server_certs)
- yoti_signed_time_stamp = process_signed_time_stamp(anchor.signed_time_stamp)
-
- anchor.origin_server_certs.each do |cert|
- anchor_types.each do |type, oid|
- yoti_anchor = get_anchor_by_oid(cert, oid, anchor.sub_type, yoti_signed_time_stamp, x509_certs_list)
- result_data[type].push(yoti_anchor) unless yoti_anchor.nil?
- end
- end
+ signed_time_stamp = process_signed_time_stamp(anchor.signed_time_stamp)
+ yoti_anchor = get_anchor_from_certs(x509_certs_list, anchor.sub_type, signed_time_stamp)
+ anchor_list_key = get_anchor_list_key_by_type(yoti_anchor.type)
+ result_data[anchor_list_key].push(yoti_anchor)
end
result_data
end
+ #
+ # Convert certificate list to a list of X509 certificates.
+ #
+ # @param [Google::Protobuf::RepeatedField] certs_list
+ #
+ # @return [Array<OpenSSL::X509::Certificate>]
+ #
def convert_certs_list_to_X509(certs_list)
x509_certs_list = []
certs_list.each do |cert|
- x509_cert = OpenSSL::X509::Certificate.new cert
- x509_certs_list.push x509_cert
+ x509_certs_list.push OpenSSL::X509::Certificate.new(cert)
end
-
x509_certs_list
end
+ #
+ # Return signed timestamp.
+ #
+ # @param [String] signed_time_stamp_binary
+ #
+ # @return [Yoti::SignedTimeStamp]
+ #
def process_signed_time_stamp(signed_time_stamp_binary)
signed_time_stamp = Yoti::Protobuf::Compubapi::SignedTimestamp.decode(signed_time_stamp_binary)
- time_in_sec = signed_time_stamp.timestamp / 1000000
- date_time = Time.parse(Time.at(time_in_sec).to_s)
- Yoti::SignedTimeStamp.new(signed_time_stamp.version, date_time)
+ time_in_sec = signed_time_stamp.timestamp.quo(1000000)
+ Yoti::SignedTimeStamp.new(signed_time_stamp.version, Time.at(time_in_sec))
end
+ #
+ # Return Anchor for provided oid.
+ #
+ # @deprecated no longer in use
+ #
+ # @param [OpenSSL::X509::Certificate] cert
+ # @param [String] oid
+ # @param [String] sub_type
+ # @param [Yoti::SignedTimeStamp] signed_time_stamp
+ # @param [Array<OpenSSL::X509::Certificate>] x509_certs_list
+ #
+ # @return [Yoti::Anchor, nil]
+ #
def get_anchor_by_oid(cert, oid, sub_type, signed_time_stamp, x509_certs_list)
asn1_obj = OpenSSL::ASN1.decode(cert)
anchor_value = get_anchor_value_by_oid(asn1_obj, oid)
- return nil if anchor_value.nil?
-
- Yoti::Anchor.new(anchor_value, sub_type, signed_time_stamp, x509_certs_list)
+ Yoti::Anchor.new(anchor_value, sub_type, signed_time_stamp, x509_certs_list) unless anchor_value.nil?
end
+ #
+ # Return Anchor value for provided oid.
+ #
+ # @deprecated no longer in use
+ #
+ # @param [OpenSSL::ASN1::Sequence, OpenSSL::ASN1::ASN1Data, Array] obj
+ # @param [String] oid
+ #
+ # @return [String, nil]
+ #
def get_anchor_value_by_oid(obj, oid)
case obj
when OpenSSL::ASN1::Sequence, Array
return get_anchor_value_by_asn1_sequence(obj, oid)
when OpenSSL::ASN1::ASN1Data
@@ -64,38 +101,167 @@
# In case it's not a valid object
nil
end
+ #
+ # Return Anchor value for ASN1 data.
+ #
+ # @deprecated no longer in use
+ #
+ # @param [OpenSSL::ASN1::ASN1Data] value
+ # @param [String] oid
+ #
+ # @return [String, nil]
+ #
def get_anchor_value_by_asn1_data(value, oid)
if value.respond_to?(:to_s) && value == oid
@get_next = true
elsif value.respond_to?(:to_s) && @get_next
- raw_value = OpenSSL::ASN1.decode(value)
- anchor_value = raw_value.value[0].value
@get_next = false
- return anchor_value
+ return OpenSSL::ASN1.decode(value).value[0].value
end
get_anchor_value_by_oid(value, oid)
end
+ #
+ # Return Anchor value for ASN1 sequence.
+ #
+ # @deprecated no longer in use
+ #
+ # @param [OpenSSL::ASN1::Sequence, Array] obj
+ # @param [String] oid
+ #
+ # @return [String, nil]
+ #
def get_anchor_value_by_asn1_sequence(obj, oid)
obj.each do |child_obj|
result = get_anchor_value_by_oid(child_obj, oid)
return result unless result.nil?
end
nil
end
+ #
+ # Mapping of anchor types to oid.
+ #
+ # @deprecated no longer in use
+ #
+ # @return [Hash]
+ #
def anchor_types
- { 'sources' => '1.3.6.1.4.1.47127.1.1.1',
- 'verifiers' => '1.3.6.1.4.1.47127.1.1.2' }
+ ANCHOR_LIST_KEYS
end
protected
+ #
# Define whether the search function get_anchor_value_by_oid
# should return the next value in the array
+ #
+ # @deprecated no longer in use
+ #
+ # @return [Boolean]
+ #
attr_reader :get_next
+
+ private
+
+ #
+ # Mapping of anchor types.
+ #
+ ANCHOR_TYPES = {
+ 'SOURCE' => '1.3.6.1.4.1.47127.1.1.1',
+ 'VERIFIER' => '1.3.6.1.4.1.47127.1.1.2',
+ 'UNKNOWN' => ''
+ }.freeze
+
+ #
+ # Mapping of anchor list keys.
+ #
+ ANCHOR_LIST_KEYS = {
+ 'sources' => ANCHOR_TYPES['SOURCE'],
+ 'verifiers' => ANCHOR_TYPES['VERIFIER'],
+ 'unknown' => ANCHOR_TYPES['UNKNOWN']
+ }.freeze
+
+ #
+ # Get anchor type by oid.
+ #
+ # @param [String] oid
+ #
+ def get_anchor_type_by_oid(oid)
+ ANCHOR_TYPES.find { |_key, value| value == oid }.first
+ end
+
+ #
+ # Get anchor list key by type.
+ #
+ # @param [String] type
+ #
+ def get_anchor_list_key_by_type(type)
+ ANCHOR_LIST_KEYS.find { |_key, value| value == ANCHOR_TYPES[type] }.first
+ end
+
+ #
+ # Get anchor from provided certificate list.
+ #
+ # @param [Array<OpenSSL::X509::Certificate>] x509_certs_list
+ # @param [String] sub_type
+ # @param [Yoti::SignedTimeStamp] signed_time_stamp
+ #
+ # @return [Yoti::Anchor]
+ #
+ def get_anchor_from_certs(x509_certs_list, sub_type, signed_time_stamp)
+ x509_certs_list.each do |cert|
+ ANCHOR_TYPES.each do |_type, oid|
+ anchor_extension = get_extension_by_oid(cert, oid)
+ next if anchor_extension.nil?
+
+ return Yoti::Anchor.new(
+ get_anchor_value(anchor_extension),
+ sub_type,
+ signed_time_stamp,
+ x509_certs_list,
+ get_anchor_type_by_oid(oid)
+ )
+ end
+ end
+ Yoti::Anchor.new('', sub_type, signed_time_stamp, x509_certs_list, 'UNKNOWN')
+ end
+
+ #
+ # Get extension for provided oid.
+ #
+ # @param [OpenSSL::X509::Certificate] cert
+ # @param [String] oid
+ #
+ # @return [OpenSSL::X509::Extension]
+ #
+ def get_extension_by_oid(cert, oid)
+ cert.extensions.each do |extension|
+ return extension if extension.oid == oid
+ end
+ nil
+ end
+
+ #
+ # Return Anchor value.
+ #
+ # @param [OpenSSL::X509::Extension] anchor_extension
+ #
+ # @return [String, nil]
+ #
+ def get_anchor_value(anchor_extension)
+ decoded_extension = OpenSSL::ASN1.decode(anchor_extension)
+ extension_value = decoded_extension.value[1] if decoded_extension.value.is_a?(Array)
+ extension_value_item = extension_value.value if extension_value.is_a?(OpenSSL::ASN1::OctetString)
+ if extension_value_item.is_a?(String)
+ decoded = OpenSSL::ASN1.decode(extension_value_item)
+ return decoded.value[0].value if decoded.value[0].is_a?(OpenSSL::ASN1::ASN1Data)
+ end
+
+ nil
+ end
end
end