コード例 #1
0
    def load_encrypted_keydata(self, keydata):
        """Load a key from encrypted keydata (in PEM format)."""
        lines = keydata.strip().replace(' ', '').splitlines()
        if not lines[1].startswith('Proc-Type:4,ENCRYPTED'):
            raise TypeError('Unsupported encryption')

        dek = lines[2].split(':')
        if len(dek) != 2 or dek[0] != 'DEK-Info':
            raise ValueError('PEM encryption method not supported')

        algo, salt = dek[1].split(',')
        salt = binascii.unhexlify(salt)

        if algo == 'DES-CBC':
            key = PBKDF1(self.passphrase, salt, 8, 1, MD5)
            obj = DES.new(key, DES.MODE_CBC, salt)

        elif algo == 'DES-EDE3-CBC':
            key = PBKDF1(self.passphrase, salt, 16, 1, MD5)
            key += PBKDF1(key + self.passphrase, salt, 8, 1, MD5)
            obj = DES3.new(key, DES3.MODE_CBC, salt)

        elif algo == 'AES-128-CBC':
            key = PBKDF1(self.passphrase, salt[:8], 16, 1, MD5)
            obj = AES.new(key, AES.MODE_CBC, salt)

        else:
            raise TypeError('%s: cipher not supported' % (algo, ))

        lines = lines[3:-1]
        data = base64.b64decode(''.join(lines))
        return unpad(obj.decrypt(data), obj.block_size)
コード例 #2
0
ファイル: PEM.py プロジェクト: 37976120/37976120.github.io
def encode(data, marker, passphrase=None, randfunc=None):
    """Encode a piece of binary data into PEM format.

    Args:
      data (byte string):
        The piece of binary data to encode.
      marker (string):
        The marker for the PEM block (e.g. "PUBLIC KEY").
        Note that there is no official master list for all allowed markers.
        Still, you can refer to the OpenSSL_ source code.
      passphrase (byte string):
        If given, the PEM block will be encrypted. The key is derived from
        the passphrase.
      randfunc (callable):
        Random number generation function; it accepts an integer N and returns
        a byte string of random data, N bytes long. If not given, a new one is
        instantiated.

    Returns:
      The PEM block, as a string.

    .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h
    """

    if randfunc is None:
        randfunc = get_random_bytes

    out = "-----BEGIN %s-----\n" % marker
    if passphrase:
        # We only support 3DES for encryption
        salt = randfunc(8)
        key = PBKDF1(passphrase, salt, 16, 1, MD5)
        key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
        objenc = DES3.new(key, DES3.MODE_CBC, salt)
        out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\
            tostr(hexlify(salt).upper())
        # Encrypt with PKCS#7 padding
        data = objenc.encrypt(pad(data, objenc.block_size))
    elif passphrase is not None:
        raise ValueError("Empty password")

    # Each BASE64 line can take up to 64 characters (=48 bytes of data)
    # b2a_base64 adds a new line character!
    chunks = [
        tostr(b2a_base64(data[i:i + 48])) for i in range(0, len(data), 48)
    ]
    out += "".join(chunks)
    out += "-----END %s-----" % marker
    return out
コード例 #3
0
 def decrypt(data, passphrase):
     encrypted_private_key_info = decode_der(DerSequence, data)
     encrypted_algorithm = decode_der(DerSequence,
                                      encrypted_private_key_info[0])
     encrypted_data = decode_der(DerOctetString,
                                 encrypted_private_key_info[1]).payload
     pbe_oid = decode_der(DerObjectId, encrypted_algorithm[0]).value
     cipher_params = {}
     if pbe_oid == '1.2.840.113549.1.5.3':
         hashmod = MD5
         ciphermod = DES
     elif pbe_oid == '1.2.840.113549.1.5.6':
         hashmod = MD5
         ciphermod = ARC2
         cipher_params['effective_keylen'] = 64
     elif pbe_oid == '1.2.840.113549.1.5.10':
         hashmod = SHA1
         ciphermod = DES
     elif pbe_oid == '1.2.840.113549.1.5.11':
         hashmod = SHA1
         ciphermod = ARC2
         cipher_params['effective_keylen'] = 64
     else:
         raise ValueError('Unknown OID')
     pbe_params = decode_der(DerSequence, encrypted_algorithm[1])
     salt = decode_der(DerOctetString, pbe_params[0]).payload
     iterations = pbe_params[1]
     key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod)
     key, iv = key_iv[:8], key_iv[8:]
     cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
     pt = cipher.decrypt(encrypted_data)
     return unpad(pt, cipher.block_size)
