Esempio n. 1
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:8]	# Remove d mod (p-1) and d mod (q-1)
		del der[0]	# Remove version
		return self.construct(der[:])
	if len(der)==2:
		# ASN.1 SubjectPublicKeyInfo element
		if der[0]=='\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=='\x03' and bitmap.payload[0]=='\x00':
				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")
Esempio n. 2
0
def _import_pkcs1_private(encoded, *kwargs):
    # RSAPrivateKey ::= SEQUENCE {
    #           version Version,
    #           modulus INTEGER, -- n
    #           publicExponent INTEGER, -- e
    #           privateExponent INTEGER, -- d
    #           prime1 INTEGER, -- p
    #           prime2 INTEGER, -- q
    #           exponent1 INTEGER, -- d mod (p-1)
    #           exponent2 INTEGER, -- d mod (q-1)
    #           coefficient INTEGER -- (inverse of q) mod p
    # }
    #
    # Version ::= INTEGER
    der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True)
    if der[0] != 0:
        raise ValueError("No PKCS#1 encoding of an RSA private key")
    return construct(der[1:6] + [Integer(der[4]).inverse(der[5])])
Esempio n. 3
0
    def sign(self, msg_hash):
        """Compute the DSA/ECDSA signature of a message.

        Args:
          msg_hash (hash object):
            The hash that was carried out over the message.
            The object belongs to the :mod:`Crypto.Hash` package.
            Under mode ``'fips-186-3'``, the hash must be a FIPS
            approved secure hash (SHA-2 or SHA-3).

        :return: The signature as ``bytes``
        :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key
        :raise TypeError: if the (EC)DSA key has no private half
        """

        if not self._key.has_private():
            raise TypeError("Private key is needed to sign")

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

        # Generate the nonce k (critical!)
        nonce = self._compute_nonce(msg_hash)

        # Perform signature using the raw API
        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        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._order_bytes) for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            # Ecdsa-Sig-Value  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            output = DerSequence(sig_pair).encode()

        return output
Esempio n. 4
0
 def process(self, data):
     key = normalize_rsa_key(data, force_public=self.args.public)
     out = self.args.output
     if out is RSAFormat.PEM:
         yield key.export_key('PEM')
         return
     if out is RSAFormat.DER:
         yield key.export_key('DER')
         return
     components = {
         'Modulus': key.n,
         'Exponent': key.e,
     }
     if key.has_private():
         decoded = DerSequence()
         decoded.decode(key.export_key('DER'))
         it = itertools.islice(decoded, 3, None)
         for v in ('D', 'P', 'Q', 'DP', 'DQ', 'InverseQ'):
             try:
                 components[v] = next(it)
             except StopIteration:
                 break
     if out is RSAFormat.XKMS:
         for tag in components:
             components[tag] = base64.b64encode(
                 number.long_to_bytes(components[tag])).decode('ascii')
         tags = '\n'.join(F'\t<{tag}>{value}</{tag}>'
                          for tag, value in components.items())
         yield F'<RSAKeyPair>\n{tags}\n</RSAKeyPair>'.encode(self.codec)
         return
     components['BitSize'] = key.n.bit_length()
     for tag, value in components.items():
         if value.bit_length() > 32:
             components[tag] = F'{value:X}'
     if out is RSAFormat.JSON:
         yield json.dumps(components, indent=4).encode(self.codec)
         return
     if out is RSAFormat.TEXT:
         table = list(flattened(components))
         for key, value in table:
             value = F'0x{value}' if isinstance(value, str) else str(value)
             value = '\n'.join(F'{L}' for L in textwrap.wrap(value, 80))
             yield F'-- {key+" ":-<77}\n{value!s}'.encode(self.codec)
