Esempio n. 1
0
 def test1(self):
     padded = pad(b(""), 4)
     self.assertTrue(padded == uh(b("04040404")))
     padded = pad(b(""), 4, 'pkcs7')
     self.assertTrue(padded == uh(b("04040404")))
     back = unpad(padded, 4)
     self.assertTrue(back == b(""))
Esempio n. 2
0
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
    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 = "1.2.840.113549.3.7"
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC',
                            'scryptAndAES128-CBC'):
            key_size = 16
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = "2.16.840.1.101.3.4.1.2"
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC',
                            'scryptAndAES192-CBC'):
            key_size = 24
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = "2.16.840.1.101.3.4.1.22"
        elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC',
                            'scryptAndAES256-CBC'):
            key_size = 32
            module = AES
            cipher_mode = AES.MODE_CBC
            enc_oid = "2.16.840.1.101.3.4.1.42"
        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("1.2.840.113549.1.5.12"),  # 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("1.3.6.1.4.1.11591.4.11"),  # 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("1.2.840.113549.1.5.13"),  # PBES2
                DerSequence([kdf_info, enc_info]),
            ]),
            DerOctetString(encrypted_data)
        ])
        return enc_private_key_info.encode()
Esempio n. 4
0
 def encrypt(self, raw):
     raw = pad(raw)
     iv = Random.new().read(AES.block_size)
     cipher = AES.new(self.key, AES.MODE_CBC, iv)
     return base64.b64encode(iv + cipher.encrypt(raw))
Esempio n. 5
0
 def test3(self):
     padded = pad(uh(b("123456")), 4, 'x923')
     self.assertTrue(padded == uh(b("12345601")))
     back = unpad(padded, 4, 'x923')
     self.assertTrue(back == uh(b("123456")))
Esempio n. 6
0
 def test2(self):
     padded = pad(uh(b("12345678")), 4, 'x923')
     self.assertTrue(padded == uh(b("1234567800000004")))
     back = unpad(padded, 4, 'x923')
     self.assertTrue(back == uh(b("12345678")))
Esempio n. 7
0
 def test1(self):
     padded = pad(b(""), 4, 'x923')
     self.assertTrue(padded == uh(b("00000004")))
     back = unpad(padded, 4, 'x923')
     self.assertTrue(back == b(""))
Esempio n. 8
0
 def test4(self):
     padded = pad(uh(b("1234567890")), 4)
     self.assertTrue(padded == uh(b("1234567890030303")))
     back = unpad(padded, 4)
     self.assertTrue(back == uh(b("1234567890")))
Esempio n. 9
0
 def test4(self):
     padded = pad(uh(b("1234567890")), 4, 'iso7816')
     self.assertTrue(padded == uh(b("1234567890800000")))
     back = unpad(padded, 4, 'iso7816')
     self.assertTrue(back == uh(b("1234567890")))
Esempio n. 10
0
 def test3(self):
     padded = pad(uh(b("123456")), 4, 'iso7816')
     self.assertTrue(padded == uh(b("12345680")))
     #import pdb; pdb.set_trace()
     back = unpad(padded, 4, 'iso7816')
     self.assertTrue(back == uh(b("123456")))
Esempio n. 11
0
 def test1(self):
     padded = pad(b(""), 4, 'iso7816')
     self.assertTrue(padded == uh(b("80000000")))
     back = unpad(padded, 4, 'iso7816')
     self.assertTrue(back == b(""))