Example #1
0
def get_service_id(private_key_file=None, cert=None):
    '''
    service_id is the first half of the sha1 of the rsa public key encoded in base32
    '''
    if private_key_file:
        with open(private_key_file, 'rb') as fd:
            private_key = fd.read()
        public_key = RSA.importKey(private_key).publickey().exportKey('DER')[22:]
        # compute sha1 of public key and encode first half in base32
        service_id = base64.b32encode(hashlib.sha1(public_key).digest()[:10]).lower().decode()
        '''
        # compute public key from priate key and export in DER format
        # ignoring the SPKI header(22 bytes)
        key = load_privatekey(FILETYPE_PEM, private_key)
        cert = X509()
        cert.set_pubkey(key)
        public_key = dump_privatekey(FILETYPE_ASN1, cert.get_pubkey())[22:]
        # compute sha1 of public key and encode first half in base32
        service_id = base64.b32encode(hashlib.sha1(public_key).digest()[:10]).lower().decode()
        '''
    elif cert:
        # compute sha1 of public key and encode first half in base32
        key = load_certificate(FILETYPE_ASN1, cert).get_pubkey()
        pub_der = DerSequence()
        pub_der.decode(dump_privatekey(FILETYPE_ASN1, key))
        public_key = RSA.construct((pub_der._seq[1], pub_der._seq[2])).exportKey('DER')[22:]
        service_id = base64.b32encode(hashlib.sha1(public_key).digest()[:10]).lower().decode()
    return service_id
Example #2
0
	def testDecode8(self):
		# Only 2 other types
		der = DerSequence()
		der.decode('0\x06\x24\x02\xb6\x63\x12\x00')
		self.assertEquals(len(der),2)
		self.assertEquals(der[0],'\x24\x02\xb6\x63')
		self.assertEquals(der[1],'\x12\x00')
Example #3
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"),
     )
Example #4
0
	def testDecode4(self):
		# One very long integer
		der = DerSequence()
		der.decode('0\x82\x01\x05'
		'\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
		'\x00\x00\x00\x00\x00\x00\x00\x00\x00')
		self.assertEquals(len(der),1)
		self.assertEquals(der[0],2**2048)
Example #5
0
	def testDecode6(self):
		# Two integers
		der = DerSequence()
		der.decode('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')
		self.assertEquals(len(der),2)
		self.assertEquals(der[0],0x180L)
		self.assertEquals(der[1],0xFFL)
Example #6
0
	def testDecode7(self):
		# One integer and 2 other types
		der = DerSequence()
		der.decode('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')
		self.assertEquals(len(der),3)
		self.assertEquals(der[0],0x180L)
		self.assertEquals(der[1],'\x24\x02\xb6\x63')
		self.assertEquals(der[2],'\x12\x00')
Example #7
0
def get_service_id(key):
    '''
    service_id is the first half of the sha1 of the rsa public key encoded in base32
    '''
    # compute sha1 of public key and encode first half in base32
    pub_der = DerSequence()
    pub_der.decode(dump_privatekey(FILETYPE_ASN1, key))
    public_key = RSA.construct((pub_der._seq[1], pub_der._seq[2])).exportKey('DER')[22:]
    service_id = base64.b32encode(hashlib.sha1(public_key).digest()[:10]).lower().decode()
    return service_id
Example #8
0
File: RSA.py Project: 4ZM/pycrypto
    def exportKey(self, format='PEM'):
        """Export the RSA key. A string is returned
        with the encoded public or the private half
        under the selected format.

        format:		'DER' (PKCS#1) or 'PEM' (RFC1421)
        """
        der = DerSequence()
        if self.has_private():
            keyType = "RSA PRIVATE"
            der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
                   self.d % (self.p-1), self.d % (self.q-1),
                   self.u ]
        else:
            keyType = "PUBLIC"
            der.append(b('\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00'))
            bitmap = DerObject('BIT STRING')
            derPK = DerSequence()
            derPK[:] = [ self.n, self.e ]
            bitmap.payload = b('\x00') + derPK.encode()
            der.append(bitmap.encode())
        if format=='DER':
            return der.encode()
        if format=='PEM':
            pem = b("-----BEGIN %s KEY-----\n" % keyType)
            binaryKey = der.encode()
            # Each BASE64 line can take up to 64 characters (=48 bytes of data)
            chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
            pem += b('').join(chunks)
            pem += b("-----END %s KEY-----" % keyType)
            return pem
        return ValueError("")
Example #9
0
	def exportKey(self, format='PEM', public=False, type=None):
		"""Export the RSA key. A string is returned
		with the encoded public or the private half
		under the selected format.
		format: 'DER' (PKCS#1) or 'PEM' (RFC1421)
		"""
		if type == 'ssh-rsa' and public:
			return ''.join(binascii.b2a_base64('\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x03' + '\x00\x00\x01\x01\x00'.join([long_to_bytes(self.e), long_to_bytes(self.n)])).split("\n"))
		
		der = DerSequence()
		if not public and self.has_private():
			keyType = "RSA PRIVATE"
			der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
				   self.d % (self.p-1), self.d % (self.q-1),
				   self.u ]
		else:
			keyType = "PUBLIC"
			der.append('\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00')
			bitmap = DerObject('BIT STRING')
			derPK = DerSequence()
			derPK[:] = [ self.n, self.e ]
			bitmap.payload = '\x00' + derPK.encode()
			der.append(bitmap.encode())
		if format=='DER':
			return der.encode()
		if format=='PEM':
			pem = "-----BEGIN %s KEY-----\n" % keyType
			binaryKey = der.encode()
			# Each BASE64 line can take up to 64 characters (=48 bytes of data)
			chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
			pem += ''.join(chunks)
			pem += "-----END %s KEY-----" % keyType
			return pem
		return ValueError("")
Example #10
0
 def _importKeyDER(self, externKey):
     der = DerSequence()
     der.decode(externKey, True)
     if len(der)==9 and der.hasOnlyInts() and der[0]==0:
         # ASN.1 RSAPrivateKey element
         del der[6:]	# Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
         der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
         del der[0]	# Remove version
         return self.construct(der[:])
     if len(der)==2:
         # The DER object is a SEQUENCE with two elements:
         # a SubjectPublicKeyInfo SEQUENCE and an opaque BIT STRING.
         #
         # The first element is always the same:
         # 0x30 0x0D     SEQUENCE, 12 bytes of payload
         #   0x06 0x09   OBJECT IDENTIFIER, 9 bytes of payload
         #     0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
         #               rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
         #   0x05 0x00   NULL
         #
         # The second encapsulates the actual ASN.1 RSAPublicKey element.
         if der[0]==b('\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00'):
             bitmap = DerObject()
             bitmap.decode(der[1], True)
             if bitmap.typeTag==b('\x03')[0] and bitmap.payload[0]==b('\x00')[0]:
                 der.decode(bitmap.payload[1:], True)
                 if len(der)==2 and der.hasOnlyInts():
                     return self.construct(der[:])
     raise ValueError("RSA key format is not supported")