Esempio n. 5
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),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used
            in combination with SHA-512.

        :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.
        """

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

        # Generate the nonce k (critical!)
        nonce = self._compute_nonce(msg_hash)

        # Perform signature using the raw API
        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        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._order_bytes)
                                 for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #               r       OCTET STRING,
            #               s       OCTET STRING
            # }
            output = DerSequence(sig_pair).encode()

        return output
Esempio n. 6
0
def privKeyXML(pemPrivateKeyFile):

    with open (pemPrivateKeyFile, 'rb') as pkFile:
        pemPrivKey = pkFile.read()
    print(type(pemPrivKey))
    pemPrivKey = pemPrivKey.decode("utf-8")
    lines = pemPrivKey.replace(" ", '').split()
    # print('555555555')
    print(len(lines))
    keyDer = DerSequence()
    keyDer.decode(a2b_base64(''.join(lines[1:-1])))
    # print(type(standard_b64encode(number.long_to_bytes(keyDer[1]))))
    xml  = '<RSAKeyValue>'
    xml += '<Modulus>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[1])).decode("utf-8")
    xml += '</Modulus>'
    xml += '<Exponent>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[2])).decode("utf-8")
    xml += '</Exponent>'
    xml += '<D>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[3])).decode("utf-8")
    xml += '</D>'
    xml += '<P>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[4])).decode("utf-8")
    xml += '</P>'
    xml += '<Q>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[5])).decode("utf-8")
    xml += '</Q>'
    xml += '<DP>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[6])).decode("utf-8")
    xml += '</DP>'
    xml += '<DQ>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[7])).decode("utf-8")
    xml += '</DQ>'
    xml += '<InverseQ>'
    xml += standard_b64encode(number.long_to_bytes(keyDer[8])).decode("utf-8")
    xml += '</InverseQ>'
    xml += '</RSAKeyValue>'
    fileName = basename(pemPrivateKeyFile)
    with open (fileName+'.xml', 'w') as pkFile:
        pkFile.write(xml)
    return
Esempio n. 7
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 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
Esempio n. 8
0
def _import_private_der(encoded, passphrase, curve_name=None):

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

    private_key = DerSequence().decode(encoded, nr_elements=(3, 4))
    if private_key[0] != 1:
        raise ValueError("Incorrect ECC private key version")

    try:
        curve_name = DerObjectId(explicit=0).decode(private_key[2]).value
    except ValueError:
        pass

    if curve_name != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" %
                                    curve_name)

    scalar_bytes = DerOctetString().decode(private_key[1]).payload
    order_bytes = _curve.order.size_in_bytes()
    if len(scalar_bytes) != order_bytes:
        raise ValueError("Private key is too small")
    d = Integer.from_bytes(scalar_bytes)

    # Decode public key (if any, it must be P-256)
    if len(private_key) == 4:
        public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value
        public_key = _import_public_der(curve_name, public_key_enc)
        point_x = public_key.pointQ.x
        point_y = public_key.pointQ.y
    else:
        point_x = point_y = None

    return construct(curve="P-256", d=d, point_x=point_x, point_y=point_y)
def sign_bytes_dsa(byte_array, path_to_private_key_pem_file):
    # Use this method for DSA keys
    key = open(path_to_private_key_pem_file, 'r').read()
    # Import the key
    dsa_key = DSA.importKey(key)

    # Create a digest of nonce + cnonce
    # This only seems to work with SHA1 (SHA256 gives us a 401 error)
    buf = buffer(byte_array)
    digest = SHA1.new(buf).digest()

    # Digitally sign the digest with our private key
    # The corresponding public key is in our admin handle on the server
    k = random.StrongRandom().randint(1, dsa_key.q - 1)
    sign = dsa_key.sign(digest, k)

    # Signature bytes from a DSA key need to be DER-encoded
    # This signature is in two parts (r and s)
    seq = DerSequence()
    seq.append(sign[0])
    seq.append(sign[1])

    return seq.encode()
Esempio n. 10
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'))
		self.assertEquals(len(der),1)
		self.assertEquals(der[0],2**2048)
Esempio n. 11
0
def extractCerts (pem):

    # pem may be multiple certs, so we remove the
    # 'begin cert' and 'end cert' comments, and then 
    # group the cert lines together, one big line for each cert
    lines = pem.replace(" ",'').split()
    encodedCerts = []
    for line in lines:
        if '-' in line:
            # Skip this. Append a new blank cert line
            encodedCerts.append('')
        else:
            encodedCerts[len(encodedCerts)-1] = encodedCerts[len(encodedCerts)-1] + line

    # remove all blank cert strings
    certs = []
    for encodedCert in encodedCerts:
        if len(encodedCert) > 0:
            der = a2b_base64(encodedCert)
            cert = DerSequence()
            cert.decode(der)   
            certs.append(cert) 
    return certs
Esempio n. 12
0
	def testEncode4(self):
		# One very long integer
		der = DerSequence()
		der.append(2**2048)
		self.assertEquals(der.encode(), '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')
Esempio n. 13
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)
Esempio n. 14
0
	def testErrDecode2(self):
		# Wrong payload type
		der = DerSequence()
		self.assertRaises(ValueError, der.decode, '\x30\x00\x00', True)
Esempio n. 15
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)
Esempio n. 16
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)
Esempio n. 17
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)
Esempio n. 18
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")
Esempio n. 19
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
Esempio n. 20
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)
Esempio n. 21
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')
Esempio n. 22
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'))
Esempio n. 23
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')
Esempio n. 24
0
 def testEncode5(self):
     der = DerSequence()
     der += 1
     der += b('\x30\x00')
     self.assertEquals(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00'))
Esempio n. 25
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)
Esempio n. 26
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')))
Esempio n. 27
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')
Esempio n. 28
0
 def testErrDecode2(self):
     der = DerSequence()
     # Too much data
     self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'))
Esempio n. 29
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')
Esempio n. 30
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)