diff --git a/asn1crypto/cms.py b/asn1crypto/cms.py index c395b22..b104c99 100644 --- a/asn1crypto/cms.py +++ b/asn1crypto/cms.py @@ -729,6 +729,12 @@ class RecipientKeyIdentifier(Sequence): ('other', OtherKeyAttribute, {'optional': True}), ] + def _setup(self): + super(RecipientKeyIdentifier, self)._setup() + # This creates a backwards compatible shim for an + # incorrect format field name that was in old versions + self._field_map['subjectKeyIdentifier'] = self._field_map['subject_key_identifier'] + class KeyAgreementRecipientIdentifier(Choice): _alternatives = [ @@ -929,21 +935,20 @@ def decompressed(self): return self._decompressed -class RecipientKeyIdentifier(Sequence): - _fields = [ - ('subjectKeyIdentifier', OctetString), - ('date', GeneralizedTime, {'optional': True}), - ('other', OtherKeyAttribute, {'optional': True}), - ] - - class SMIMEEncryptionKeyPreference(Choice): _alternatives = [ ('issuer_and_serial_number', IssuerAndSerialNumber, {'implicit': 0}), - ('recipientKeyId', RecipientKeyIdentifier, {'implicit': 1}), - ('subjectAltKeyIdentifier', PublicKeyInfo, {'implicit': 2}), + ('recipient_key_id', RecipientKeyIdentifier, {'implicit': 1}), + ('subject_alt_key_identifier', PublicKeyInfo, {'implicit': 2}), ] + def _setup(self): + super(SMIMEEncryptionKeyPreference, self)._setup() + # This creates backwards compatible shims for two + # incorrect format alternative names that were in old versions + self._name_map['recipientKeyId'] = self._name_map['recipient_key_id'] + self._name_map['subjectAltKeyIdentifier'] = self._name_map['subject_alt_key_identifier'] + class SMIMEEncryptionKeyPreferences(SetOf): _child_spec = SMIMEEncryptionKeyPreference diff --git a/asn1crypto/core.py b/asn1crypto/core.py index 2edd4f3..428ef0e 100644 --- a/asn1crypto/core.py +++ b/asn1crypto/core.py @@ -3429,6 +3429,17 @@ def __init__(self, value=None, default=None, **kwargs): self.__setitem__(key, value[key]) unused_keys.remove(key) + # This handles the situation where there is field name + # mapping going on due to a field be renamed. Normally + # the keys are checked against the primary field list. + # If there are still keys left over, check to see if they + # are mapped via checking the _field_map. + if len(unused_keys): + for key in list(unused_keys): + if key in self._field_map: + self.__setitem__(key, value[key]) + unused_keys.remove(key) + if len(unused_keys): raise ValueError(unwrap( ''' diff --git a/tests/test_cms.py b/tests/test_cms.py index 8f9b1e6..2698282 100644 --- a/tests/test_cms.py +++ b/tests/test_cms.py @@ -1001,3 +1001,41 @@ def test_create_role_syntax(self): ]), rs.native ) + + def test_backwards_compat_field_name(self): + new_version = cms.RecipientKeyIdentifier({'subject_key_identifier': b'\x08\x09\x10'}) + old_version = cms.RecipientKeyIdentifier({'subjectKeyIdentifier': b'\x08\x09\x10'}) + self.assertEqual( + new_version.dump(True), + old_version.dump(True), + ) + self.assertEqual( + new_version.native, + old_version.native, + ) + + def test_backwards_compat_choice_names(self): + rki = cms.RecipientKeyIdentifier({'subject_key_identifier': b'\x08\x09\x10'}) + new_sekp = cms.SMIMEEncryptionKeyPreference({'recipient_key_id': rki}) + old_sekp = cms.SMIMEEncryptionKeyPreference({'recipientKeyId': rki}) + + self.assertEqual( + new_sekp.dump(True), + old_sekp.dump(True), + ) + self.assertEqual( + new_sekp.native, + old_sekp.native, + ) + self.assertEqual( + new_sekp.chosen.untag().dump(True), + rki.dump(True), + ) + self.assertEqual( + 'recipient_key_id', + new_sekp.name, + ) + self.assertEqual( + 'recipient_key_id', + old_sekp.name, + )