class Name < OpenSSL::ASN1::Sequence attr_accessor :givenName, :initial, :familyName asn1_tag 1, :APPLICATION, :IMPLICIT asn1_attr :givenName, OpenSSL::ASN1::ISO64String asn1_attr :initial, OpenSSL::ASN1::ISO64String asn1_attr :familyName, OpenSSL::ASN1::ISO64String end class EmployeeNumber < OpenSSL::ASN1::Integer asn1_tag 2, :APPLICATION, :IMPLICIT end class Date < OpenSSL::ASN1::ISO64String asn1_tag 3, :APPLICATION, :IMPLICIT end class ChildInformation < OpenSSL::ASN1::Set attr_accessor :name, :dateOfBirth asn1_attr :name, Name asn1_attr :dateOfBirth, Date, 0 end class PersonnelRecord < OpenSSL::ASN1::Set attr_accessor :name, :title, :number, :dateOfHire, :nameOfSpouse, :children asn1_tag 0, :APPLICATION, :IMPLICIT asn1_attr :name, Name asn1_attr :title, OpenSSL::ASN1::ISO64String, 0 asn1_attr :number, EmployeeNumber asn1_attr :dateOfHire, Date, 1 asn1_attr :nameOfSpouse, Name, 2 asn1_sequence :children, ChildInformation, 3, nil, :IMPLICIT end person = PersonnelRecord.new( :name => Name.new( :givenName => "John", :initial => "P", :familyName => "Smith" ), :number => 51, # or Number.new(51) ? :dateOfHire => "19710917", # or Date.new("19710917") ? :nameOfSpouse => Name.new( :givenName => "Mary", :initial => "T", :familyname => "Smith" ), :children => [ ChildInformation.new( :name => Name.new( :givenName => "Ralph", :initial => "T", :familyName => "Smith" ), :dateOfBirth => "19571111" ), ChildInformation.new( :name => Name.new( :givenName => "Susan", :initial => "B", :familyName => "Jones" ), :dateOfBirth => "19590717" ), ] ) assert_equal("John", person.name.givenName) assert_equal(51, person.number) # or person.number.value ? der = person.to_der p der.unpack("H*")[0].scan(/(..)/).join(":") person2 = OpenSSL::ASN1.decode(der) assert(person2 == person) # FIXME: the ASN1 structure info should be built into an object, and # it should be possible to have multiple such objects, so that ASN1.decode # can handle multiple record structures # FIXME: I'd prefer ASN1 to be mixed-in rather than direct inheritance