def parse_encryption(cls, encryption, key_info): """Read encryption information from the <EncryptionKey> XML tree.""" if key_info is None: return encryption.id = key_info.get('Id') encryption.algorithm = ( key_info.get('Algorithm') or key_info.get('algorithm') or encryption.algorithm) for name in findall(key_info, 'KeyName', 'DerivedKey/MasterKeyName', 'DerivedKey/CarriedKeyName'): encryption.key_names.append(findtext(name, '.')) encryption.iv = findbin(key_info, 'IV') or encryption.iv cls.parse_key_derivation(encryption.derivation, find( key_info, 'DerivedKey/KeyDerivationMethod')) encryption.derivation.pbkdf2_salt = ( findbin(key_info, 'PBESalt') or encryption.derivation.pbkdf2_salt) encryption.derivation.pbkdf2_iterations = ( findint(key_info, 'PBEIterationCount') or encryption.derivation.pbkdf2_iterations) algorithm = ( key_info.get('Algorithm') or key_info.get('algorithm') or '') if (algorithm.lower().startswith('pbe') and not encryption.derivation.algorithm): encryption.derivation.algorithm = 'pbkdf2' encryption.derivation.pbkdf2_key_length = ( encryption.derivation.pbkdf2_key_length or encryption.algorithm_key_lengths[0])
def parse_signature(cls, signature, signature_elm): """Read signature information from the <Signature> element.""" if signature_elm is None: return cm_elm = find(signature_elm, 'SignedInfo/CanonicalizationMethod') if cm_elm is not None: signature.canonicalization_method = cm_elm.attrib.get('Algorithm') sm_elm = find(signature_elm, 'SignedInfo/SignatureMethod') if sm_elm is not None: signature.algorithm = sm_elm.attrib.get('Algorithm') dm_elm = find(signature_elm, 'SignedInfo/Reference/DigestMethod') if dm_elm is not None: signature.digest_algorithm = dm_elm.attrib.get('Algorithm') issuer = find(signature_elm, 'KeyInfo/X509Data/X509IssuerSerial') if issuer is not None: signature.issuer = findtext(issuer, 'X509IssuerName') signature.serial = findtext(issuer, 'X509SerialNumber') certificate = findbin( signature_elm, 'KeyInfo/X509Data/X509Certificate') if certificate: certificate = base64.b64encode(certificate) signature.certificate = b'\n'.join( [b'-----BEGIN CERTIFICATE-----'] + [certificate[i:i + 64] for i in range(0, len(certificate), 64)] + [b'-----END CERTIFICATE-----'])
def parse_data(cls, key, field, element): """Read information from the provided element. The element is expected to contain <PlainValue>, <EncryptedValue> and/or <ValueMAC> elements that contain information on the actual value. """ if element is None: return pskc = key.device.pskc plain_value = None cipher_value = None algorithm = None # get the plain2value function and encryption storage if field == 'secret': plain2value = base64.b64decode encrypted_value_cls = EncryptedValue else: plain2value = plain2int encrypted_value_cls = EncryptedIntegerValue # read plaintext value from <PlainValue> plain_value = findtext(element, 'PlainValue') if plain_value is not None: plain_value = plain2value(plain_value) # read encrypted data from <EncryptedValue> encrypted_value = find(element, 'EncryptedValue') if encrypted_value is not None: algorithm, cipher_value = cls.parse_encrypted_value( encrypted_value) # store the found algorithm in the pskc.encryption property if not pskc.encryption.algorithm and algorithm: pskc.encryption.algorithm = algorithm # read MAC information from <ValueMAC> mac_value = findbin(element, 'ValueMAC', 'ValueDigest') # read legacy <Value> elements (can be plain or encrypted) value = findtext(element, 'Value') if value is not None: if pskc.encryption.algorithm and mac_value: cipher_value = findbin(element, 'Value') else: plain_value = plain2value(value) # store the found information if plain_value is not None: setattr(key, field, plain_value) elif cipher_value: setattr(key, field, encrypted_value_cls(cipher_value, mac_value, algorithm))
def parse(self, encrypted_value): """Read encrypted data from the <EncryptedValue> XML tree.""" from pskc.xml import find, findbin if encrypted_value is None: return encryption_method = find(encrypted_value, 'xenc:EncryptionMethod') if encryption_method is not None: self.algorithm = encryption_method.attrib.get('Algorithm') self.cipher_value = findbin( encrypted_value, 'xenc:CipherData/xenc:CipherValue')
def parse_encrypted_value(cls, encrypted_value): """Read encryption value from <EncryptedValue> element.""" algorithm = None cipher_value = findbin(encrypted_value, 'CipherData/CipherValue') encryption_method = find(encrypted_value, 'EncryptionMethod') if encryption_method is not None: algorithm = encryption_method.attrib.get('Algorithm') encryption_scheme = find( encrypted_value, 'EncryptionMethod/EncryptionScheme') if encryption_scheme is not None: algorithm = encryption_scheme.attrib.get('Algorithm') or algorithm return (algorithm, cipher_value)
def parse_key_derivation(cls, derivation, key_derivation): """Read derivation parameters from a <KeyDerivationMethod> element.""" if key_derivation is None: return derivation.algorithm = key_derivation.get('Algorithm') # PBKDF2 properties pbkdf2 = find(key_derivation, 'PBKDF2-params') if pbkdf2 is not None: # get used salt derivation.pbkdf2_salt = findbin(pbkdf2, 'Salt/Specified') # required number of iterations derivation.pbkdf2_iterations = findint(pbkdf2, 'IterationCount') # key length derivation.pbkdf2_key_length = findint(pbkdf2, 'KeyLength') # pseudorandom function used prf = find(pbkdf2, 'PRF') if prf is not None: derivation.pbkdf2_prf = prf.get('Algorithm')
def parse(self, key_deriviation): """Read derivation parameters from a <KeyDerivationMethod> element.""" from pskc.xml import find, findint, findbin if key_deriviation is None: return self.algorithm = key_deriviation.get('Algorithm') # PBKDF2 properties pbkdf2 = find( key_deriviation, 'xenc11:PBKDF2-params', 'pkcs5:PBKDF2-params') if pbkdf2 is not None: # get used salt self.pbkdf2_salt = findbin( pbkdf2, 'Salt/Specified', 'xenc11:Salt/xenc11:Specified') # required number of iterations self.pbkdf2_iterations = findint( pbkdf2, 'IterationCount', 'xenc11:IterationCount') # key length self.pbkdf2_key_length = findint( pbkdf2, 'KeyLength', 'xenc11:KeyLength') # pseudorandom function used prf = find(pbkdf2, 'PRF', 'xenc11:PRF') if prf is not None: self.pbkdf2_prf = prf.get('Algorithm')
def parse(self, value_mac): """Read MAC information from the <ValueMAC> XML tree.""" from pskc.xml import findbin if value_mac is None: return self._value_mac = findbin(value_mac, '.')