コード例 #4
0
ファイル: pbkdf1.py プロジェクト: binref/refinery
 def process(self, data):
     from Crypto.Protocol.KDF import PBKDF1
     return multidecode(
         data, lambda pwd: (PBKDF1(pwd,
                                   self.args.salt,
                                   dkLen=self.args.size,
                                   count=self.args.iter,
                                   hashAlgo=self.hash)))
コード例 #5
0
def encode(data, marker, passphrase=None, randfunc=None):
    if randfunc is None:
        randfunc = get_random_bytes
    out = '-----BEGIN %s-----\n' % marker
    if passphrase:
        salt = randfunc(8)
        key = PBKDF1(passphrase, salt, 16, 1, MD5)
        key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
        objenc = DES3.new(key, DES3.MODE_CBC, salt)
        out += 'Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n' % tostr(
            hexlify(salt).upper())
        data = objenc.encrypt(pad(data, objenc.block_size))
    chunks = [
        tostr(b2a_base64(data[i:i + 48])) for i in range(0, len(data), 48)
    ]
    out += ''.join(chunks)
    out += '-----END %s-----' % marker
    return out
コード例 #6
0
    def decrypt(data, passphrase):
        """Decrypt a piece of data using a passphrase and *PBES1*.

        The algorithm to use is automatically detected.

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

        encrypted_private_key_info = decode_der(DerSequence, data)
        encrypted_algorithm = decode_der(
                                DerSequence,
                                encrypted_private_key_info[0]
                                )
        encrypted_data = decode_der(
                            DerOctetString,
                            encrypted_private_key_info[1]
                            ).payload

        pbe_oid = decode_der(DerObjectId, encrypted_algorithm[0]).value
        cipher_params = {}
        if pbe_oid == "1.2.840.113549.1.5.3":
            # PBE_MD5_DES_CBC
            hashmod = MD5
            ciphermod = DES
        elif pbe_oid == "1.2.840.113549.1.5.6":
            # PBE_MD5_RC2_CBC
            hashmod = MD5
            ciphermod = ARC2
            cipher_params['effective_keylen'] = 64
        elif pbe_oid == "1.2.840.113549.1.5.10":
            # PBE_SHA1_DES_CBC
            hashmod = SHA1
            ciphermod = DES
        elif pbe_oid == "1.2.840.113549.1.5.11":
            # PBE_SHA1_RC2_CBC
            hashmod = SHA1
            ciphermod = ARC2
            cipher_params['effective_keylen'] = 64
        else:
            raise PbesError("Unknown OID for PBES1")

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

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

        cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
        pt = cipher.decrypt(encrypted_data)
        return unpad(pt, cipher.block_size)
コード例 #7
0
def decode(pem_data, passphrase=None):
    r = re.compile('\\s*-----BEGIN (.*)-----\n')
    m = r.match(pem_data)
    if not m:
        raise ValueError('Not a valid PEM pre boundary')
    marker = m.group(1)
    r = re.compile('-----END (.*)-----\\s*$')
    m = r.search(pem_data)
    if not m or m.group(1) != marker:
        raise ValueError('Not a valid PEM post boundary')
    lines = pem_data.replace(' ', '').split()
    if lines[1].startswith('Proc-Type:4,ENCRYPTED'):
        if not passphrase:
            raise ValueError('PEM is encrypted, but no passphrase available')
        DEK = lines[2].split(':')
        if len(DEK) != 2 or DEK[0] != 'DEK-Info':
            raise ValueError('PEM encryption format not supported.')
        algo, salt = DEK[1].split(',')
        salt = unhexlify(tobytes(salt))
        if algo == 'DES-CBC':
            key = PBKDF1(passphrase, salt, 8, 1, MD5)
            objdec = DES.new(key, DES.MODE_CBC, salt)
        elif algo == 'DES-EDE3-CBC':
            key = PBKDF1(passphrase, salt, 16, 1, MD5)
            key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
            objdec = DES3.new(key, DES3.MODE_CBC, salt)
        elif algo == 'AES-128-CBC':
            key = PBKDF1(passphrase, salt[:8], 16, 1, MD5)
            objdec = AES.new(key, AES.MODE_CBC, salt)
        else:
            raise ValueError('Unsupport PEM encryption algorithm.')
        lines = lines[2:]
    else:
        objdec = None
    data = a2b_base64(b(''.join(lines[1:-1])))
    enc_flag = False
    if objdec:
        data = unpad(objdec.decrypt(data), objdec.block_size)
        enc_flag = True
    return (data, marker, enc_flag)
コード例 #8
0
ファイル: utils.py プロジェクト: sambacha/catena
def encrypt_key_object(private_key):
    data = private_key.exportKey(format='DER')
    out = "-----BEGIN RSA PRIVATE KEY-----\n"
    salt = Random.get_random_bytes(16)

    # Doing some AES-128-CBC here
    key = PBKDF1(CONF.get('encryption_key'), salt[:8], 16, 1, MD5)
    objenc = AES.new(key, AES.MODE_CBC, salt)

    out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: AES-128-CBC,%s\n\n" % (tostr(
        hexlify(salt).upper()))

    data = objenc.encrypt(pad(data, objenc.block_size))
    chunks = [
        tostr(b2a_base64(data[i:i + 48])) for i in range(0, len(data), 48)
    ]
    out += "".join(chunks)
    out += "-----END RSA PRIVATE KEY-----"

    return out
コード例 #9
0
    def importKey(self, externKey, passphrase=None):
        """Import an RSA key (public or private half), encoded in standard form.

        :Parameter externKey:
            The RSA key to import, encoded as a string.

            An RSA public key can be in any of the following formats:

            - X.509 `subjectPublicKeyInfo` DER SEQUENCE (binary or PEM encoding)
            - `PKCS#1`_ `RSAPublicKey` DER SEQUENCE (binary or PEM encoding)
            - OpenSSH (textual public key only)

            An RSA private key can be in any of the following formats:

            - PKCS#1 `RSAPrivateKey` DER SEQUENCE (binary or PEM encoding)
            - `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE (binary or PEM encoding)
            - OpenSSH (textual public key only)

            For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
            
            In case of PEM encoding, the private key can be encrypted with DES or 3TDES according to a certain ``pass phrase``.
            Only OpenSSL-compatible pass phrases are supported.
        :Type externKey: string

        :Parameter passphrase:
            In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.
        :Type passphrase: string
        
        :Return: An RSA key object (`_RSAobj`).

        :Raise ValueError/IndexError/TypeError:
            When the given key cannot be parsed (possibly because the pass phrase is wrong).

        .. _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
        """
        externKey = tobytes(externKey)
        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if externKey.startswith(b('-----')):
                # This is probably a PEM encoded key
                lines = externKey.replace(b(" "),b('')).split()
                keyobj = None

                # The encrypted PEM format
                if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
                    DEK = lines[2].split(b(':'))
                    if len(DEK)!=2 or DEK[0]!=b('DEK-Info') or not passphrase:
                        raise ValueError("PEM encryption format not supported.")
                    algo, salt = DEK[1].split(b(','))
                    salt = binascii.a2b_hex(salt)
                    import Crypto.Hash.MD5
                    from Crypto.Cipher import DES, DES3
                    from Crypto.Protocol.KDF import PBKDF1
                    if algo==b("DES-CBC"):
                        # This is EVP_BytesToKey in OpenSSL
                        key = PBKDF1(passphrase, salt, 8, 1, Crypto.Hash.MD5)
                        keyobj = DES.new(key, Crypto.Cipher.DES.MODE_CBC, salt)
                    elif algo==b("DES-EDE3-CBC"):
                        # Note that EVP_BytesToKey is note exactly the same as PBKDF1
                        key =  PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
                        key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
                        keyobj = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
                    else:
                        raise ValueError("Unsupport PEM encryption algorithm.")
                    lines = lines[2:]
                
                der = binascii.a2b_base64(b('').join(lines[1:-1]))
                if keyobj:
                    der = keyobj.decrypt(der)
                    padding = bord(der[-1])
                    der = der[:-padding]
                return self._importKeyDER(der)

        if externKey.startswith(b('ssh-rsa ')):
                # This is probably an OpenSSH key
                keystring = binascii.a2b_base64(externKey.split(b(' '))[1])
                keyparts = []
                while len(keystring)>4:
                    l = struct.unpack(">I",keystring[:4])[0]
                    keyparts.append(keystring[4:4+l])
                    keystring = keystring[4+l:]
                e = bytes_to_long(keyparts[1])
                n = bytes_to_long(keyparts[2])
                return self.construct([n, e])
        if bord(externKey[0])==0x30:
                # This is probably a DER encoded key
                return self._importKeyDER(externKey)
        
        raise ValueError("RSA key format is not supported")
コード例 #10
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)
コード例 #11
0
ファイル: honey_vault.py プロジェクト: mspencer08/nocrack
def do_crypto_setup(mp, salt = b'madhubala'):
    key = PBKDF1(mp, salt, 16, 100, SHA256)
    ctr = Counter.new(128, initial_value=long(254))
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)
    return aes 
コード例 #12
0
 def test1(self):
     v = self._testData[0]
     res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1)
     self.assertEqual(res, t2b(v[4]))
コード例 #13
0
ファイル: PEM.py プロジェクト: Abdulmohsen-91/Casting-Agency
def decode(pem_data, passphrase=None):
    """Decode a PEM block into binary.

    :Parameters:
      pem_data : string
        The PEM block.
      passphrase : byte string
        If given and the PEM block is encrypted,
        the key will be derived from the passphrase.
    :Returns:
      A tuple with the binary data, the marker string, and a boolean to
      indicate if decryption was performed.
    :Raises ValueError:
      If decoding fails, if the PEM file is encrypted and no passphrase has
      been provided or if the passphrase is incorrect.
    """

    # Verify Pre-Encapsulation Boundary
    r = re.compile("\s*-----BEGIN (.*)-----\n")
    m = r.match(pem_data)
    if not m:
        raise ValueError("Not a valid PEM pre boundary")
    marker = m.group(1)

    # Verify Post-Encapsulation Boundary
    r = re.compile("-----END (.*)-----\s*$")
    m = r.search(pem_data)
    if not m or m.group(1) != marker:
        raise ValueError("Not a valid PEM post boundary")

    # Removes spaces and slit on lines
    lines = pem_data.replace(" ", '').split()

    # Decrypts, if necessary
    if lines[1].startswith('Proc-Type:4,ENCRYPTED'):
        if not passphrase:
            raise ValueError("PEM is encrypted, but no passphrase available")
        DEK = lines[2].split(':')
        if len(DEK) != 2 or DEK[0] != 'DEK-Info':
            raise ValueError("PEM encryption format not supported.")
        algo, salt = DEK[1].split(',')
        salt = unhexlify(tobytes(salt))
        if algo == "DES-CBC":
            # This is EVP_BytesToKey in OpenSSL
            key = PBKDF1(passphrase, salt, 8, 1, MD5)
            objdec = DES.new(key, DES.MODE_CBC, salt)
        elif algo == "DES-EDE3-CBC":
            # Note that EVP_BytesToKey is note exactly the same as PBKDF1
            key = PBKDF1(passphrase, salt, 16, 1, MD5)
            key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
            objdec = DES3.new(key, DES3.MODE_CBC, salt)
        elif algo == "AES-128-CBC":
            key = PBKDF1(passphrase, salt[:8], 16, 1, MD5)
            objdec = AES.new(key, AES.MODE_CBC, salt)
        else:
            raise ValueError("Unsupport PEM encryption algorithm.")
        lines = lines[2:]
    else:
        objdec = None

    # Decode body
    data = a2b_base64(b(''.join(lines[1:-1])))
    enc_flag = False
    if objdec:
        data = unpad(objdec.decrypt(data), objdec.block_size)
        enc_flag = True

    return (data, marker, enc_flag)
コード例 #14
0
def do_crypto_setup():
    key = PBKDF1(PRIVATE_HONEY_ENC_KEY, PRIVATE_SALT, 16, 100, SHA256)
    ctr = Counter.new(8 * SECURITY_PARAM, initial_value=long(254))
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)
    return aes