Beispiel #1
0
def der2rsa(der):
    # Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
    cert = DerSequence()
    cert.decode(der)
    tbs_certificate = DerSequence()
    tbs_certificate.decode(cert[0])
    subject_public_key_info = tbs_certificate[6]

    # Initialize RSA key
    return RSA.importKey(subject_public_key_info)
def _create_subject_public_key_info(algo_oid, secret_key, params=None):

    if params is None:
        params = DerNull()

    spki = DerSequence([
        DerSequence([DerObjectId(algo_oid), params]),
        DerBitString(secret_key)
    ])
    return spki.encode()
Beispiel #3
0
    def decrypt(data, passphrase):
        """Decrypt a piece of data using a passphrase and *PBES1*.

        The algorithm to use is automatically detected.

        :Parameters:
          data : byte string
            The piece of data to decrypt.
          passphrase : byte string
            The passphrase to use for decrypting the data.
        :Returns:
          The decrypted data, as a binary string.
        """

        enc_private_key_info = DerSequence().decode(data)
        encrypted_algorithm = DerSequence().decode(enc_private_key_info[0])
        encrypted_data = DerOctetString().decode(
            enc_private_key_info[1]).payload

        pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value
        cipher_params = {}
        if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC:
            # PBE_MD5_DES_CBC
            hashmod = MD5
            ciphermod = DES
        elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC:
            # PBE_MD5_RC2_CBC
            hashmod = MD5
            ciphermod = ARC2
            cipher_params['effective_keylen'] = 64
        elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC:
            # PBE_SHA1_DES_CBC
            hashmod = SHA1
            ciphermod = DES
        elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC:
            # PBE_SHA1_RC2_CBC
            hashmod = SHA1
            ciphermod = ARC2
            cipher_params['effective_keylen'] = 64
        else:
            raise PbesError("Unknown OID for PBES1")

        pbe_params = DerSequence().decode(encrypted_algorithm[1],
                                          nr_elements=2)
        salt = DerOctetString().decode(pbe_params[0]).payload
        iterations = pbe_params[1]

        key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod)
        key, iv = key_iv[:8], key_iv[8:]

        cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
        pt = cipher.decrypt(encrypted_data)
        return unpad(pt, cipher.block_size)
Beispiel #4
0
    def test_expected_nr_elements(self):
        der_bin = DerSequence([1, 2, 3]).encode()

        DerSequence().decode(der_bin, nr_elements=3)
        DerSequence().decode(der_bin, nr_elements=(2, 3))
        self.assertRaises(ValueError,
                          DerSequence().decode,
                          der_bin,
                          nr_elements=1)
        self.assertRaises(ValueError,
                          DerSequence().decode,
                          der_bin,
                          nr_elements=(4, 5))
Beispiel #5
0
    def generate_rsa_key_pair():

        rsa_key = RSA.generate(2048)

        private_key = DerSequence([
            0, rsa_key.n, rsa_key.e, rsa_key.d, rsa_key.p, rsa_key.q,
            rsa_key.d % (rsa_key.p - 1), rsa_key.d % (rsa_key.q - 1),
            Integer(rsa_key.q).inverse(rsa_key.p)
        ]).encode()
        pub_key = rsa_key.publickey()
        public_key = DerSequence([pub_key.n, pub_key.e]).encode()

        return private_key, public_key
Beispiel #6
0
def rsa_public_from_der_certificate(certificate):
    # Extract subject_public_key_info field from X.509 certificate (see RFC3280)
    try:
        # try to extract pubkey from scapy.layers.x509 X509Cert type in case
        # der_certificate is of type X509Cert
        # Note: der_certificate may not be of type X509Cert if it wasn't
        # received completely, in that case, we'll try to extract it anyway
        # using the old method.
        # TODO: get rid of the old method and always expect X509Cert obj ?
        """
        Rebuild ASN1 SubjectPublicKeyInfo since X509Cert does not provide the full struct

        ASN1F_SEQUENCE(
                ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"),
                               ASN1F_field("pk_value",ASN1_NULL(0))),
                ASN1F_BIT_STRING("pubkey","")
                ),
        """
        subject_public_key_info = ASN1_SEQUENCE([
            ASN1_SEQUENCE([certificate.pubkey_algo, certificate.pk_value]),
            certificate.pubkey
        ])
        return RSA.importKey(str(subject_public_key_info))
    except AttributeError:
        pass

    # Fallback method, may pot. allow to extract pubkey from incomplete der streams
    cert = DerSequence()
    cert.decode(certificate)

    tbs_certificate = DerSequence()
    tbs_certificate.decode(cert[0])  # first DER SEQUENCE

    # search for pubkey OID: rsaEncryption: "1.2.840.113549.1.1.1"
    # hex: 06 09 2A 86 48 86 F7 0D 01 01 01
    subject_public_key_info = None
    for seq in tbs_certificate:
        if not isinstance(seq, basestring):
            continue  # skip numerics and non sequence stuff
        if "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01" in seq:
            subject_public_key_info = seq

    if subject_public_key_info is None:
        raise ValueError(
            "could not find OID rsaEncryption 1.2.840.113549.1.1.1 in certificate"
        )

    # Initialize RSA key
    return RSA.importKey(subject_public_key_info)