Example #11
0
def get_pubkey_ssh2_fingerprint(pubkey):
    # This is the format that EC2 shows for public key fingerprints in its
    # KeyPair mgmt API
    if not pycrypto_available:
        raise RuntimeError('pycrypto is not available')
    k = importKey(pubkey)
    derPK = DerSequence([k.n, k.e])
    bitmap = DerObject('BIT STRING')
    bitmap.payload = bchr(0x00) + derPK.encode()
    der = DerSequence([algorithmIdentifier, bitmap.encode()])
    return _to_md5_fingerprint(der.encode())
Example #12
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 `Crypto.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).

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

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

        if not self._deterministic:
            if self._n > msg_hash.digest_size * 8:
                raise ValueError("Hash is not long enough")

            if not hash_is_shs(msg_hash):
                raise ValueError("Hash does not belong to SHS")

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

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

        z = bytes_to_long(msg_hash.digest()[:self._n])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCrypto code to fail
        return False
Example #13
0
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()
Example #14
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 `Crypto.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 PyCrypto code to fail
        return False
Example #15
0
    def exportKey(self, format="PEM"):
        """Export the RSA key. A string is returned
        with the encoded public or the private half
        under the selected format.

        format:		'DER' (PKCS#1) or 'PEM' (RFC1421)
        """
        der = DerSequence()
        if self.has_private():
            keyType = "RSA PRIVATE"
            der[:] = [0, self.n, self.e, self.d, self.p, self.q, self.d % (self.p - 1), self.d % (self.q - 1), self.u]
        else:
            keyType = "PUBLIC"
            der.append("\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00")
            bitmap = DerObject("BIT STRING")
            derPK = DerSequence()
            derPK[:] = [self.n, self.e]
            bitmap.payload = "\x00" + derPK.encode()
            der.append(bitmap.encode())
        if format == "DER":
            return der.encode()
        if format == "PEM":
            pem = "-----BEGIN %s KEY-----\n" % keyType
            binaryKey = der.encode()
            # Each BASE64 line can take up to 64 characters (=48 bytes of data)
            chunks = []
            for i in range(0, len(binaryKey), 48):
                chunks.append(binascii.b2a_base64(binaryKey[i : i + 48]))
            pem += "".join(chunks)
            pem += "-----END %s KEY-----" % keyType
            return pem
        if format == "SSH":
            # Create public key.
            ssh_rsa = "00000007" + base64.b16encode("ssh-rsa")

            # Exponent.
            exponent = "%x" % (self.key.e,)
            if len(exponent) % 2:
                exponent = "0" + exponent

            ssh_rsa += "%08x" % (len(exponent) / 2,)
            ssh_rsa += exponent

            modulus = "%x" % (self.key.n,)
            if len(modulus) % 2:
                modulus = "0" + modulus

            if modulus[0] in "89abcdef":
                modulus = "00" + modulus

            ssh_rsa += "%08x" % (len(modulus) / 2,)
            ssh_rsa += modulus

            return "ssh-rsa %s" % (base64.b64encode(base64.b16decode(ssh_rsa.upper())),)

        return ValueError("")
Example #16
0
	def testEncode6(self):
		# Two integers
		der = DerSequence()
		der.append(0x180L)
		der.append(0xFFL)
		self.assertEquals(der.encode(), '0\x08\x02\x02\x01\x80\x02\x02\x00\xff')
		self.failUnless(der.hasOnlyInts())
		#
		der.append(0x01)
		der[1:] = [9,8]
		self.assertEquals(len(der),3)
		self.assertEqual(der[1:],[9,8])
		self.assertEqual(der[1:-1],[9])
		self.assertEquals(der.encode(), '0\x0A\x02\x02\x01\x80\x02\x01\x09\x02\x01\x08')
Example #17
0
 def testEncode2(self):
     # Indexing
     der = DerSequence()
     der.append(0)
     der[0] = 1
     self.assertEqual(len(der),1)
     self.assertEqual(der[0],1)
     self.assertEqual(der[-1],1)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x01'))
     #
     der[:] = [1]
     self.assertEqual(len(der),1)
     self.assertEqual(der[0],1)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x01'))
