def encode(data, marker, passphrase=None, randfunc=None): """Encode a piece of binary data into PEM format. :Parameters: 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: http://cvs.openssl.org/fileview?f=openssl/crypto/pem/pem.h&v=1.66.2.1.4.2 """ 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 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_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
def runTest(self): for pt, ct, key, prefix in self.bindata: counter = Counter.new(32, prefix=prefix) cipher = AES.new(key, AES.MODE_CTR, counter=counter) result = cipher.encrypt(pt) self.assertEqual(hexlify(ct), hexlify(result))