Beispiel #7
0
def get_public_key_from_file(file_name):
    with open(file_name) as f:
        pem = f.read()
    lines = pem.replace(" ", '').split()
    der = a2b_base64(''.join(lines[1:-1]))

    # Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
    cert = DerSequence()
    cert.decode(der)
    tbsCertificate = DerSequence()
    tbsCertificate.decode(cert[0])
    subjectPublicKeyInfo = tbsCertificate[6]

    # Initialize RSA key
    publicKey = RSA.importKey(subjectPublicKeyInfo)
    return publicKey.publickey()
Beispiel #8
0
    def write_signature_value(self, wire, contents) -> int:
        cng = Cng()
        hash_val, cb_hash = self._hash_contents(contents)

        cb_signature = c.c_ulong()
        status = cng.ncrypt.NCryptSignHash(self.h_key, 0, hash_val, cb_hash, 0,
                                           0, c.pointer(cb_signature), 0)
        if not cng.nt_success(status):
            raise OSError(f'Error {status} returned by NCryptSignHash')

        signature = (c.c_ubyte * cb_signature.value)()
        status = cng.ncrypt.NCryptSignHash(self.h_key, 0, hash_val, cb_hash,
                                           signature, cb_signature,
                                           c.pointer(cb_signature), 0)
        if not cng.nt_success(status):
            raise OSError(f'Error {status} returned by NCryptSignHash')

        if self.key_type == SignatureType.SHA256_WITH_ECDSA:
            der = DerSequence(
                (int.from_bytes(signature[:cb_signature.value // 2], 'big'),
                 int.from_bytes(signature[cb_signature.value // 2:],
                                'big'))).encode()
        else:
            der = bytes(signature)

        real_len = len(der)
        wire[:real_len] = der
        return real_len
Beispiel #9
0
 def testEncode7(self):
     # One integer and another type (already encoded)
     der = DerSequence()
     der.append(0x180)
     der.append(b('0\x03\x02\x01\x05'))
     self.assertEquals(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05'))
     self.failIf(der.hasOnlyInts())
Beispiel #10
0
    def _export_private_der(self, include_ec_params=True):

        assert self.has_private()

        # ECPrivateKey ::= SEQUENCE {
        #           version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
        #           privateKey     OCTET STRING,
        #           parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
        #           publicKey  [1] BIT STRING OPTIONAL
        #    }

        # Public key - uncompressed form
        order_bytes = _curve.order.size_in_bytes()
        public_key = (b'\x04' + self.pointQ.x.to_bytes(order_bytes) +
                      self.pointQ.y.to_bytes(order_bytes))

        seq = [
            1,
            DerOctetString(self.d.to_bytes(order_bytes)),
            DerObjectId(_curve.oid, explicit=0),
            DerBitString(public_key, explicit=1)
        ]

        if not include_ec_params:
            del seq[2]

        return DerSequence(seq).encode()
Beispiel #11
0
 def testEncode4(self):
     # One very long integer
     der = DerSequence()
     der.append(2**2048)
     self.assertEquals(
         der.encode(),
         b('0\x82\x01\x05') +
         b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
Beispiel #12
0
 def testDecode6(self):
     # Two integers
     der = DerSequence()
     der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
     self.assertEquals(len(der), 2)
     self.assertEquals(der[0], 0x180)
     self.assertEquals(der[1], 0xFF)
Beispiel #13
0
def _import_pkcs1_public(encoded, *kwargs):
    # RSAPublicKey ::= SEQUENCE {
    #           modulus INTEGER, -- n
    #           publicExponent INTEGER -- e
    # }
    der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True)
    return construct(der)
Beispiel #14
0
 def testDecode4(self):
     # One very long integer
     der = DerSequence()
     der.decode(
         b('0\x82\x01\x05') +
         b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
     self.assertEquals(len(der), 1)
     self.assertEquals(der[0], 2**2048)
Beispiel #15
0
def _import_openssl_private(encoded, passphrase, params):
    if params:
        raise ValueError("DSA private key already comes with parameters")
    der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True)
    if der[0] != 0:
        raise ValueError("No version found")
    tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
    return construct(tup)
Beispiel #16
0
 def testDecode7(self):
     # One integer and 2 other types
     der = DerSequence()
     der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00'))
     self.assertEquals(len(der), 3)
     self.assertEquals(der[0], 0x180)
     self.assertEquals(der[1], b('\x24\x02\xb6\x63'))
     self.assertEquals(der[2], b('\x12\x00'))
Beispiel #17
0
 def testErrDecode3(self):
     # Wrong length format
     der = DerSequence()
     # Missing length in sub-item
     self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00'))
     # Valid BER, but invalid DER length
     self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01'))
     self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01'))
Beispiel #18
0
def import_key(extern_key, salt=None):
    der, marker, _ = PEM.decode(extern_key)
    ints = DerSequence().decode(der)

    if not marker.startswith('myDSA'):
        raise ValueError('Invalid format')

    key_dict = dict(zip(('p', 'q', 'g', 'y', 'x'), map(Integer, ints)))
    return myDSA(key_dict, salt)
Beispiel #19
0
def _extract_subject_public_key_info(x509_certificate):
    """Extract subjectPublicKeyInfo from a DER X.509 certificate."""

    certificate = DerSequence().decode(x509_certificate, nr_elements=3)
    tbs_certificate = DerSequence().decode(certificate[0],
                                           nr_elements=list(range(6, 11)))

    index = 5
    try:
        tbs_certificate[0] + 1
        # Version not present
        version = 1
    except TypeError:
        version = DerInteger(explicit=0).decode(tbs_certificate[0]).value
        if version not in (2, 3):
            raise ValueError("Incorrect X.509 certificate version")
        index = 6

    return tbs_certificate[index]
Beispiel #20
0
def _import_pkcs8(encoded, passphrase, params):
    if params:
        raise ValueError("PKCS#8 already includes parameters")
    k = PKCS8.unwrap(encoded, passphrase)
    if k[0] != oid:
        raise ValueError("No PKCS#8 encoded DSA key")
    x = DerInteger().decode(k[1]).value
    p, q, g = list(DerSequence().decode(k[2]))
    tup = (pow(g, x, p), g, p, q, x)
    return construct(tup)
Beispiel #21
0
    def test_expected_only_integers(self):

        der_bin1 = DerSequence([1, 2, 3]).encode()
        der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode()

        DerSequence().decode(der_bin1, only_ints_expected=True)
        DerSequence().decode(der_bin1, only_ints_expected=False)
        DerSequence().decode(der_bin2, only_ints_expected=False)
        self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True)
Beispiel #22
0
 def testDecode8(self):
     # Only 2 other types
     der = DerSequence()
     der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))
     self.assertEquals(len(der), 2)
     self.assertEquals(der[0], b('\x24\x02\xb6\x63'))
     self.assertEquals(der[1], b('\x12\x00'))
     self.assertEquals(der.hasInts(), 0)
     self.assertEquals(der.hasInts(False), 0)
     self.failIf(der.hasOnlyInts())
     self.failIf(der.hasOnlyInts(False))
Beispiel #23
0
def _import_subjectPublicKeyInfo(encoded, passphrase, params):

    algoid, encoded_key, emb_params =  _expand_subject_public_key_info(encoded)
    if algoid != oid:
        raise ValueError("No DSA subjectPublicKeyInfo")
    if params and emb_params:
        raise ValueError("Too many DSA parameters")

    y = DerInteger().decode(encoded_key).value
    p, q, g = list(DerSequence().decode(params or emb_params))
    tup = (y, g, p, q)
    return construct(tup)
Beispiel #24
0
    def verify(self, msg_hash, signature):
        """Verify that a certain DSS signature is authentic.

        This function checks if the party holding the private half of the key
        really signed the message.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message.
            This is an object belonging to the `Cryptodome.Hash` module.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used in
            combination with SHA-512.

          signature : byte string
            The signature that needs to be validated.

        :Raise ValueError:
            If the signature is not authentic.
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash does not belong to SHS")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [
                Integer.from_bytes(x) for x in (signature[:self._order_bytes],
                                                signature[self._order_bytes:])
            ]
        else:
            try:
                der_seq = DerSequence().decode(signature)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError(
                    "The signature is not authentic (DER content)")
            r_prime, s_prime = der_seq[0], der_seq[1]

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Beispiel #25
0
 def test_verify(self):
     # Ecdsa signature is not unique, so we only test if we can verify it
     pri_key = ECC.generate(curve="P-256")
     key = pri_key.export_key(format="DER")
     pub_key = pri_key.public_key()
     signer = Sha256WithEcdsaSigner("/K/KEY/x", key)
     pkt = make_data("/test", MetaInfo(), b"test content", signer=signer)
     _, _, _, sig_ptrs = parse_data(pkt)
     # Test its format is ASN.1 der format
     DerSequence().decode(bytes(sig_ptrs.signature_value_buf))
     validator = EccChecker.from_key(
         "/K/KEY/x", bytes(pub_key.export_key(format='DER')))
     assert aio.run(validator(Name.from_str("/test"), sig_ptrs))
Beispiel #26
0
 def testDecode1(self):
     # Empty sequence
     der = DerSequence()
     der.decode(b('0\x00'))
     self.assertEquals(len(der), 0)
     # One single-byte integer (zero)
     der.decode(b('0\x03\x02\x01\x00'))
     self.assertEquals(len(der), 1)
     self.assertEquals(der[0], 0)
     # Invariant
     der.decode(b('0\x03\x02\x01\x00'))
     self.assertEquals(len(der), 1)
     self.assertEquals(der[0], 0)
Beispiel #27
0
    def verify(self, msg_hash, signature):
        """Check if a certain (EC)DSA signature is authentic.

        :parameter msg_hash:
            The hash that was carried out over the message.
            This is an object belonging to the :mod:`Cryptodome.Hash` module.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used in
            combination with SHA-512.
        :type msg_hash: hash object

        :parameter signature:
            The signature that needs to be validated
        :type signature: byte string

        :raise ValueError: if the signature is not authentic
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [
                Integer.from_bytes(x) for x in (signature[:self._order_bytes],
                                                signature[self._order_bytes:])
            ]
        else:
            try:
                der_seq = DerSequence().decode(signature, strict=True)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError(
                    "The signature is not authentic (DER content)")
            r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1])

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Beispiel #28
0
 def testEncode2(self):
     # Indexing
     der = DerSequence()
     der.append(0)
     der[0] = 1
     self.assertEquals(len(der), 1)
     self.assertEquals(der[0], 1)
     self.assertEquals(der[-1], 1)
     self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
     #
     der[:] = [1]
     self.assertEquals(len(der), 1)
     self.assertEquals(der[0], 1)
     self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