Example #18
0
    def sign(self, msg_hash):
        """Produce the DSS signature of a message.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message.
            The object belongs to the `Crypto.Hash` package.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family).

        :Return: The signature encoded as a byte string.
        :Raise ValueError:
            If the hash algorithm is incompatible to the DSA key.
        :Raise TypeError:
            If the DSA key has no private half.
        """

        # Generate the nonce k (critical!)
        if self._deterministic:
            nonce = self._compute_nonce(msg_hash)
        else:
            if self._n > msg_hash.digest_size * 8:
                raise ValueError("Hash is not long enough")

            if not hash_is_shs(msg_hash):
                raise ValueError("Hash does not belong to SHS")

            rng = StrongRandom(randfunc=self._randfunc)
            nonce = rng.randint(1, self._key.q - 1)

        # Perform signature using the raw API
        z = bytes_to_long(msg_hash.digest()[:self._n])
        sig_pair = self._key._sign(z, nonce)

        # Encode the signature into a single byte string
        if self._encoding == 'binary':
            output = b("").join([long_to_bytes(x, self._n)
                                 for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #               r       OCTET STRING,
            #               s       OCTET STRING
            # }
            der_seq = DerSequence(sig_pair)
            output = der_seq.encode()

        return output
Example #19
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:`Crypto.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 PyCrypto code to fail
        return False
Example #20
0
 def testEncode7(self):
     # One integer and another type (no matter what it is)
     der = DerSequence()
     der.append(0x180)
     der.append(b('\x00\x02\x00\x00'))
     self.assertEqual(der.encode(), b('0\x08\x02\x02\x01\x80\x00\x02\x00\x00'))
     self.assertFalse(der.hasOnlyInts())
Example #21
0
def _importKeyDER(extern_key, passphrase, verify_x509_cert):
    """Import an RSA key (public or private half), encoded in DER form."""

    try:

        der = DerSequence().decode(extern_key)

        # Try PKCS#1 first, for a private key
        if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
            # ASN.1 RSAPrivateKey element
            del der[6:]     # Remove d mod (p-1),
                            # d mod (q-1), and
                            # q^{-1} mod p
            der.append(Integer(der[4]).inverse(der[5]))  # Add p^{-1} mod q
            del der[0]      # Remove version
            return construct(der[:])

        # Keep on trying PKCS#1, but now for a public key
        if len(der) == 2:
            try:
                # The DER object is an RSAPublicKey SEQUENCE with
                # two elements
                if der.hasOnlyInts():
                    return construct(der[:])
                # The DER object is a SubjectPublicKeyInfo SEQUENCE
                # with two elements: an 'algorithmIdentifier' and a
                # 'subjectPublicKey'BIT STRING.
                # 'algorithmIdentifier' takes the value given at the
                # module level.
                # 'subjectPublicKey' encapsulates the actual ASN.1
                # RSAPublicKey element.
                if der[0] == algorithmIdentifier:
                    bitmap = DerBitString().decode(der[1])
                    rsaPub = DerSequence().decode(bitmap.value)
                    if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
                        return construct(rsaPub[:])
            except (ValueError, EOFError):
                pass

        # Try to see if this is an X.509 DER certificate
        # (Certificate ASN.1 type)
        if len(der) == 3:
            from Crypto.PublicKey import _extract_sp_info
            try:
                sp_info = _extract_sp_info(der)
                if verify_x509_cert:
                    raise NotImplementedError("X.509 certificate validation is not supported")
                return _importKeyDER(sp_info, passphrase, False)
            except ValueError:
                pass

        # Try PKCS#8 (possibly encrypted)
        k = PKCS8.unwrap(extern_key, passphrase)
        if k[0] == oid:
            return _importKeyDER(k[1], passphrase, False)

    except (ValueError, EOFError):
        pass

    raise ValueError("RSA key format is not supported")
Example #22
0
 def testEncode8(self):
     # One integer and another type (yet to encode)
     der = DerSequence()
     der.append(0x180)
     der.append(DerSequence([5]))
     self.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05'))
     self.assertFalse(der.hasOnlyInts())
Example #23
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.assertEqual(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05'))
     self.assertFalse(der.hasOnlyInts())
Example #24
0
def _extract_sp_info(x509_certificate):
    """Extract subjectPublicKeyInfo from a DER X.509 certificate."""

    from Crypto.Util.asn1 import DerSequence, DerInteger

    try:
        # This code will partially parse tbsCertificate
        # to get to subjectPublicKeyInfo.
        #
        # However, the first 2 elements of tbsCertificate are:
        #
        #   version [0]  Version DEFAULT v1,
        #   serialNumber         CertificateSerialNumber,
        #
        # where:
        #
        #   Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
        #   CertificateSerialNumber  ::=  INTEGER
        #
        # In order to know the position of subjectPublicKeyInfo
        # in the tbsCertificate SEQUENCE, we try to see if the
        # first element is an untagged INTEGER (that is, the
        # certificate serial number).

        x509_tbs_cert = DerSequence()
        x509_tbs_cert.decode(x509_certificate[0])

        index = -1  # Sentinel
        try:
            _ = x509_tbs_cert[0] + 1
            # Still here? There was no version then
            index = 5
        except TypeError:
            # Landed here? Version was there
            x509_version = DerInteger(explicit=0)
            x509_version.decode(x509_tbs_cert[0])
            index = 6

        if index in (5, 6):
            return x509_tbs_cert[index]

    except (TypeError, IndexError, ValueError, EOFError):
        pass

    raise ValueError("Cannot extract subjectPublicKeyInfo")
Example #25
0
	def testEncode6(self):
		# One integer and another type (no matter what it is)
		der = DerSequence()
		der.append(0x180L)
		der.append('\x00\x02\x00\x00')
		self.assertEquals(der.encode(), '0\x08\x02\x02\x01\x80\x00\x02\x00\x00')
		self.failIf(der.hasOnlyInts())
Example #26
0
	def testEncode1(self):
		# Empty sequence
		der = DerSequence()
		self.assertEqual(der.encode(), b('0\x00'))
		self.assertFalse(der.hasOnlyInts())
		# One single-byte integer (zero)
		der.append(0)
		self.assertEqual(der.encode(), b('0\x03\x02\x01\x00'))
		self.assertTrue(der.hasOnlyInts())
		# Invariant
		self.assertEqual(der.encode(), b('0\x03\x02\x01\x00'))
Example #27
0
	def testEncode1(self):
		# Empty sequence
		der = DerSequence()
		self.assertEquals(der.encode(), '0\x00')
		self.failIf(der.hasOnlyInts())
		# One single-byte integer (zero)
		der.append(0)
		self.assertEquals(der.encode(), '0\x03\x02\x01\x00')
		self.failUnless(der.hasOnlyInts())
		# Invariant
		self.assertEquals(der.encode(), '0\x03\x02\x01\x00')
Example #28
0
  def get_cert_moduli(self, derCert):
    # convert PEM to DER
    pem = derCert.decode()
    lines = pem.replace(" ",'').split()
    der = binascii.a2b_base64(''.join(lines[1:-1]))

    # get Subject Public Key
    cert = DerSequence()
    b = cert.decode(der)
    tbsCertificate = DerSequence()
    tbsCertificate.decode(cert[0])
    try:
      subjectPublicKeyInfo = tbsCertificate[6]
    except IndexError:
      return "unkown", "unkown"

    rsa_key = RSA.importKey(subjectPublicKeyInfo)
    # rsa_key.n = modulus, rsa_key.e = public exponent
    # increment size with 1 as the Python counts from 0 (duh)
    return (hex(rsa_key.n), rsa_key.key.size() + 1)
Example #29
0
 def get_spki(self):
     """Get the Subject PublicKey info, DER encoded."""
     der = DerSequence()
     der.decode(self.DER)
     cert = DerSequence()
     cert.decode(der[0])
     return cert[6]
Example #30
0
def forge(certificate_path: str, key_pem: str):
    """
    given a valid certificate_path and key_pem create a forged key
    """
    public_key_point = get_public_key(certificate_path)
    Q = Point(int(public_key_point[0:96], 16),
              int(public_key_point[96:], 16),
              curve=P384)

    # Generate rogue generator
    privkey_inv = 2
    # we take the private key as being the inverse of 2 modulo the curve order
    private_key = gmpy2.invert(privkey_inv, P384.q)  # pylint: disable=c-extension-no-member
    private_key = unhexlify(f"{private_key:x}".encode())
    # we multply our public key Q with the inverse of our chosen private key value
    roug_g = privkey_inv * Q
    roug_g = unhexlify(b"04" + f"{roug_g.x:x}".encode() +
                       f"{roug_g.y:x}".encode())

    # Generate the file with explicit parameters
    with open(key_pem, mode="rt") as handle:
        keyfile = PEM.decode(handle.read())

    seq_der = DerSequence()
    der = seq_der.decode(keyfile[0])

    # Replace private key
    octet_der = DerOctetString(private_key)
    der[1] = octet_der.encode()

    # Replace public key
    bits_der = DerBitString(unhexlify(b"04" + public_key_point))
    der[3] = b"\xa1\x64" + bits_der.encode()

    # Replace the generator
    seq_der = DerSequence()
    s = seq_der.decode(der[2][4:])  # pylint: disable=invalid-name
    octet_der = DerOctetString(roug_g)
    s[3] = octet_der.encode()
    der[2] = der[2][:4] + s.encode()

    return PEM.encode(der.encode(), "EC PRIVATE KEY")
Example #31
0
        def CRYPTO_EMSA_PKCS1_V1_5_ENCODE(M, emLen):
            msg_hash = SHA256.new(M)
            digestAlgo = DerSequence([DerObjectId(msg_hash.oid).encode()])
            print(digestAlgo)

            digestAlgo.append(DerNull().encode())

            digest = DerOctetString(msg_hash.digest())
            digestInfo = DerSequence([digestAlgo.encode(),
                                      digest.encode()]).encode()
            print("%x" % int.from_bytes(digestInfo, byteorder='big'))
            print("%x" % int.from_bytes(digestAlgo.encode(), byteorder='big'))
            print("%x" % int.from_bytes(digest.encode(), byteorder='big'))
            print("%x" % int.from_bytes(msg_hash.digest(), byteorder='big'))

            #b91d0b7a09f57c109926a449647283adb5dc213c0fdb0cf2b219e064cc132273 2004 00 0501020403650148866009060d30 3130
            #                                                                          501020403650148866009060d30
            #b91d0b7a09f57c109926a449647283adb5dc213c0fdb0cf2b219e064cc132273 2004
            #b91d0b7a09f57c109926a449647283adb5dc213c0fdb0cf2b219e064cc132273
            #b91d0b7a09f57c109926a449647283adb5dc213c0fdb0cf2b219e064cc1322732004000501020403650148866009060d30313000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0100

            #3031 300d06096086480165030402010500 0420 732213cc64e019b2f20cdb0f3c21dcb5ad83726449a42699107cf5097a0b1db9
            #     300d06096086480165030402010500
            #                                    0420 732213cc64e019b2f20cdb0f3c21dcb5ad83726449a42699107cf5097a0b1db9
            #                                         732213cc64e019b2f20cdb0f3c21dcb5ad83726449a42699107cf5097a0b1db9
            #0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420732213cc64e019b2f20cdb0f3c21dcb5ad83726449a42699107cf5097a0b1db9

            # We need at least 11 bytes for the remaining data: 3 fixed bytes and
            # at least 8 bytes of padding).
            if emLen < len(digestInfo) + 11:
                raise TypeError(
                    "Selected hash algorith has a too long digest (%d bytes)."
                    % len(digest))
            PS = b'\xFF' * (emLen - len(digestInfo) - 3)
            out = b'\x00\x01' + PS + b'\x00' + digestInfo
            print("%x" % int.from_bytes(out, byteorder='big'))
            return out
Example #32
0
def generatePublicKey(cert_file):
    osw = OpenSSLWrapper()
    cert_str = osw.read_str_from_file(cert_file)
    cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_str)
    pub_key = cert.get_pubkey()
    src = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pub_key)
    pub_der = DerSequence()
    pub_der.decode(src)
    pub_key_rsa = RSA.construct((long(pub_der._seq[1]), long(pub_der._seq[2])))
    pemSeq = DerSequence()
    pemSeq[:] = [pub_key_rsa.key.n, pub_key_rsa.key.e]
    s = pub_key_str = b64encode(pemSeq.encode())
    pem_src = '-----BEGIN RSA PUBLIC KEY-----\n'
    while True:
        pem_src += s[:64] + '\n'
        s = s[64:]
        if s == '':
            break
    pem_src += '-----END RSA PUBLIC KEY-----'

    jwks = {
        "keys": [{
            "use": "enc",
            "e": "AQAB",
            "kty": "RSA",
            "n": pub_key_str
        }, {
            "use": "sig",
            "e": "AQAB",
            "kty": "RSA",
            "n": pub_key_str
        }]
    }

    jwks_str = json.dumps(jwks)
    osw.write_str_to_file("./static/jwks.json", jwks_str)
Example #33
0
def pkcs1_v1_5_encode(msg_hash: SHA256.SHA256Hash, emLen: int) -> bytes:
    # this code is copied from  EMSA_PKCS1_V1_5_ENCODE
    # https://github.com/dlitz/pycrypto/blob/v2.7a1/lib/Crypto/Signature/PKCS1_v1_5.py#L173
    digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ])

    #if with_hash_parameters:
    if True:
        digestAlgo.append(DerNull().encode())

    digest      = DerOctetString(msg_hash.digest())
    digestInfo  = DerSequence([
                    digestAlgo.encode(),
                      digest.encode()
                    ]).encode()

    # We need at least 11 bytes for the remaining data: 3 fixed bytes and
    # at least 8 bytes of padding).
    if emLen<len(digestInfo)+11:
          raise TypeError("Selected hash algorith has a too long digest (%d bytes)." % len(digest))
    PS = b'\xFF' * (emLen - len(digestInfo) - 3)
    return b'\x00\x01' + PS + b'\x00' + digestInfo
Example #34
0
 def testInit1(self):
     der = DerSequence([1, DerInteger(2), b('0\x00')])
     self.assertEquals(der.encode(),
                       b('0\x08\x02\x01\x01\x02\x01\x020\x00'))
Example #35
0
	def testEncode5(self):
		# One single-byte integer (looks negative)
		der = DerSequence()
		der.append(0xFFL)
		self.assertEquals(der.encode(), '0\x04\x02\x02\x00\xff')
Example #36
0
	def testEncode3(self):
		# One multi-byte integer (non-zero)
		der = DerSequence()
		der.append(0x180L)
		self.assertEquals(der.encode(), '0\x04\x02\x02\x01\x80')
Example #37
0
        except ValueError:
            error_str = "PBES1[Invalid]"

        if not found:
            try:
                p8_private_key = PBES2.decrypt(p8_private_key, passphrase)
                found = True
            except PbesError, e:
                error_str += ",PBES2[%s]" % str(e)
            except ValueError:
                error_str += ",PBES2[Invalid]"

        if not found:
            raise ValueError("Error decoding PKCS#8 (%s)" % error_str)

    pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4))
    if len(pk_info) == 2 and not passphrase:
        raise ValueError("Not a valid clear PKCS#8 structure "
                         "(maybe it is encrypted?)")

    #
    #   PrivateKeyInfo ::= SEQUENCE {
    #       version                 Version,
    #       privateKeyAlgorithm     PrivateKeyAlgorithmIdentifier,
    #       privateKey              PrivateKey,
    #       attributes              [0]  IMPLICIT Attributes OPTIONAL
    #   }
    #   Version ::= INTEGER
    if pk_info[0] != 0:
        raise ValueError("Not a valid PrivateKeyInfo SEQUENCE")
Example #38
0
 def testEncode6(self):
     # Two positive integers
     der = DerSequence()
     der.append(0x180L)
     der.append(0xFFL)
     self.assertEquals(der.encode(),
                       b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
     self.failUnless(der.hasOnlyInts())
     self.failUnless(der.hasOnlyInts(False))
     # Two mixed integers
     der = DerSequence()
     der.append(2)
     der.append(-2)
     self.assertEquals(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE'))
     self.assertEquals(der.hasInts(), 1)
     self.assertEquals(der.hasInts(False), 2)
     self.failIf(der.hasOnlyInts())
     self.failUnless(der.hasOnlyInts(False))
     #
     der.append(0x01)
     der[1:] = [9, 8]
     self.assertEquals(len(der), 3)
     self.assertEqual(der[1:], [9, 8])
     self.assertEqual(der[1:-1], [9])
     self.assertEquals(der.encode(),
                       b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08'))
Example #39
0
	def testDecode5(self):
		# One single-byte integer (looks negative)
		der = DerSequence()
		der.decode('0\x04\x02\x02\x00\xff')
		self.assertEquals(len(der),1)
		self.assertEquals(der[0],0xFFL)
Example #40
0
	def testDecode3(self):
		# One multi-byte integer (non-zero)
		der = DerSequence()
		der.decode('0\x04\x02\x02\x01\x80')
		self.assertEquals(len(der),1)
		self.assertEquals(der[0],0x180L)
Example #41
0
def dump_signature(data):
    if data[0:2] == b'\x30\x82':
        slen = struct.unpack('>H', data[2:4])[0]
        total = slen + 4
        cert = struct.unpack('<%ds' % total, data[0:total])[0]

        der = DerSequence()
        der.decode(cert)
        cert0 = DerSequence()
        cert0.decode(bytes(der[1]))

        pk = DerSequence()
        pk.decode(bytes(cert0[0]))
        subjectPublicKeyInfo = pk[6]

        meta = DerSequence()
        meta.decode(der[3])
        print(der[3])
        name = meta[0][2:]
        length = meta[1]

        signature = bytes(der[4])[4:0x104]
        pub_key = RSA.importKey(subjectPublicKeyInfo)
        hash=extract_hash(pub_key,signature)
        return [name,length,hash,pub_key,bytes(der[3])[1:2]]
Example #42
0
    def encrypt(data, passphrase, protection, prot_params=None, randfunc=None):
        """Encrypt a piece of data using a passphrase and *PBES2*.

        :Parameters:
          data : byte string
            The piece of data to encrypt.
          passphrase : byte string
            The passphrase to use for encrypting the data.
          protection : string
            The identifier of the encryption algorithm to use.
            The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'.
          prot_params : dictionary
            Parameters of the protection algorithm.

            +------------------+-----------------------------------------------+
            | Key              | Description                                   |
            +==================+===============================================+
            | iteration_count  | The KDF algorithm is repeated several times to|
            |                  | slow down brute force attacks on passwords    |
            |                  | (called *N* or CPU/memory cost in scrypt).    |
            |                  |                                               |
            |                  | The default value for PBKDF2 is 1 000.        |
            |                  | The default value for scrypt is 16 384.       |
            +------------------+-----------------------------------------------+
            | salt_size        | Salt is used to thwart dictionary and rainbow |
            |                  | attacks on passwords. The default value is 8  |
            |                  | bytes.                                        |
            +------------------+-----------------------------------------------+
            | block_size       | *(scrypt only)* Memory-cost (r). The default  |
            |                  | value is 8.                                   |
            +------------------+-----------------------------------------------+
            | parallelization  | *(scrypt only)* CPU-cost (p). The default     |
            |                  | value is 1.                                   |
            +------------------+-----------------------------------------------+


          randfunc : callable
            Random number generation function; it should accept
            a single integer N and return a string of random data,
            N bytes long. If not specified, a new RNG will be
            instantiated from ``Crypto.Random``.

        :Returns:
          The encrypted data, as a binary string.
        """

        if prot_params is None:
            prot_params = {}

        if randfunc is None:
            randfunc = Random.new().read

        if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC':
            key_size = 24
            module = DES3
            cipher_mode = DES3.MODE_CBC
            enc_oid = _OID_DES_EDE3_CBC
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC',
                            'scryptAndAES128-CBC'):
            key_size = 16
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = _OID_AES128_CBC
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC',
                            'scryptAndAES192-CBC'):
            key_size = 24
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = _OID_AES192_CBC
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC',
                            'scryptAndAES256-CBC'):
            key_size = 32
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = _OID_AES256_CBC
        else:
            raise ValueError("Unknown PBES2 mode")

        # Get random data
        iv = randfunc(module.block_size)
        salt = randfunc(prot_params.get("salt_size", 8))

        # Derive key from password
        if protection.startswith('PBKDF2'):
            count = prot_params.get("iteration_count", 1000)
            key = PBKDF2(passphrase, salt, key_size, count)
            kdf_info = DerSequence([
                DerObjectId(_OID_PBKDF2),  # PBKDF2
                DerSequence([DerOctetString(salt),
                             DerInteger(count)])
            ])
        else:
            # It must be scrypt
            count = prot_params.get("iteration_count", 16384)
            scrypt_r = prot_params.get('block_size', 8)
            scrypt_p = prot_params.get('parallelization', 1)
            key = scrypt(passphrase, salt, key_size, count, scrypt_r, scrypt_p)
            kdf_info = DerSequence([
                DerObjectId(_OID_SCRYPT),  # scrypt
                DerSequence([
                    DerOctetString(salt),
                    DerInteger(count),
                    DerInteger(scrypt_r),
                    DerInteger(scrypt_p)
                ])
            ])

        # Create cipher and use it
        cipher = module.new(key, cipher_mode, iv)
        encrypted_data = cipher.encrypt(pad(data, cipher.block_size))
        enc_info = DerSequence([DerObjectId(enc_oid), DerOctetString(iv)])

        # Result
        enc_private_key_info = DerSequence([
            # encryptionAlgorithm
            DerSequence([
                DerObjectId(_OID_PBES2),
                DerSequence([kdf_info, enc_info]),
            ]),
            DerOctetString(encrypted_data)
        ])
        return enc_private_key_info.encode()
Example #43
0
    def exportKey(self,
                  format='PEM',
                  passphrase=None,
                  pkcs=1,
                  protection=None,
                  randfunc=None):
        """Export this RSA key.

        Args:
          format (string):
            The format to use for wrapping the key:

            - *'PEM'*. (*Default*) Text encoding, done according to `RFC1421`_/`RFC1423`_.
            - *'DER'*. Binary encoding.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).

          passphrase (string):
            (*For private keys only*) The pass phrase used for protecting the output.

          pkcs (integer):
            (*For private keys only*) The ASN.1 structure to use for
            serializing the key. Note that even in case of PEM
            encoding, there is an inner ASN.1 DER structure.

            With ``pkcs=1`` (*default*), the private key is encoded in a
            simple `PKCS#1`_ structure (``RSAPrivateKey``).

            With ``pkcs=8``, the private key is encoded in a `PKCS#8`_ structure
            (``PrivateKeyInfo``).

            .. note::
                This parameter is ignored for a public key.
                For DER and PEM, an ASN.1 DER ``SubjectPublicKeyInfo``
                structure is always used.

          protection (string):
            (*For private keys only*)
            The encryption scheme to use for protecting the private key.

            If ``None`` (default), the behavior depends on :attr:`format`:

            - For *'DER'*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
              scheme is used. The following operations are performed:

                1. A 16 byte Triple DES key is derived from the passphrase
                   using :func:`Crypto.Protocol.KDF.PBKDF2` with 8 bytes salt,
                   and 1 000 iterations of :mod:`Crypto.Hash.HMAC`.
                2. The private key is encrypted using CBC.
                3. The encrypted key is encoded according to PKCS#8.

            - For *'PEM'*, the obsolete PEM encryption scheme is used.
              It is based on MD5 for key derivation, and Triple DES for encryption.

            Specifying a value for :attr:`protection` is only meaningful for PKCS#8
            (that is, ``pkcs=8``) and only if a pass phrase is present too.

            The supported schemes for PKCS#8 are listed in the
            :mod:`Crypto.IO.PKCS8` module (see :attr:`wrap_algo` parameter).

          randfunc (callable):
            A function that provides random bytes. Only used for PEM encoding.
            The default is :func:`Crypto.Random.get_random_bytes`.

        Returns:
          byte string: the encoded key

        Raises:
          ValueError:when the format is unknown or when you try to encrypt a private
            key with *DER* format and PKCS#1.

        .. warning::
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """

        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if randfunc is None:
            randfunc = Random.get_random_bytes

        if format == 'OpenSSH':
            e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)]
            if bord(e_bytes[0]) & 0x80:
                e_bytes = bchr(0) + e_bytes
            if bord(n_bytes[0]) & 0x80:
                n_bytes = bchr(0) + n_bytes
            keyparts = [b('ssh-rsa'), e_bytes, n_bytes]
            keystring = b('').join(
                [struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return b('ssh-rsa ') + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        if self.has_private():
            binary_key = DerSequence([
                0, self.n, self.e, self.d, self.p, self.q,
                self.d % (self.p - 1), self.d % (self.q - 1),
                Integer(self.q).inverse(self.p)
            ]).encode()
            if pkcs == 1:
                key_type = 'RSA PRIVATE KEY'
                if format == 'DER' and passphrase:
                    raise ValueError("PKCS#1 private key cannot be encrypted")
            else:  # PKCS#8
                if format == 'PEM' and protection is None:
                    key_type = 'PRIVATE KEY'
                    binary_key = PKCS8.wrap(binary_key, oid, None)
                else:
                    key_type = 'ENCRYPTED PRIVATE KEY'
                    if not protection:
                        protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
                    binary_key = PKCS8.wrap(binary_key, oid, passphrase,
                                            protection)
                    passphrase = None
        else:
            key_type = "PUBLIC KEY"
            binary_key = _create_subject_public_key_info(
                oid, DerSequence([self.n, self.e]))

        if format == 'DER':
            return binary_key
        if format == 'PEM':
            pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc)
            return tobytes(pem_str)

        raise ValueError(
            "Unknown key format '%s'. Cannot export the RSA key." % format)
Example #44
0
    def exportKey(self,
                  format='PEM',
                  pkcs8=None,
                  passphrase=None,
                  protection=None,
                  randfunc=None):
        """Export this DSA key.

        Args:
          format (string):
            The encoding for the output:

            - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_.
            - *'DER'*. Binary ASN.1 encoding.
            - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_.
              Only suitable for public keys, not for private keys.

          passphrase (string):
            *Private keys only*. The pass phrase to protect the output.

          pkcs8 (boolean):
            *Private keys only*. If ``True`` (default), the key is encoded
            with `PKCS#8`_. If ``False``, it is encoded in the custom
            OpenSSL/OpenSSH container.

          protection (string):
            *Only in combination with a pass phrase*.
            The encryption scheme to use to protect the output.

            If :data:`pkcs8` takes value ``True``, this is the PKCS#8
            algorithm to use for deriving the secret and encrypting
            the private DSA key.
            For a complete list of algorithms, see :mod:`Crypto.IO.PKCS8`.
            The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*.

            If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is
            used. It is based on MD5 for key derivation, and Triple DES for
            encryption. Parameter :data:`protection` is then ignored.

            The combination ``format='DER'`` and ``pkcs8=False`` is not allowed
            if a passphrase is present.

          randfunc (callable):
            A function that returns random bytes.
            By default it is :func:`Crypto.Random.get_random_bytes`.

        Returns:
          byte string : the encoded key

        Raises:
          ValueError : when the format is unknown or when you try to encrypt a private
            key with *DER* format and OpenSSL/OpenSSH.

        .. warning::
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _RFC4253:    http://www.ietf.org/rfc/rfc4253.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """

        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if randfunc is None:
            randfunc = Random.get_random_bytes

        if format == 'OpenSSH':
            tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')]

            def func(x):
                if (bord(x[0]) & 0x80):
                    return bchr(0) + x
                else:
                    return x

            tup2 = list(map(func, tup1))
            keyparts = [b('ssh-dss')] + tup2
            keystring = b('').join(
                [struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return b('ssh-dss ') + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        params = DerSequence([self.p, self.q, self.g])
        if self.has_private():
            if pkcs8 is None:
                pkcs8 = True
            if pkcs8:
                if not protection:
                    protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
                private_key = DerInteger(self.x).encode()
                binary_key = PKCS8.wrap(private_key,
                                        oid,
                                        passphrase,
                                        protection,
                                        key_params=params,
                                        randfunc=randfunc)
                if passphrase:
                    key_type = 'ENCRYPTED PRIVATE'
                else:
                    key_type = 'PRIVATE'
                passphrase = None
            else:
                if format != 'PEM' and passphrase:
                    raise ValueError("DSA private key cannot be encrypted")
                ints = [0, self.p, self.q, self.g, self.y, self.x]
                binary_key = DerSequence(ints).encode()
                key_type = "DSA PRIVATE"
        else:
            if pkcs8:
                raise ValueError("PKCS#8 is only meaningful for private keys")

            binary_key = _create_subject_public_key_info(
                oid, DerInteger(self.y), params)
            key_type = "PUBLIC"

        if format == 'DER':
            return binary_key
        if format == 'PEM':
            pem_str = PEM.encode(binary_key, key_type + " KEY", passphrase,
                                 randfunc)
            return tobytes(pem_str)
        raise ValueError(
            "Unknown key format '%s'. Cannot export the DSA key." % format)
Example #45
0
 def testErrDecode2(self):
     der = DerSequence()
     # Too much data
     self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'))
Example #46
0
 def testDecode9(self):
     # Verify that decode returns itself
     der = DerSequence()
     self.assertEqual(der, der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')))
Example #47
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'))
Example #48
0
	def testDecode2(self):
		# One single-byte integer (non-zero)
		der = DerSequence()
		der.decode('0\x03\x02\x01\x7f')
		self.assertEquals(len(der),1)
		self.assertEquals(der[0],127)
Example #49
0
	def testErrDecode1(self):
		# Not a sequence
		der = DerSequence()
		self.assertRaises(ValueError, der.decode, '')
		self.assertRaises(ValueError, der.decode, '\x00')
		self.assertRaises(ValueError, der.decode, '\x30')
Example #50
0
    def decrypt(data, passphrase):
        """Decrypt a piece of data using a passphrase and *PBES2*.

        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, nr_elements=2)
        enc_algo = DerSequence().decode(enc_private_key_info[0])
        encrypted_data = DerOctetString().decode(
            enc_private_key_info[1]).payload

        pbe_oid = DerObjectId().decode(enc_algo[0]).value
        if pbe_oid != _OID_PBES2:
            raise PbesError("Not a PBES2 object")

        pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2)

        ### Key Derivation Function selection
        kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2)
        kdf_oid = DerObjectId().decode(kdf_info[0]).value

        kdf_key_length = None

        # We only support PBKDF2 or scrypt
        if kdf_oid == _OID_PBKDF2:

            pbkdf2_params = DerSequence().decode(kdf_info[1],
                                                 nr_elements=(2, 3, 4))
            salt = DerOctetString().decode(pbkdf2_params[0]).payload
            iteration_count = pbkdf2_params[1]

            left = len(pbkdf2_params) - 2
            idx = 2

            if left > 0:
                try:
                    kdf_key_length = pbkdf2_params[idx] - 0
                    left -= 1
                    idx += 1
                except TypeError:
                    pass

            # Default is HMAC-SHA1
            pbkdf2_prf_oid = "1.2.840.113549.2.7"
            if left > 0:
                pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx])
                pbkdf2_prf_oid = DerObjectId().decode(
                    pbkdf2_prf_algo_id[0]).value

        elif kdf_oid == _OID_SCRYPT:

            scrypt_params = DerSequence().decode(kdf_info[1],
                                                 nr_elements=(4, 5))
            salt = DerOctetString().decode(scrypt_params[0]).payload
            iteration_count, scrypt_r, scrypt_p = [
                scrypt_params[x] for x in (1, 2, 3)
            ]
            if len(scrypt_params) > 4:
                kdf_key_length = scrypt_params[4]
            else:
                kdf_key_length = None
        else:
            raise PbesError("Unsupported PBES2 KDF")

        ### Cipher selection
        enc_info = DerSequence().decode(pbes2_params[1])
        enc_oid = DerObjectId().decode(enc_info[0]).value

        if enc_oid == _OID_DES_EDE3_CBC:
            # DES_EDE3_CBC
            ciphermod = DES3
            key_size = 24
        elif enc_oid == _OID_AES128_CBC:
            # AES128_CBC
            ciphermod = AES
            key_size = 16
        elif enc_oid == _OID_AES192_CBC:
            # AES192_CBC
            ciphermod = AES
            key_size = 24
        elif enc_oid == _OID_AES256_CBC:
            # AES256_CBC
            ciphermod = AES
            key_size = 32
        else:
            raise PbesError("Unsupported PBES2 cipher")

        if kdf_key_length and kdf_key_length != key_size:
            raise PbesError("Mismatch between PBES2 KDF parameters"
                            " and selected cipher")

        IV = DerOctetString().decode(enc_info[1]).payload

        # Create cipher
        if kdf_oid == _OID_PBKDF2:
            if pbkdf2_prf_oid == _OID_HMAC_SHA1:
                hmac_hash_module = SHA1
            elif pbkdf2_prf_oid == _OID_HMAC_SHA224:
                hmac_hash_module = SHA224
            elif pbkdf2_prf_oid == _OID_HMAC_SHA256:
                hmac_hash_module = SHA256
            elif pbkdf2_prf_oid == _OID_HMAC_SHA384:
                hmac_hash_module = SHA384
            elif pbkdf2_prf_oid == _OID_HMAC_SHA512:
                hmac_hash_module = SHA512
            else:
                raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid)

            key = PBKDF2(passphrase,
                         salt,
                         key_size,
                         iteration_count,
                         hmac_hash_module=hmac_hash_module)
        else:
            key = scrypt(passphrase, salt, key_size, iteration_count, scrypt_r,
                         scrypt_p)
        cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV)

        # Decrypt data
        pt = cipher.decrypt(encrypted_data)
        return unpad(pt, cipher.block_size)
Example #51
0
	def testErrDecode3(self):
		# Wrong length format
		der = DerSequence()
		self.assertRaises(ValueError, der.decode, '\x30\x04\x02\x01\x01\x00')
		self.assertRaises(ValueError, der.decode, '\x30\x81\x03\x02\x01\x01')
		self.assertRaises(ValueError, der.decode, '\x30\x04\x02\x81\x01\x01')
Example #52
0
def _importKeyDER(key_data, passphrase, params):
    """Import a DSA key (public or private half), encoded in DER form."""

    try:
        #
        # Dss-Parms  ::=  SEQUENCE  {
        #       p       OCTET STRING,
        #       q       OCTET STRING,
        #       g       OCTET STRING
        # }
        #

        # Try a simple private key first
        if params:
            x = DerInteger().decode(key_data).value
            p, q, g = list(DerSequence().decode(params))    # Dss-Parms
            tup = (pow(g, x, p), g, p, q, x)
            return construct(tup)

        der = DerSequence().decode(key_data)

        # Try OpenSSL format for private keys
        if len(der) == 6 and der.hasOnlyInts() and der[0] == 0:
            tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
            return construct(tup)

        # Try SubjectPublicKeyInfo
        if len(der) == 2:
            try:
                algo = DerSequence().decode(der[0])
                algo_oid = DerObjectId().decode(algo[0]).value
                params = DerSequence().decode(algo[1])  # Dss-Parms

                if algo_oid == oid and len(params) == 3 and\
                        params.hasOnlyInts():
                    bitmap = DerBitString().decode(der[1])
                    pub_key = DerInteger().decode(bitmap.value)
                    tup = [pub_key.value]
                    tup += [params[comp] for comp in (2, 0, 1)]
                    return construct(tup)
            except (ValueError, EOFError):
                pass

        # Try to see if this is an X.509 DER certificate
        # (Certificate ASN.1 type)
        if len(der) == 3:
            from Crypto.PublicKey import _extract_sp_info
            try:
                sp_info = _extract_sp_info(der)
                return _importKeyDER(sp_info, passphrase, None)
            except ValueError:
                pass

        # Try unencrypted PKCS#8
        p8_pair = PKCS8.unwrap(key_data, passphrase)
        if p8_pair[0] == oid:
            return _importKeyDER(p8_pair[1], passphrase, p8_pair[2])

    except (ValueError, EOFError):
        pass

    raise ValueError("DSA key format is not supported")
Example #53
0
 def testEncode5(self):
     der = DerSequence()
     der += 1
     der += b('\x30\x00')
     self.assertEquals(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00'))
Example #54
0
        if bord(externKey[0])==0x30:
                # This is probably a DER encoded key
                return self._importKeyDER(externKey)
        
        raise ValueError("RSA key format is not supported")

#: This is the ASN.1 DER object that qualifies an algorithm as
#: compliant to PKCS#1 (that is, the standard RSA).
# It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
# It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
#   0x06 0x09   OBJECT IDENTIFIER, 9 bytes of payload
#     0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
#               rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
#   0x05 0x00   NULL
algorithmIdentifier = DerSequence(
  [ b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
  DerNull().encode() ]
  ).encode()
 
_impl = RSAImplementation()
#:
#: Randomly generate a fresh, new RSA key object.
#:
#: See `RSAImplementation.generate`.
#:
generate = _impl.generate
#:
#: Construct an RSA key object from a tuple of valid RSA components.
#:
#: See `RSAImplementation.construct`.
#:
construct = _impl.construct
Example #55
0
    def exportKey(self, format='PEM', passphrase=None, pkcs=1):
        """Export this RSA key.

        :Parameter format: The format to use for wrapping the key.

            - *'DER'*. Binary encoding, always unencrypted.
            - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
              Unencrypted (default) or encrypted.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).
        :Type format: string

        :Parameter passphrase: In case of PEM, the pass phrase to derive the encryption key from.
        :Type passphrase: string 

        :Parameter pkcs: The PKCS standard to follow for assembling the key.
         You have two choices:

          - with **1**, the public key is embedded into an X.509 `SubjectPublicKeyInfo` DER SEQUENCE.
            The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQUENCE.
            This mode is the default.
          - with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE.
            This mode is not available for public keys.

         PKCS standards are not relevant for the *OpenSSH* format.
        :Type pkcs: integer

        :Return: A byte string with the encoded public or private half.
        :Raise ValueError:
            When the format is unknown.

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """
        if passphrase is not None:
            passphrase = tobytes(passphrase)
        if format=='OpenSSH':
               eb = long_to_bytes(self.e)
               nb = long_to_bytes(self.n)
               if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
               if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
               keyparts = [ b('ssh-rsa'), eb, nb ]
               keystring = b('').join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
               return b('ssh-rsa ')+binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        der = DerSequence()
        if self.has_private():
                keyType= { 1: 'RSA PRIVATE', 8: 'PRIVATE' }[pkcs]
                der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
                           self.d % (self.p-1), self.d % (self.q-1),
                           inverse(self.q, self.p) ]
                if pkcs==8:
                    derkey = der.encode()
                    der = DerSequence([0])
                    der.append(algorithmIdentifier)
                    der.append(DerObject('OCTET STRING', derkey).encode())
        else:
                keyType = "PUBLIC"
                der.append(algorithmIdentifier)
                bitmap = DerObject('BIT STRING')
                derPK = DerSequence( [ self.n, self.e ] )
                bitmap.payload = bchr(0x00) + derPK.encode()
                der.append(bitmap.encode())
        if format=='DER':
                return der.encode()
        if format=='PEM':
                pem = b("-----BEGIN " + keyType + " KEY-----\n")
                objenc = None
                if passphrase and keyType.endswith('PRIVATE'):
                    # We only support 3DES for encryption
                    import Crypto.Hash.MD5
                    from Crypto.Cipher import DES3
                    from Crypto.Protocol.KDF import PBKDF1
                    salt = self._randfunc(8)
                    key =  PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
                    key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
                    objenc = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
                    pem += b('Proc-Type: 4,ENCRYPTED\n')
                    pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(salt).upper() + b('\n\n')
                
                binaryKey = der.encode()
                if objenc:
                    # Add PKCS#7-like padding
                    padding = objenc.block_size-len(binaryKey)%objenc.block_size
                    binaryKey = objenc.encrypt(binaryKey+bchr(padding)*padding)

                # Each BASE64 line can take up to 64 characters (=48 bytes of data)
                chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
                pem += b('').join(chunks)
                pem += b("-----END " + keyType + " KEY-----")
                return pem
        return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
Example #56
0
	def testErrDecode2(self):
		# Wrong payload type
		der = DerSequence()
		self.assertRaises(ValueError, der.decode, '\x30\x00\x00', True)
Example #57
0
    def _importKeyDER(self, externKey):
        """Import an RSA key (public or private half), encoded in DER form."""

        try:

            der = DerSequence()
            der.decode(externKey, True)

            # Try PKCS#1 first, for a private key
            if len(der)==9 and der.hasOnlyInts() and der[0]==0:
                # ASN.1 RSAPrivateKey element
                del der[6:]     # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
                der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
                del der[0]      # Remove version
                return self.construct(der[:])

            # Keep on trying PKCS#1, but now for a public key
            if len(der)==2:
                # The DER object is an RSAPublicKey SEQUENCE with two elements
                if der.hasOnlyInts():
                    return self.construct(der[:])
                # The DER object is a SubjectPublicKeyInfo SEQUENCE with two elements:
                # an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subjectPublicKey' BIT STRING.
                # 'algorithm' takes the value given a few lines above.
                # 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
                if der[0]==algorithmIdentifier:
                        bitmap = DerObject()
                        bitmap.decode(der[1], True)
                        if bitmap.isType('BIT STRING') and bord(bitmap.payload[0])==0x00:
                                der.decode(bitmap.payload[1:], True)
                                if len(der)==2 and der.hasOnlyInts():
                                        return self.construct(der[:])

            # Try unencrypted PKCS#8
            if der[0]==0:
                # The second element in the SEQUENCE is algorithmIdentifier.
                # It must say RSA (see above for description).
                if der[1]==algorithmIdentifier:
                    privateKey = DerObject()
                    privateKey.decode(der[2], True)
                    if privateKey.isType('OCTET STRING'):
                        return self._importKeyDER(privateKey.payload)

        except (ValueError, IndexError):
            pass

        raise ValueError("RSA key format is not supported")
Example #58
0
def wrap(private_key,
         key_oid,
         passphrase=None,
         protection=None,
         prot_params=None,
         key_params=None,
         randfunc=None):
    """Wrap a private key into a PKCS#8 blob (clear or encrypted).

    :Parameters:

      private_key : byte string
        The private key encoded in binary form. The actual encoding is
        algorithm specific. In most cases, it is DER.

      key_oid : string
        The object identifier (OID) of the private key to wrap.
        It is a dotted string, like "``1.2.840.113549.1.1.1``" (for RSA keys).

      passphrase : (binary) string
        The secret passphrase from which the wrapping key is derived.
        Set it only if encryption is required.

      protection : string
        The identifier of the algorithm to use for securely wrapping the key.
        The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'.

      prot_params : dictionary
        Parameters for the protection algorithm.

        +------------------+-----------------------------------------------+
        | Key              | Description                                   |
        +==================+===============================================+
        | iteration_count  | The KDF algorithm is repeated several times to|
        |                  | slow down brute force attacks on passwords    |
        |                  | (called *N* or CPU/memory cost in scrypt).    |
        |                  |                                               |
        |                  | The default value for PBKDF2 is 1 000.        |
        |                  | The default value for scrypt is 16 384.       |
        +------------------+-----------------------------------------------+
        | salt_size        | Salt is used to thwart dictionary and rainbow |
        |                  | attacks on passwords. The default value is 8  |
        |                  | bytes.                                        |
        +------------------+-----------------------------------------------+
        | block_size       | *(scrypt only)* Memory-cost (r). The default  |
        |                  | value is 8.                                   |
        +------------------+-----------------------------------------------+
        | parallelization  | *(scrypt only)* CPU-cost (p). The default     |
        |                  | value is 1.                                   |
        +------------------+-----------------------------------------------+

      key_params : DER object
        The algorithm parameters associated to the private key.
        It is required for algorithms like DSA, but not for others like RSA.

      randfunc : callable
        Random number generation function; it should accept a single integer
        N and return a string of random data, N bytes long.
        If not specified, a new RNG will be instantiated
        from ``Crypto.Random``.

    :Return:
      The PKCS#8-wrapped private key (possibly encrypted),
      as a binary string.
    """

    if key_params is None:
        key_params = DerNull()

    #
    #   PrivateKeyInfo ::= SEQUENCE {
    #       version                 Version,
    #       privateKeyAlgorithm     PrivateKeyAlgorithmIdentifier,
    #       privateKey              PrivateKey,
    #       attributes              [0]  IMPLICIT Attributes OPTIONAL
    #   }
    #
    pk_info = DerSequence([
        0,
        DerSequence([DerObjectId(key_oid), key_params]),
        DerOctetString(private_key)
    ])
    pk_info_der = pk_info.encode()

    if passphrase is None:
        return pk_info_der

    if not passphrase:
        raise ValueError("Empty passphrase")

    # Encryption with PBES2
    passphrase = tobytes(passphrase)
    if protection is None:
        protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
    return PBES2.encrypt(pk_info_der, passphrase, protection, prot_params,
                         randfunc)
Example #59
0
        keyparts = []
        while len(keystring) > 4:
            l = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + l])
            keystring = keystring[4 + l:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _importKeyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")


#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates
#: a generic RSA key, even when such key will be actually used for digital
#: signatures.
#:
#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
oid = "1.2.840.113549.1.1.1"

#: This is the standard DER object that qualifies a cryptographic algorithm
#: in ASN.1-based data structures (e.g. X.509 certificates).
algorithmIdentifier = DerSequence([
    DerObjectId(oid).encode(),  # algorithm field
    DerNull().encode()
]  # parameters field
                                  ).encode()