Beispiel #29
0
 def testEncode1(self):
     # Empty sequence
     der = DerSequence()
     self.assertEquals(der.encode(), b('0\x00'))
     self.failIf(der.hasOnlyInts())
     # One single-byte integer (zero)
     der.append(0)
     self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
     self.assertEquals(der.hasInts(), 1)
     self.assertEquals(der.hasInts(False), 1)
     self.failUnless(der.hasOnlyInts())
     self.failUnless(der.hasOnlyInts(False))
     # Invariant
     self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
Beispiel #30
0
def rsa_public_from_der_certificate(certificate):
    # Extract subject_public_key_info field from X.509 certificate (see RFC3280)
    try:
        # try to extract pubkey from scapy.layers.x509 X509Cert type in case
        # der_certificate is of type X509Cert
        # Note: der_certificate may not be of type X509Cert if it wasn't
        # received completely, in that case, we'll try to extract it anyway
        # using the old method.
        # TODO: get rid of the old method and always expect X509Cert obj ?
        return RSA.importKey(
            str(certificate.tbsCertificate.subjectPublicKeyInfo))
    except AttributeError:
        pass

    # Fallback method, may pot. allow to extract pubkey from incomplete der streams
    cert = DerSequence()
    cert.decode(certificate)

    tbs_certificate = DerSequence()
    tbs_certificate.decode(cert[0])  # first DER SEQUENCE

    # search for pubkey OID: rsaEncryption: "1.2.840.113549.1.1.1"
    # hex: 06 09 2A 86 48 86 F7 0D 01 01 01
    subject_public_key_info = None
    for seq in tbs_certificate:
        if not isinstance(seq, bytes) and not isinstance(seq, str):
            continue  # skip numerics and non sequence stuff
        if b"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01" in seq:
            subject_public_key_info = seq

    if subject_public_key_info is None:
        raise ValueError(
            "could not find OID rsaEncryption 1.2.840.113549.1.1.1 in certificate"
        )

    # Initialize RSA key
    return RSA.importKey(subject_public_key_info)