signature:
def _handshake ( self ) :
    """Perform an initial TLS handshake"""

implementation:
self . _ssl = None
self . _rbio = None
self . _wbio = None
try :
    self . _ssl = libssl . SSL_new ( self . _session . _ssl_ctx )
    if is_null ( self . _ssl ) :
        self . _ssl = None
        handle_openssl_error ( 0 )
    mem_bio = libssl . BIO_s_mem ( )
    self . _rbio = libssl . BIO_new ( mem_bio )
    if is_null ( self . _rbio ) :
        handle_openssl_error ( 0 )
    self . _wbio = libssl . BIO_new ( mem_bio )
    if is_null ( self . _wbio ) :
        handle_openssl_error ( 0 )
    libssl . SSL_set_bio ( self . _ssl , self . _rbio , self . _wbio )
    utf8_domain = self . _hostname . encode ( 'utf-8' )
    libssl . SSL_ctrl ( self . _ssl , LibsslConst . SSL_CTRL_SET_TLSEXT_HOSTNAME , LibsslConst . TLSEXT_NAMETYPE_host_name , utf8_domain )
    libssl . SSL_set_connect_state ( self . _ssl )
    if self . _session . _ssl_session :
        libssl . SSL_set_session ( self . _ssl , self . _session . _ssl_session )
    self . _bio_write_buffer = buffer_from_bytes ( self . _buffer_size )
    self . _read_buffer = buffer_from_bytes ( self . _buffer_size )
    handshake_server_bytes = b''
    handshake_client_bytes = b''
    while True :
        result = libssl . SSL_do_handshake ( self . _ssl )
        handshake_client_bytes += self . _raw_write ( )
        if result == 1 :
            break
        error = libssl . SSL_get_error ( self . _ssl , result )
        if error == LibsslConst . SSL_ERROR_WANT_READ :
            chunk = self . _raw_read ( )
            if chunk == b'' :
                if handshake_server_bytes == b'' :
                    raise_disconnection ( )
                if detect_client_auth_request ( handshake_server_bytes ) :
                    raise_client_auth ( )
                raise_protocol_error ( handshake_server_bytes )
            handshake_server_bytes += chunk
        elif error == LibsslConst . SSL_ERROR_WANT_WRITE :
            handshake_client_bytes += self . _raw_write ( )
        elif error == LibsslConst . SSL_ERROR_ZERO_RETURN :
            self . _gracefully_closed = True
            self . _shutdown ( False )
            self . _raise_closed ( )
        else :
            info = peek_openssl_error ( )
            if libcrypto_version_info < ( 1 , 1 ) :
                dh_key_info = ( 20 , LibsslConst . SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM , LibsslConst . SSL_R_DH_KEY_TOO_SMALL )
            else :
                dh_key_info = ( 20 , LibsslConst . SSL_F_TLS_PROCESS_SKE_DHE , LibsslConst . SSL_R_DH_KEY_TOO_SMALL )
            if info == dh_key_info :
                raise_dh_params ( )
            if libcrypto_version_info < ( 1 , 1 ) :
                unknown_protocol_info = ( 20 , LibsslConst . SSL_F_SSL23_GET_SERVER_HELLO , LibsslConst . SSL_R_UNKNOWN_PROTOCOL )
            else :
                unknown_protocol_info = ( 20 , LibsslConst . SSL_F_SSL3_GET_RECORD , LibsslConst . SSL_R_WRONG_VERSION_NUMBER )
            if info == unknown_protocol_info :
                raise_protocol_error ( handshake_server_bytes )
            tls_version_info_error = ( 20 , LibsslConst . SSL_F_SSL23_GET_SERVER_HELLO , LibsslConst . SSL_R_TLSV1_ALERT_PROTOCOL_VERSION )
            if info == tls_version_info_error :
                raise_protocol_version ( )
            handshake_error_info = ( 20 , LibsslConst . SSL_F_SSL23_GET_SERVER_HELLO , LibsslConst . SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE )
            if info == handshake_error_info :
                raise_handshake ( )
            handshake_failure_info = ( 20 , LibsslConst . SSL_F_SSL3_READ_BYTES , LibsslConst . SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE )
            if info == handshake_failure_info :
                raise_client_auth ( )
            if libcrypto_version_info < ( 1 , 1 ) :
                cert_verify_failed_info = ( 20 , LibsslConst . SSL_F_SSL3_GET_SERVER_CERTIFICATE , LibsslConst . SSL_R_CERTIFICATE_VERIFY_FAILED )
            else :
                cert_verify_failed_info = ( 20 , LibsslConst . SSL_F_TLS_PROCESS_SERVER_CERTIFICATE , LibsslConst . SSL_R_CERTIFICATE_VERIFY_FAILED )
            if info == cert_verify_failed_info :
                verify_result = libssl . SSL_get_verify_result ( self . _ssl )
                chain = extract_chain ( handshake_server_bytes )
                self_signed = False
                time_invalid = False
                no_issuer = False
                cert = None
                oscrypto_cert = None
                if chain :
                    cert = chain [ 0 ]
                    oscrypto_cert = load_certificate ( cert )
                    self_signed = oscrypto_cert . self_signed
                    issuer_error_codes = set ( [ LibsslConst . X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT , LibsslConst . X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN , LibsslConst . X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ] )
                    if verify_result in issuer_error_codes :
                        no_issuer = not self_signed
                    time_error_codes = set ( [ LibsslConst . X509_V_ERR_CERT_HAS_EXPIRED , LibsslConst . X509_V_ERR_CERT_NOT_YET_VALID ] )
                    time_invalid = verify_result in time_error_codes
                if time_invalid :
                    raise_expired_not_yet_valid ( cert )
                if no_issuer :
                    raise_no_issuer ( cert )
                if self_signed :
                    raise_self_signed ( cert )
                if oscrypto_cert and oscrypto_cert . asn1 . hash_algo in set ( [ 'md5' , 'md2' ] ) :
                    raise_weak_signature ( oscrypto_cert )
                raise_verification ( cert )
            handle_openssl_error ( 0 , TLSError )
    session_info = parse_session_info ( handshake_server_bytes , handshake_client_bytes )
    self . _protocol = session_info [ 'protocol' ]
    self . _cipher_suite = session_info [ 'cipher_suite' ]
    self . _compression = session_info [ 'compression' ]
    self . _session_id = session_info [ 'session_id' ]
    self . _session_ticket = session_info [ 'session_ticket' ]
    if self . _cipher_suite . find ( '_DHE_' ) != - 1 :
        dh_params_length = get_dh_params_length ( handshake_server_bytes )
        if dh_params_length < 1024 :
            self . close ( )
            raise_dh_params ( )
    # When saving the session for future requests , we use
    # SSL _ get1 _ session ( ) variant to increase the reference count . This
    # prevents the session from being freed when one connection closes
    # before another is opened . However , since we increase the ref
    # count , we also have to explicitly free any previous session .
    if self . _session_id == 'new' or self . _session_ticket == 'new' :
        if self . _session . _ssl_session :
            libssl . SSL_SESSION_free ( self . _session . _ssl_session )
        self . _session . _ssl_session = libssl . SSL_get1_session ( self . _ssl )
    if not self . _session . _manual_validation :
        if self . certificate . hash_algo in set ( [ 'md5' , 'md2' ] ) :
            raise_weak_signature ( self . certificate )
        # OpenSSL does not do hostname or IP address checking in the end
        # entity certificate , so we must perform that check
        if not self . certificate . is_valid_domain_ip ( self . _hostname ) :
            raise_hostname ( self . certificate , self . _hostname )
except ( OSError , socket_ . error ) :
    if self . _ssl :
        libssl . SSL_free ( self . _ssl )
        self . _ssl = None
        self . _rbio = None
        self . _wbio = None
    # The BIOs are freed by SSL _ free ( ) , so we only need to free
    # them if for some reason SSL _ free ( ) was not called
    else :
        if self . _rbio :
            libssl . BIO_free ( self . _rbio )
            self . _rbio = None
        if self . _wbio :
            libssl . BIO_free ( self . _wbio )
            self . _wbio = None
    self . close ( )
    raise


signature:
def _raw_read ( self ) :
    """Reads data from the socket and writes it to the memory bio
 used by libssl to decrypt the data . Returns the unencrypted
 data for the purpose of debugging handshakes .
 : return :
 A byte string of ciphertext from the socket . Used for
 debugging the handshake only ."""

implementation:
data = self . _raw_bytes
try :
    data += self . _socket . recv ( 8192 )
except ( socket_ . error ) :
    pass
output = data
written = libssl . BIO_write ( self . _rbio , data , len ( data ) )
self . _raw_bytes = data [ written : ]
return output


signature:
def _raw_write ( self ) :
    """Takes ciphertext from the memory bio and writes it to the
 socket .
 : return :
 A byte string of ciphertext going to the socket . Used
 for debugging the handshake only ."""

implementation:
data_available = libssl . BIO_ctrl_pending ( self . _wbio )
if data_available == 0 :
    return b''
to_read = min ( self . _buffer_size , data_available )
read = libssl . BIO_read ( self . _wbio , self . _bio_write_buffer , to_read )
to_write = bytes_from_buffer ( self . _bio_write_buffer , read )
output = to_write
while len ( to_write ) :
    raise_disconnect = False
    try :
        sent = self . _socket . send ( to_write )
    except ( socket_ . error ) as e : # Handle ECONNRESET and EPIPE
        if e . errno == 104 or e . errno == 32 :
            raise_disconnect = True
        else :
            raise
    if raise_disconnect :
        raise_disconnection ( )
    to_write = to_write [ sent : ]
    if len ( to_write ) :
        self . select_write ( )
return output


signature:
def read ( self , max_length ) :
    """Reads data from the TLS - wrapped socket
 : param max _ length :
 The number of bytes to read - output may be less than this
 : raises :
 socket . socket - when a non - TLS socket error occurs
 oscrypto . errors . TLSError - when a TLS - related error occurs
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the data read"""

implementation:
if not isinstance ( max_length , int_types ) :
    raise TypeError ( pretty_message ( '''
                max_length must be an integer, not %s
                ''' , type_name ( max_length ) ) )
buffered_length = len ( self . _decrypted_bytes )
# If we already have enough buffered data , just use that
if buffered_length >= max_length :
    output = self . _decrypted_bytes [ 0 : max_length ]
    self . _decrypted_bytes = self . _decrypted_bytes [ max_length : ]
    return output
if self . _ssl is None :
    self . _raise_closed ( )
# Don ' t block if we have buffered data available , since it is ok to
# return less than the max _ length
if buffered_length > 0 and not self . select_read ( 0 ) :
    output = self . _decrypted_bytes
    self . _decrypted_bytes = b''
    return output
# Only read enough to get the requested amount when
# combined with buffered data
to_read = min ( self . _buffer_size , max_length - buffered_length )
output = self . _decrypted_bytes
# The SSL _ read ( ) loop handles renegotiations , so we need to handle
# requests for both reads and writes
again = True
while again :
    again = False
    result = libssl . SSL_read ( self . _ssl , self . _read_buffer , to_read )
    self . _raw_write ( )
    if result <= 0 :
        error = libssl . SSL_get_error ( self . _ssl , result )
        if error == LibsslConst . SSL_ERROR_WANT_READ :
            if self . _raw_read ( ) != b'' :
                again = True
                continue
            raise_disconnection ( )
        elif error == LibsslConst . SSL_ERROR_WANT_WRITE :
            self . _raw_write ( )
            again = True
            continue
        elif error == LibsslConst . SSL_ERROR_ZERO_RETURN :
            self . _gracefully_closed = True
            self . _shutdown ( False )
            break
        else :
            handle_openssl_error ( 0 , TLSError )
    output += bytes_from_buffer ( self . _read_buffer , result )
if self . _gracefully_closed and len ( output ) == 0 :
    self . _raise_closed ( )
self . _decrypted_bytes = output [ max_length : ]
return output [ 0 : max_length ]


signature:
def write ( self , data ) :
    """Writes data to the TLS - wrapped socket
 : param data :
 A byte string to write to the socket
 : raises :
 socket . socket - when a non - TLS socket error occurs
 oscrypto . errors . TLSError - when a TLS - related error occurs
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library"""

implementation:
data_len = len ( data )
while data_len :
    if self . _ssl is None :
        self . _raise_closed ( )
    result = libssl . SSL_write ( self . _ssl , data , data_len )
    self . _raw_write ( )
    if result <= 0 :
        error = libssl . SSL_get_error ( self . _ssl , result )
        if error == LibsslConst . SSL_ERROR_WANT_READ :
            if self . _raw_read ( ) != b'' :
                continue
            raise_disconnection ( )
        elif error == LibsslConst . SSL_ERROR_WANT_WRITE :
            self . _raw_write ( )
            continue
        elif error == LibsslConst . SSL_ERROR_ZERO_RETURN :
            self . _gracefully_closed = True
            self . _shutdown ( False )
            self . _raise_closed ( )
        else :
            handle_openssl_error ( 0 , TLSError )
    data = data [ result : ]
    data_len = len ( data )


signature:
def _shutdown ( self , manual ) :
    """Shuts down the TLS session and then shuts down the underlying socket
 : param manual :
 A boolean if the connection was manually shutdown"""

implementation:
if self . _ssl is None :
    return
while True :
    result = libssl . SSL_shutdown ( self . _ssl )
    # Don ' t be noisy if the socket is already closed
    try :
        self . _raw_write ( )
    except ( TLSDisconnectError ) :
        pass
    if result >= 0 :
        break
    if result < 0 :
        error = libssl . SSL_get_error ( self . _ssl , result )
        if error == LibsslConst . SSL_ERROR_WANT_READ :
            if self . _raw_read ( ) != b'' :
                continue
            else :
                break
        elif error == LibsslConst . SSL_ERROR_WANT_WRITE :
            self . _raw_write ( )
            continue
        else :
            handle_openssl_error ( 0 , TLSError )
if manual :
    self . _local_closed = True
libssl . SSL_free ( self . _ssl )
self . _ssl = None
# BIOs are freed by SSL _ free ( )
self . _rbio = None
self . _wbio = None
try :
    self . _socket . shutdown ( socket_ . SHUT_RDWR )
except ( socket_ . error ) :
    pass


signature:
def _read_certificates ( self ) :
    """Reads end - entity and intermediate certificate information from the
 TLS session"""

implementation:
stack_pointer = libssl . SSL_get_peer_cert_chain ( self . _ssl )
if is_null ( stack_pointer ) :
    handle_openssl_error ( 0 , TLSError )
if libcrypto_version_info < ( 1 , 1 ) :
    number_certs = libssl . sk_num ( stack_pointer )
else :
    number_certs = libssl . OPENSSL_sk_num ( stack_pointer )
self . _intermediates = [ ]
for index in range ( 0 , number_certs ) :
    if libcrypto_version_info < ( 1 , 1 ) :
        x509_ = libssl . sk_value ( stack_pointer , index )
    else :
        x509_ = libssl . OPENSSL_sk_value ( stack_pointer , index )
    buffer_size = libcrypto . i2d_X509 ( x509_ , null ( ) )
    cert_buffer = buffer_from_bytes ( buffer_size )
    cert_pointer = buffer_pointer ( cert_buffer )
    cert_length = libcrypto . i2d_X509 ( x509_ , cert_pointer )
    handle_openssl_error ( cert_length )
    cert_data = bytes_from_buffer ( cert_buffer , cert_length )
    cert = x509 . Certificate . load ( cert_data )
    if index == 0 :
        self . _certificate = cert
    else :
        self . _intermediates . append ( cert )


signature:
def certificate ( self ) :
    """An asn1crypto . x509 . Certificate object of the end - entity certificate
 presented by the server"""

implementation:
if self . _ssl is None :
    self . _raise_closed ( )
if self . _certificate is None :
    self . _read_certificates ( )
return self . _certificate


signature:
def intermediates ( self ) :
    """A list of asn1crypto . x509 . Certificate objects that were presented as
 intermediates by the server"""

implementation:
if self . _ssl is None :
    self . _raise_closed ( )
if self . _certificate is None :
    self . _read_certificates ( )
return self . _intermediates


signature:
def aes_cbc_no_padding_encrypt ( key , data , iv ) :
    """Encrypts plaintext using AES in CBC mode with a 128 , 192 or 256 bit key and
 no padding . This means the ciphertext must be an exact multiple of 16 bytes
 long .
 : param key :
 The encryption key - a byte string either 16 , 24 or 32 bytes long
 : param data :
 The plaintext - a byte string
 : param iv :
 The initialization vector - either a byte string 16 - bytes long or None
 to generate an IV
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A tuple of two byte strings ( iv , ciphertext )"""

implementation:
if len ( key ) not in [ 16 , 24 , 32 ] :
    raise ValueError ( pretty_message ( '''
            key must be either 16, 24 or 32 bytes (128, 192 or 256 bits)
            long - is %s
            ''' , len ( key ) ) )
if not iv :
    iv = rand_bytes ( 16 )
elif len ( iv ) != 16 :
    raise ValueError ( pretty_message ( '''
            iv must be 16 bytes long - is %s
            ''' , len ( iv ) ) )
if len ( data ) % 16 != 0 :
    raise ValueError ( pretty_message ( '''
            data must be a multiple of 16 bytes long - is %s
            ''' , len ( data ) ) )
return ( iv , _encrypt ( 'aes' , key , data , iv , False ) )


signature:
def aes_cbc_no_padding_decrypt ( key , data , iv ) :
    """Decrypts AES ciphertext in CBC mode using a 128 , 192 or 256 bit key and no
 padding .
 : param key :
 The encryption key - a byte string either 16 , 24 or 32 bytes long
 : param data :
 The ciphertext - a byte string
 : param iv :
 The initialization vector - a byte string 16 - bytes long
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the plaintext"""

implementation:
if len ( key ) not in [ 16 , 24 , 32 ] :
    raise ValueError ( pretty_message ( '''
            key must be either 16, 24 or 32 bytes (128, 192 or 256 bits)
            long - is %s
            ''' , len ( key ) ) )
if len ( iv ) != 16 :
    raise ValueError ( pretty_message ( '''
            iv must be 16 bytes long - is %s
            ''' , len ( iv ) ) )
return _decrypt ( 'aes' , key , data , iv , False )


signature:
def tripledes_cbc_pkcs5_encrypt ( key , data , iv ) :
    """Encrypts plaintext using 3DES in either 2 or 3 key mode
 : param key :
 The encryption key - a byte string 16 or 24 bytes long ( 2 or 3 key mode )
 : param data :
 The plaintext - a byte string
 : param iv :
 The 8 - byte initialization vector to use - a byte string - set as None
 to generate an appropriate one
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A tuple of two byte strings ( iv , ciphertext )"""

implementation:
if len ( key ) != 16 and len ( key ) != 24 :
    raise ValueError ( pretty_message ( '''
            key must be 16 bytes (2 key) or 24 bytes (3 key) long - is %s
            ''' , len ( key ) ) )
if not iv :
    iv = rand_bytes ( 8 )
elif len ( iv ) != 8 :
    raise ValueError ( pretty_message ( '''
            iv must be 8 bytes long - is %s
            ''' , len ( iv ) ) )
cipher = 'tripledes_3key'
if len ( key ) == 16 :
    cipher = 'tripledes_2key'
return ( iv , _encrypt ( cipher , key , data , iv , True ) )


signature:
def _advapi32_create_handles ( cipher , key , iv ) :
    """Creates an HCRYPTPROV and HCRYPTKEY for symmetric encryption / decryption . The
 HCRYPTPROV must be released by close _ context _ handle ( ) and the
 HCRYPTKEY must be released by advapi32 . CryptDestroyKey ( ) when done .
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 A byte string of the symmetric key
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : return :
 A tuple of ( HCRYPTPROV , HCRYPTKEY )"""

implementation:
context_handle = None
if cipher == 'aes' :
    algorithm_id = { 16 : Advapi32Const . CALG_AES_128 , 24 : Advapi32Const . CALG_AES_192 , 32 : Advapi32Const . CALG_AES_256 , } [ len ( key ) ]
else :
    algorithm_id = { 'des' : Advapi32Const . CALG_DES , 'tripledes_2key' : Advapi32Const . CALG_3DES_112 , 'tripledes_3key' : Advapi32Const . CALG_3DES , 'rc2' : Advapi32Const . CALG_RC2 , 'rc4' : Advapi32Const . CALG_RC4 , } [ cipher ]
provider = Advapi32Const . MS_ENH_RSA_AES_PROV
context_handle = open_context_handle ( provider , verify_only = False )
blob_header_pointer = struct ( advapi32 , 'BLOBHEADER' )
blob_header = unwrap ( blob_header_pointer )
blob_header . bType = Advapi32Const . PLAINTEXTKEYBLOB
blob_header . bVersion = Advapi32Const . CUR_BLOB_VERSION
blob_header . reserved = 0
blob_header . aiKeyAlg = algorithm_id
blob_struct_pointer = struct ( advapi32 , 'PLAINTEXTKEYBLOB' )
blob_struct = unwrap ( blob_struct_pointer )
blob_struct . hdr = blob_header
blob_struct . dwKeySize = len ( key )
blob = struct_bytes ( blob_struct_pointer ) + key
flags = 0
if cipher in set ( [ 'rc2' , 'rc4' ] ) and len ( key ) == 5 :
    flags = Advapi32Const . CRYPT_NO_SALT
key_handle_pointer = new ( advapi32 , 'HCRYPTKEY *' )
res = advapi32 . CryptImportKey ( context_handle , blob , len ( blob ) , null ( ) , flags , key_handle_pointer )
handle_error ( res )
key_handle = unwrap ( key_handle_pointer )
if cipher == 'rc2' :
    buf = new ( advapi32 , 'DWORD *' , len ( key ) * 8 )
    res = advapi32 . CryptSetKeyParam ( key_handle , Advapi32Const . KP_EFFECTIVE_KEYLEN , buf , 0 )
    handle_error ( res )
if cipher != 'rc4' :
    res = advapi32 . CryptSetKeyParam ( key_handle , Advapi32Const . KP_IV , iv , 0 )
    handle_error ( res )
    buf = new ( advapi32 , 'DWORD *' , Advapi32Const . CRYPT_MODE_CBC )
    res = advapi32 . CryptSetKeyParam ( key_handle , Advapi32Const . KP_MODE , buf , 0 )
    handle_error ( res )
    buf = new ( advapi32 , 'DWORD *' , Advapi32Const . PKCS5_PADDING )
    res = advapi32 . CryptSetKeyParam ( key_handle , Advapi32Const . KP_PADDING , buf , 0 )
    handle_error ( res )
return ( context_handle , key_handle )


signature:
def _bcrypt_create_key_handle ( cipher , key ) :
    """Creates a BCRYPT _ KEY _ HANDLE for symmetric encryption / decryption . The
 handle must be released by bcrypt . BCryptDestroyKey ( ) when done .
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 A byte string of the symmetric key
 : return :
 A BCRYPT _ KEY _ HANDLE"""

implementation:
alg_handle = None
alg_constant = { 'aes' : BcryptConst . BCRYPT_AES_ALGORITHM , 'des' : BcryptConst . BCRYPT_DES_ALGORITHM , 'tripledes_2key' : BcryptConst . BCRYPT_3DES_112_ALGORITHM , 'tripledes_3key' : BcryptConst . BCRYPT_3DES_ALGORITHM , 'rc2' : BcryptConst . BCRYPT_RC2_ALGORITHM , 'rc4' : BcryptConst . BCRYPT_RC4_ALGORITHM , } [ cipher ]
try :
    alg_handle = open_alg_handle ( alg_constant )
    blob_type = BcryptConst . BCRYPT_KEY_DATA_BLOB
    blob_struct_pointer = struct ( bcrypt , 'BCRYPT_KEY_DATA_BLOB_HEADER' )
    blob_struct = unwrap ( blob_struct_pointer )
    blob_struct . dwMagic = BcryptConst . BCRYPT_KEY_DATA_BLOB_MAGIC
    blob_struct . dwVersion = BcryptConst . BCRYPT_KEY_DATA_BLOB_VERSION1
    blob_struct . cbKeyData = len ( key )
    blob = struct_bytes ( blob_struct_pointer ) + key
    if cipher == 'rc2' :
        buf = new ( bcrypt , 'DWORD *' , len ( key ) * 8 )
        res = bcrypt . BCryptSetProperty ( alg_handle , BcryptConst . BCRYPT_EFFECTIVE_KEY_LENGTH , buf , 4 , 0 )
        handle_error ( res )
    key_handle_pointer = new ( bcrypt , 'BCRYPT_KEY_HANDLE *' )
    res = bcrypt . BCryptImportKey ( alg_handle , null ( ) , blob_type , key_handle_pointer , null ( ) , 0 , blob , len ( blob ) , 0 )
    handle_error ( res )
    return unwrap ( key_handle_pointer )
finally :
    if alg_handle :
        close_alg_handle ( alg_handle )


signature:
def _encrypt ( cipher , key , data , iv , padding ) :
    """Encrypts plaintext
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 The encryption key - a byte string 5-16 bytes long
 : param data :
 The plaintext - a byte string
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : param padding :
 Boolean , if padding should be used - unused for RC4
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the ciphertext"""

implementation:
if not isinstance ( key , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            key must be a byte string, not %s
            ''' , type_name ( key ) ) )
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
if cipher != 'rc4' and not isinstance ( iv , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            iv must be a byte string, not %s
            ''' , type_name ( iv ) ) )
if cipher != 'rc4' and not padding :
    raise ValueError ( 'padding must be specified' )
if _backend == 'winlegacy' :
    return _advapi32_encrypt ( cipher , key , data , iv , padding )
return _bcrypt_encrypt ( cipher , key , data , iv , padding )


signature:
def _advapi32_encrypt ( cipher , key , data , iv , padding ) :
    """Encrypts plaintext via CryptoAPI
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 The encryption key - a byte string 5-16 bytes long
 : param data :
 The plaintext - a byte string
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : param padding :
 Boolean , if padding should be used - unused for RC4
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the ciphertext"""

implementation:
context_handle = None
key_handle = None
try :
    context_handle , key_handle = _advapi32_create_handles ( cipher , key , iv )
    out_len = new ( advapi32 , 'DWORD *' , len ( data ) )
    res = advapi32 . CryptEncrypt ( key_handle , null ( ) , True , 0 , null ( ) , out_len , 0 )
    handle_error ( res )
    buffer_len = deref ( out_len )
    buffer = buffer_from_bytes ( buffer_len )
    write_to_buffer ( buffer , data )
    pointer_set ( out_len , len ( data ) )
    res = advapi32 . CryptEncrypt ( key_handle , null ( ) , True , 0 , buffer , out_len , buffer_len )
    handle_error ( res )
    output = bytes_from_buffer ( buffer , deref ( out_len ) )
    # Remove padding when not required . CryptoAPI doesn ' t support this , so
    # we just manually remove it .
    if cipher == 'aes' and not padding :
        if output [ - 16 : ] != ( b'\x10' * 16 ) :
            raise ValueError ( 'Invalid padding generated by OS crypto library' )
        output = output [ : - 16 ]
    return output
finally :
    if key_handle :
        advapi32 . CryptDestroyKey ( key_handle )
    if context_handle :
        close_context_handle ( context_handle )


signature:
def _bcrypt_encrypt ( cipher , key , data , iv , padding ) :
    """Encrypts plaintext via CNG
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 The encryption key - a byte string 5-16 bytes long
 : param data :
 The plaintext - a byte string
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : param padding :
 Boolean , if padding should be used - unused for RC4
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the ciphertext"""

implementation:
key_handle = None
try :
    key_handle = _bcrypt_create_key_handle ( cipher , key )
    if iv is None :
        iv_len = 0
    else :
        iv_len = len ( iv )
    flags = 0
    if padding is True :
        flags = BcryptConst . BCRYPT_BLOCK_PADDING
    out_len = new ( bcrypt , 'ULONG *' )
    res = bcrypt . BCryptEncrypt ( key_handle , data , len ( data ) , null ( ) , null ( ) , 0 , null ( ) , 0 , out_len , flags )
    handle_error ( res )
    buffer_len = deref ( out_len )
    buffer = buffer_from_bytes ( buffer_len )
    iv_buffer = buffer_from_bytes ( iv ) if iv else null ( )
    res = bcrypt . BCryptEncrypt ( key_handle , data , len ( data ) , null ( ) , iv_buffer , iv_len , buffer , buffer_len , out_len , flags )
    handle_error ( res )
    return bytes_from_buffer ( buffer , deref ( out_len ) )
finally :
    if key_handle :
        bcrypt . BCryptDestroyKey ( key_handle )


signature:
def _decrypt ( cipher , key , data , iv , padding ) :
    """Decrypts AES / RC4 / RC2/3DES / DES ciphertext
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 The encryption key - a byte string 5-16 bytes long
 : param data :
 The ciphertext - a byte string
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : param padding :
 Boolean , if padding should be used - unused for RC4
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the plaintext"""

implementation:
if not isinstance ( key , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            key must be a byte string, not %s
            ''' , type_name ( key ) ) )
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
if cipher != 'rc4' and not isinstance ( iv , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            iv must be a byte string, not %s
            ''' , type_name ( iv ) ) )
if cipher != 'rc4' and padding is None :
    raise ValueError ( 'padding must be specified' )
if _backend == 'winlegacy' :
    return _advapi32_decrypt ( cipher , key , data , iv , padding )
return _bcrypt_decrypt ( cipher , key , data , iv , padding )


signature:
def _advapi32_decrypt ( cipher , key , data , iv , padding ) :
    """Decrypts AES / RC4 / RC2/3DES / DES ciphertext via CryptoAPI
 : param cipher :
 A unicode string of " aes " , " des " , " tripledes _ 2key " , " tripledes _ 3key " ,
 " rc2 " , " rc4"
 : param key :
 The encryption key - a byte string 5-16 bytes long
 : param data :
 The ciphertext - a byte string
 : param iv :
 The initialization vector - a byte string - unused for RC4
 : param padding :
 Boolean , if padding should be used - unused for RC4
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string of the plaintext"""

implementation:
context_handle = None
key_handle = None
try :
    context_handle , key_handle = _advapi32_create_handles ( cipher , key , iv )
    # Add removed padding when not required . CryptoAPI doesn ' t support no
    # padding , so we just add it back in
    if cipher == 'aes' and not padding :
        data += ( b'\x10' * 16 )
    buffer = buffer_from_bytes ( data )
    out_len = new ( advapi32 , 'DWORD *' , len ( data ) )
    res = advapi32 . CryptDecrypt ( key_handle , null ( ) , True , 0 , buffer , out_len )
    handle_error ( res )
    return bytes_from_buffer ( buffer , deref ( out_len ) )
finally :
    if key_handle :
        advapi32 . CryptDestroyKey ( key_handle )
    if context_handle :
        close_context_handle ( context_handle )


signature:
def handle_error ( error_num ) :
    """Extracts the last Windows error message into a python unicode string
 : param error _ num :
 The number to get the error string for
 : return :
 A unicode string error message"""

implementation:
if error_num == 0 :
    return
messages = { BcryptConst . STATUS_NOT_FOUND : 'The object was not found' , BcryptConst . STATUS_INVALID_PARAMETER : 'An invalid parameter was passed to a service or function' , BcryptConst . STATUS_NO_MEMORY : ( 'Not enough virtual memory or paging file quota is available to complete the specified operation' ) , BcryptConst . STATUS_INVALID_HANDLE : 'An invalid HANDLE was specified' , BcryptConst . STATUS_INVALID_SIGNATURE : 'The cryptographic signature is invalid' , BcryptConst . STATUS_NOT_SUPPORTED : 'The request is not supported' , BcryptConst . STATUS_BUFFER_TOO_SMALL : 'The buffer is too small to contain the entry' , BcryptConst . STATUS_INVALID_BUFFER_SIZE : 'The size of the buffer is invalid for the specified operation' , }
output = 'NTSTATUS error 0x%0.2X' % error_num
if error_num is not None and error_num in messages :
    output += ': ' + messages [ error_num ]
raise OSError ( output )


signature:
def handle_openssl_error ( result , exception_class = None ) :
    """Checks if an error occured , and if so throws an OSError containing the
 last OpenSSL error message
 : param result :
 An integer result code - 1 or greater indicates success
 : param exception _ class :
 The exception class to use for the exception if an error occurred
 : raises :
 OSError - when an OpenSSL error occurs"""

implementation:
if result > 0 :
    return
if exception_class is None :
    exception_class = OSError
error_num = libcrypto . ERR_get_error ( )
buffer = buffer_from_bytes ( 120 )
libcrypto . ERR_error_string ( error_num , buffer )
# Since we are dealing with a string , it is NULL terminated
error_string = byte_string_from_buffer ( buffer )
raise exception_class ( _try_decode ( error_string ) )


signature:
def peek_openssl_error ( ) :
    """Peeks into the error stack and pulls out the lib , func and reason
 : return :
 A three - element tuple of integers ( lib , func , reason )"""

implementation:
error = libcrypto . ERR_peek_error ( )
lib = int ( ( error >> 24 ) & 0xff )
func = int ( ( error >> 12 ) & 0xfff )
reason = int ( error & 0xfff )
return ( lib , func , reason )


signature:
def _is_osx_107 ( ) :
    """: return :
 A bool if the current machine is running OS X 10.7"""

implementation:
if sys . platform != 'darwin' :
    return False
version = platform . mac_ver ( ) [ 0 ]
return tuple ( map ( int , version . split ( '.' ) ) ) [ 0 : 2 ] == ( 10 , 7 )


signature:
def add_pss_padding ( hash_algorithm , salt_length , key_length , message ) :
    """Pads a byte string using the EMSA - PSS - Encode operation described in PKCS # 1
 v2.2.
 : param hash _ algorithm :
 The string name of the hash algorithm to use : " sha1 " , " sha224 " ,
 " sha256 " , " sha384 " , " sha512"
 : param salt _ length :
 The length of the salt as an integer - typically the same as the length
 of the output from the hash _ algorithm
 : param key _ length :
 The length of the RSA key , in bits
 : param message :
 A byte string of the message to pad
 : return :
 The encoded ( passed ) message"""

implementation:
if _backend != 'winlegacy' and sys . platform != 'darwin' :
    raise SystemError ( pretty_message ( '''
            Pure-python RSA PSS signature padding addition code is only for
            Windows XP/2003 and OS X
            ''' ) )
if not isinstance ( message , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            message must be a byte string, not %s
            ''' , type_name ( message ) ) )
if not isinstance ( salt_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            salt_length must be an integer, not %s
            ''' , type_name ( salt_length ) ) )
if salt_length < 0 :
    raise ValueError ( pretty_message ( '''
            salt_length must be 0 or more - is %s
            ''' , repr ( salt_length ) ) )
if not isinstance ( key_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            key_length must be an integer, not %s
            ''' , type_name ( key_length ) ) )
if key_length < 512 :
    raise ValueError ( pretty_message ( '''
            key_length must be 512 or more - is %s
            ''' , repr ( key_length ) ) )
if hash_algorithm not in set ( [ 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' ] ) :
    raise ValueError ( pretty_message ( '''
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            ''' , repr ( hash_algorithm ) ) )
hash_func = getattr ( hashlib , hash_algorithm )
# The maximal bit size of a non - negative integer is one less than the bit
# size of the key since the first bit is used to store sign
em_bits = key_length - 1
em_len = int ( math . ceil ( em_bits / 8 ) )
message_digest = hash_func ( message ) . digest ( )
hash_length = len ( message_digest )
if em_len < hash_length + salt_length + 2 :
    raise ValueError ( pretty_message ( '''
            Key is not long enough to use with specified hash_algorithm and
            salt_length
            ''' ) )
if salt_length > 0 :
    salt = os . urandom ( salt_length )
else :
    salt = b''
m_prime = ( b'\x00' * 8 ) + message_digest + salt
m_prime_digest = hash_func ( m_prime ) . digest ( )
padding = b'\x00' * ( em_len - salt_length - hash_length - 2 )
db = padding + b'\x01' + salt
db_mask = _mgf1 ( hash_algorithm , m_prime_digest , em_len - hash_length - 1 )
masked_db = int_to_bytes ( int_from_bytes ( db ) ^ int_from_bytes ( db_mask ) )
masked_db = fill_width ( masked_db , len ( db_mask ) )
zero_bits = ( 8 * em_len ) - em_bits
left_bit_mask = ( '0' * zero_bits ) + ( '1' * ( 8 - zero_bits ) )
left_int_mask = int ( left_bit_mask , 2 )
if left_int_mask != 255 :
    masked_db = chr_cls ( left_int_mask & ord ( masked_db [ 0 : 1 ] ) ) + masked_db [ 1 : ]
return masked_db + m_prime_digest + b'\xBC'


signature:
def verify_pss_padding ( hash_algorithm , salt_length , key_length , message , signature ) :
    """Verifies the PSS padding on an encoded message
 : param hash _ algorithm :
 The string name of the hash algorithm to use : " sha1 " , " sha224 " ,
 " sha256 " , " sha384 " , " sha512"
 : param salt _ length :
 The length of the salt as an integer - typically the same as the length
 of the output from the hash _ algorithm
 : param key _ length :
 The length of the RSA key , in bits
 : param message :
 A byte string of the message to pad
 : param signature :
 The signature to verify
 : return :
 A boolean indicating if the signature is invalid"""

implementation:
if _backend != 'winlegacy' and sys . platform != 'darwin' :
    raise SystemError ( pretty_message ( '''
            Pure-python RSA PSS signature padding verification code is only for
            Windows XP/2003 and OS X
            ''' ) )
if not isinstance ( message , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            message must be a byte string, not %s
            ''' , type_name ( message ) ) )
if not isinstance ( signature , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            signature must be a byte string, not %s
            ''' , type_name ( signature ) ) )
if not isinstance ( salt_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            salt_length must be an integer, not %s
            ''' , type_name ( salt_length ) ) )
if salt_length < 0 :
    raise ValueError ( pretty_message ( '''
            salt_length must be 0 or more - is %s
            ''' , repr ( salt_length ) ) )
if hash_algorithm not in set ( [ 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' ] ) :
    raise ValueError ( pretty_message ( '''
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            ''' , repr ( hash_algorithm ) ) )
hash_func = getattr ( hashlib , hash_algorithm )
em_bits = key_length - 1
em_len = int ( math . ceil ( em_bits / 8 ) )
message_digest = hash_func ( message ) . digest ( )
hash_length = len ( message_digest )
if em_len < hash_length + salt_length + 2 :
    return False
if signature [ - 1 : ] != b'\xBC' :
    return False
zero_bits = ( 8 * em_len ) - em_bits
masked_db_length = em_len - hash_length - 1
masked_db = signature [ 0 : masked_db_length ]
first_byte = ord ( masked_db [ 0 : 1 ] )
bits_that_should_be_zero = first_byte >> ( 8 - zero_bits )
if bits_that_should_be_zero != 0 :
    return False
m_prime_digest = signature [ masked_db_length : masked_db_length + hash_length ]
db_mask = _mgf1 ( hash_algorithm , m_prime_digest , em_len - hash_length - 1 )
left_bit_mask = ( '0' * zero_bits ) + ( '1' * ( 8 - zero_bits ) )
left_int_mask = int ( left_bit_mask , 2 )
if left_int_mask != 255 :
    db_mask = chr_cls ( left_int_mask & ord ( db_mask [ 0 : 1 ] ) ) + db_mask [ 1 : ]
db = int_to_bytes ( int_from_bytes ( masked_db ) ^ int_from_bytes ( db_mask ) )
if len ( db ) < len ( masked_db ) :
    db = ( b'\x00' * ( len ( masked_db ) - len ( db ) ) ) + db
zero_length = em_len - hash_length - salt_length - 2
zero_string = b'\x00' * zero_length
if not constant_compare ( db [ 0 : zero_length ] , zero_string ) :
    return False
if db [ zero_length : zero_length + 1 ] != b'\x01' :
    return False
salt = db [ 0 - salt_length : ]
m_prime = ( b'\x00' * 8 ) + message_digest + salt
h_prime = hash_func ( m_prime ) . digest ( )
return constant_compare ( m_prime_digest , h_prime )


signature:
def _mgf1 ( hash_algorithm , seed , mask_length ) :
    """The PKCS # 1 MGF1 mask generation algorithm
 : param hash _ algorithm :
 The string name of the hash algorithm to use : " sha1 " , " sha224 " ,
 " sha256 " , " sha384 " , " sha512"
 : param seed :
 A byte string to use as the seed for the mask
 : param mask _ length :
 The desired mask length , as an integer
 : return :
 A byte string of the mask"""

implementation:
if not isinstance ( seed , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            seed must be a byte string, not %s
            ''' , type_name ( seed ) ) )
if not isinstance ( mask_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            mask_length must be an integer, not %s
            ''' , type_name ( mask_length ) ) )
if mask_length < 1 :
    raise ValueError ( pretty_message ( '''
            mask_length must be greater than 0 - is %s
            ''' , repr ( mask_length ) ) )
if hash_algorithm not in set ( [ 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' ] ) :
    raise ValueError ( pretty_message ( '''
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            ''' , repr ( hash_algorithm ) ) )
output = b''
hash_length = { 'sha1' : 20 , 'sha224' : 28 , 'sha256' : 32 , 'sha384' : 48 , 'sha512' : 64 } [ hash_algorithm ]
iterations = int ( math . ceil ( mask_length / hash_length ) )
pack = struct . Struct ( b'>I' ) . pack
hash_func = getattr ( hashlib , hash_algorithm )
for counter in range ( 0 , iterations ) :
    b = pack ( counter )
    output += hash_func ( seed + b ) . digest ( )
return output [ 0 : mask_length ]


signature:
def _add_pkcs1v15_padding ( key_length , data , operation ) :
    """Adds PKCS # 1 v1.5 padding to a message
 : param key _ length :
 An integer of the number of bytes in the key
 : param data :
 A byte string to unpad
 : param operation :
 A unicode string of " encrypting " or " signing "
 : return :
 The padded data as a byte string"""

implementation:
if operation == 'encrypting' :
    second_byte = b'\x02'
else :
    second_byte = b'\x01'
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
if not isinstance ( key_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            key_length must be an integer, not %s
            ''' , type_name ( key_length ) ) )
if key_length < 64 :
    raise ValueError ( pretty_message ( '''
            key_length must be 64 or more - is %s
            ''' , repr ( key_length ) ) )
if len ( data ) > key_length - 11 :
    raise ValueError ( pretty_message ( '''
            data must be between 1 and %s bytes long - is %s
            ''' , key_length - 11 , len ( data ) ) )
required_bytes = key_length - 3 - len ( data )
padding = b''
while required_bytes > 0 :
    temp_padding = rand_bytes ( required_bytes )
    # Remove null bytes since they are markers in PKCS # 1 v1.5
    temp_padding = b'' . join ( temp_padding . split ( b'\x00' ) )
    padding += temp_padding
    required_bytes -= len ( temp_padding )
return b'\x00' + second_byte + padding + b'\x00' + data


signature:
def _remove_pkcs1v15_padding ( key_length , data , operation ) :
    """Removes PKCS # 1 v1.5 padding from a message using constant time operations
 : param key _ length :
 An integer of the number of bytes in the key
 : param data :
 A byte string to unpad
 : param operation :
 A unicode string of " decrypting " or " verifying "
 : return :
 The unpadded data as a byte string"""

implementation:
if operation == 'decrypting' :
    second_byte = 2
else :
    second_byte = 1
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
if not isinstance ( key_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            key_length must be an integer, not %s
            ''' , type_name ( key_length ) ) )
if key_length < 64 :
    raise ValueError ( pretty_message ( '''
            key_length must be 64 or more - is %s
            ''' , repr ( key_length ) ) )
if len ( data ) != key_length :
    raise ValueError ( 'Error %s' % operation )
error = 0
trash = 0
padding_end = 0
# Uses bitwise operations on an error variable and another trash variable
# to perform constant time error checking / token scanning on the data
for i in range ( 0 , len ( data ) ) :
    byte = data [ i : i + 1 ]
    byte_num = ord ( byte )
    # First byte should be \ x00
    if i == 0 :
        error |= byte_num
    # Second byte should be \ x02 for decryption , \ x01 for verification
    elif i == 1 :
        error |= int ( ( byte_num | second_byte ) != second_byte )
    # Bytes 3-10 should not be \ x00
    elif i < 10 :
        error |= int ( ( byte_num ^ 0 ) == 0 )
    # Byte 11 or after that is zero is end of padding
    else :
        non_zero = byte_num | 0
        if padding_end == 0 :
            if non_zero :
                trash |= i
            else :
                padding_end |= i
        else :
            if non_zero :
                trash |= i
            else :
                trash |= i
if error != 0 :
    raise ValueError ( 'Error %s' % operation )
return data [ padding_end + 1 : ]


signature:
def raw_rsa_private_crypt ( private_key , data ) :
    """Performs a raw RSA algorithm in a byte string using a private key .
 This is a low - level primitive and is prone to disastrous results if used
 incorrectly .
 : param private _ key :
 An oscrypto . asymmetric . PrivateKey object
 : param data :
 A byte string of the plaintext to be signed or ciphertext to be
 decrypted . Must be less than or equal to the length of the private key .
 In the case of signing , padding must already be applied . In the case of
 decryption , padding must be removed afterward .
 : return :
 A byte string of the transformed data"""

implementation:
if _backend != 'winlegacy' :
    raise SystemError ( 'Pure-python RSA crypt is only for Windows XP/2003' )
if not hasattr ( private_key , 'asn1' ) or not isinstance ( private_key . asn1 , PrivateKeyInfo ) :
    raise TypeError ( pretty_message ( '''
            private_key must be an instance of the
            oscrypto.asymmetric.PrivateKey class, not %s
            ''' , type_name ( private_key ) ) )
algo = private_key . asn1 [ 'private_key_algorithm' ] [ 'algorithm' ] . native
if algo != 'rsa' :
    raise ValueError ( pretty_message ( '''
            private_key must be an RSA key, not %s
            ''' , algo . upper ( ) ) )
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
rsa_private_key = private_key . asn1 [ 'private_key' ] . parsed
transformed_int = pow ( int_from_bytes ( data ) , rsa_private_key [ 'private_exponent' ] . native , rsa_private_key [ 'modulus' ] . native )
return int_to_bytes ( transformed_int , width = private_key . asn1 . byte_size )


signature:
def raw_rsa_public_crypt ( certificate_or_public_key , data ) :
    """Performs a raw RSA algorithm in a byte string using a certificate or
 public key . This is a low - level primitive and is prone to disastrous results
 if used incorrectly .
 : param certificate _ or _ public _ key :
 An oscrypto . asymmetric . PublicKey or oscrypto . asymmetric . Certificate
 object
 : param data :
 A byte string of the signature when verifying , or padded plaintext when
 encrypting . Must be less than or equal to the length of the public key .
 When verifying , padding will need to be removed afterwards . When
 encrypting , padding must be applied before .
 : return :
 A byte string of the transformed data"""

implementation:
if _backend != 'winlegacy' :
    raise SystemError ( 'Pure-python RSA crypt is only for Windows XP/2003' )
has_asn1 = hasattr ( certificate_or_public_key , 'asn1' )
valid_types = ( PublicKeyInfo , Certificate )
if not has_asn1 or not isinstance ( certificate_or_public_key . asn1 , valid_types ) :
    raise TypeError ( pretty_message ( '''
            certificate_or_public_key must be an instance of the
            oscrypto.asymmetric.PublicKey or oscrypto.asymmetric.Certificate
            classes, not %s
            ''' , type_name ( certificate_or_public_key ) ) )
algo = certificate_or_public_key . asn1 [ 'algorithm' ] [ 'algorithm' ] . native
if algo != 'rsa' :
    raise ValueError ( pretty_message ( '''
            certificate_or_public_key must be an RSA key, not %s
            ''' , algo . upper ( ) ) )
if not isinstance ( data , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            data must be a byte string, not %s
            ''' , type_name ( data ) ) )
rsa_public_key = certificate_or_public_key . asn1 [ 'public_key' ] . parsed
transformed_int = pow ( int_from_bytes ( data ) , rsa_public_key [ 'public_exponent' ] . native , rsa_public_key [ 'modulus' ] . native )
return int_to_bytes ( transformed_int , width = certificate_or_public_key . asn1 . byte_size )


signature:
def pkcs12_kdf ( hash_algorithm , password , salt , iterations , key_length , id_ ) :
    """KDF from RFC7292 appendix B . 2 - https : / / tools . ietf . org / html / rfc7292 # page - 19
 : param hash _ algorithm :
 The string name of the hash algorithm to use : " md5 " , " sha1 " , " sha224 " , " sha256 " , " sha384 " , " sha512"
 : param password :
 A byte string of the password to use an input to the KDF
 : param salt :
 A cryptographic random byte string
 : param iterations :
 The numbers of iterations to use when deriving the key
 : param key _ length :
 The length of the desired key in bytes
 : param id _ :
 The ID of the usage - 1 for key , 2 for iv , 3 for mac
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 : return :
 The derived key as a byte string"""

implementation:
if not isinstance ( password , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            password must be a byte string, not %s
            ''' , type_name ( password ) ) )
if not isinstance ( salt , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            salt must be a byte string, not %s
            ''' , type_name ( salt ) ) )
if not isinstance ( iterations , int_types ) :
    raise TypeError ( pretty_message ( '''
            iterations must be an integer, not %s
            ''' , type_name ( iterations ) ) )
if iterations < 1 :
    raise ValueError ( pretty_message ( '''
            iterations must be greater than 0 - is %s
            ''' , repr ( iterations ) ) )
if not isinstance ( key_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            key_length must be an integer, not %s
            ''' , type_name ( key_length ) ) )
if key_length < 1 :
    raise ValueError ( pretty_message ( '''
            key_length must be greater than 0 - is %s
            ''' , repr ( key_length ) ) )
if hash_algorithm not in set ( [ 'md5' , 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' ] ) :
    raise ValueError ( pretty_message ( '''
            hash_algorithm must be one of "md5", "sha1", "sha224", "sha256",
            "sha384", "sha512", not %s
            ''' , repr ( hash_algorithm ) ) )
if id_ not in set ( [ 1 , 2 , 3 ] ) :
    raise ValueError ( pretty_message ( '''
            id_ must be one of 1, 2, 3, not %s
            ''' , repr ( id_ ) ) )
utf16_password = password . decode ( 'utf-8' ) . encode ( 'utf-16be' ) + b'\x00\x00'
digest_type = { 'md5' : libcrypto . EVP_md5 , 'sha1' : libcrypto . EVP_sha1 , 'sha224' : libcrypto . EVP_sha224 , 'sha256' : libcrypto . EVP_sha256 , 'sha384' : libcrypto . EVP_sha384 , 'sha512' : libcrypto . EVP_sha512 , } [ hash_algorithm ] ( )
output_buffer = buffer_from_bytes ( key_length )
result = libcrypto . PKCS12_key_gen_uni ( utf16_password , len ( utf16_password ) , salt , len ( salt ) , id_ , iterations , key_length , output_buffer , digest_type )
handle_openssl_error ( result )
return bytes_from_buffer ( output_buffer )


signature:
def extract_from_system ( cert_callback = None , callback_only_on_failure = False ) :
    """Extracts trusted CA certificates from the OS X trusted root keychain .
 : param cert _ callback :
 A callback that is called once for each certificate in the trust store .
 It should accept two parameters : an asn1crypto . x509 . Certificate object ,
 and a reason . The reason will be None if the certificate is being
 exported , otherwise it will be a unicode string of the reason it won ' t .
 : param callback _ only _ on _ failure :
 A boolean - if the callback should only be called when a certificate is
 not exported .
 : raises :
 OSError - when an error is returned by the OS crypto library
 : return :
 A list of 3 - element tuples :
 - 0 : a byte string of a DER - encoded certificate
 - 1 : a set of unicode strings that are OIDs of purposes to trust the
 certificate for
 - 2 : a set of unicode strings that are OIDs of purposes to reject the
 certificate for"""

implementation:
certs_pointer_pointer = new ( CoreFoundation , 'CFArrayRef *' )
res = Security . SecTrustCopyAnchorCertificates ( certs_pointer_pointer )
handle_sec_error ( res )
certs_pointer = unwrap ( certs_pointer_pointer )
certificates = { }
trust_info = { }
all_purposes = '2.5.29.37.0'
default_trust = ( set ( ) , set ( ) )
length = CoreFoundation . CFArrayGetCount ( certs_pointer )
for index in range ( 0 , length ) :
    cert_pointer = CoreFoundation . CFArrayGetValueAtIndex ( certs_pointer , index )
    der_cert , cert_hash = _cert_details ( cert_pointer )
    certificates [ cert_hash ] = der_cert
CoreFoundation . CFRelease ( certs_pointer )
for domain in [ SecurityConst . kSecTrustSettingsDomainUser , SecurityConst . kSecTrustSettingsDomainAdmin ] :
    cert_trust_settings_pointer_pointer = new ( CoreFoundation , 'CFArrayRef *' )
    res = Security . SecTrustSettingsCopyCertificates ( domain , cert_trust_settings_pointer_pointer )
    if res == SecurityConst . errSecNoTrustSettings :
        continue
    handle_sec_error ( res )
    cert_trust_settings_pointer = unwrap ( cert_trust_settings_pointer_pointer )
    length = CoreFoundation . CFArrayGetCount ( cert_trust_settings_pointer )
    for index in range ( 0 , length ) :
        cert_pointer = CoreFoundation . CFArrayGetValueAtIndex ( cert_trust_settings_pointer , index )
        trust_settings_pointer_pointer = new ( CoreFoundation , 'CFArrayRef *' )
        res = Security . SecTrustSettingsCopyTrustSettings ( cert_pointer , domain , trust_settings_pointer_pointer )
        # In OS X 10.11 , this value started being seen . From the comments in
        # the Security Framework Reference , the lack of any settings should
        # indicate " always trust this certificate "
        if res == SecurityConst . errSecItemNotFound :
            continue
        # If the trust settings for a certificate are invalid , we need to
        # assume the certificate should not be trusted
        if res == SecurityConst . errSecInvalidTrustSettings :
            der_cert , cert_hash = _cert_details ( cert_pointer )
            if cert_hash in certificates :
                _cert_callback ( cert_callback , certificates [ cert_hash ] , 'invalid trust settings' )
                del certificates [ cert_hash ]
            continue
        handle_sec_error ( res )
        trust_settings_pointer = unwrap ( trust_settings_pointer_pointer )
        trust_oids = set ( )
        reject_oids = set ( )
        settings_length = CoreFoundation . CFArrayGetCount ( trust_settings_pointer )
        for settings_index in range ( 0 , settings_length ) :
            settings_dict_entry = CoreFoundation . CFArrayGetValueAtIndex ( trust_settings_pointer , settings_index )
            settings_dict = CFHelpers . cf_dictionary_to_dict ( settings_dict_entry )
            # No policy OID means the trust result is for all purposes
            policy_oid = settings_dict . get ( 'kSecTrustSettingsPolicy' , { } ) . get ( 'SecPolicyOid' , all_purposes )
            # 0 = kSecTrustSettingsResultInvalid
            # 1 = kSecTrustSettingsResultTrustRoot
            # 2 = kSecTrustSettingsResultTrustAsRoot
            # 3 = kSecTrustSettingsResultDeny
            # 4 = kSecTrustSettingsResultUnspecified
            trust_result = settings_dict . get ( 'kSecTrustSettingsResult' , 1 )
            should_trust = trust_result != 0 and trust_result != 3
            if should_trust :
                trust_oids . add ( policy_oid )
            else :
                reject_oids . add ( policy_oid )
        der_cert , cert_hash = _cert_details ( cert_pointer )
        # If rejected for all purposes , we don ' t export the certificate
        if all_purposes in reject_oids :
            if cert_hash in certificates :
                _cert_callback ( cert_callback , certificates [ cert_hash ] , 'explicitly distrusted' )
                del certificates [ cert_hash ]
        else :
            if all_purposes in trust_oids :
                trust_oids = set ( [ all_purposes ] )
            trust_info [ cert_hash ] = ( trust_oids , reject_oids )
        CoreFoundation . CFRelease ( trust_settings_pointer )
    CoreFoundation . CFRelease ( cert_trust_settings_pointer )
output = [ ]
for cert_hash in certificates :
    if not callback_only_on_failure :
        _cert_callback ( cert_callback , certificates [ cert_hash ] , None )
    cert_trust_info = trust_info . get ( cert_hash , default_trust )
    output . append ( ( certificates [ cert_hash ] , cert_trust_info [ 0 ] , cert_trust_info [ 1 ] ) )
return output


signature:
def _cert_callback ( callback , der_cert , reason ) :
    """Constructs an asn1crypto . x509 . Certificate object and calls the export
 callback
 : param callback :
 The callback to call
 : param der _ cert :
 A byte string of the DER - encoded certificate
 : param reason :
 None if cert is being exported , or a unicode string of the reason it
 is not being exported"""

implementation:
if not callback :
    return
callback ( x509 . Certificate . load ( der_cert ) , reason )


signature:
def _cert_details ( cert_pointer ) :
    """Return the certificate and a hash of it
 : param cert _ pointer :
 A SecCertificateRef
 : return :
 A 2 - element tuple :
 - [ 0 ] : A byte string of the SHA1 hash of the cert
 - [ 1 ] : A byte string of the DER - encoded contents of the cert"""

implementation:
data_pointer = None
try :
    data_pointer = Security . SecCertificateCopyData ( cert_pointer )
    der_cert = CFHelpers . cf_data_to_bytes ( data_pointer )
    cert_hash = hashlib . sha1 ( der_cert ) . digest ( )
    return ( der_cert , cert_hash )
finally :
    if data_pointer is not None :
        CoreFoundation . CFRelease ( data_pointer )


signature:
def _extract_error ( ) :
    """Extracts the last OS error message into a python unicode string
 : return :
 A unicode string error message"""

implementation:
error_num = errno ( )
try :
    error_string = os . strerror ( error_num )
except ( ValueError ) :
    return str_cls ( error_num )
if isinstance ( error_string , str_cls ) :
    return error_string
return _try_decode ( error_string )


signature:
def pbkdf2 ( hash_algorithm , password , salt , iterations , key_length ) :
    """PBKDF2 from PKCS # 5
 : param hash _ algorithm :
 The string name of the hash algorithm to use : " sha1 " , " sha224 " , " sha256 " , " sha384 " , " sha512"
 : param password :
 A byte string of the password to use an input to the KDF
 : param salt :
 A cryptographic random byte string
 : param iterations :
 The numbers of iterations to use when deriving the key
 : param key _ length :
 The length of the desired key in bytes
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 The derived key as a byte string"""

implementation:
if not isinstance ( password , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            password must be a byte string, not %s
            ''' , type_name ( password ) ) )
if not isinstance ( salt , byte_cls ) :
    raise TypeError ( pretty_message ( '''
            salt must be a byte string, not %s
            ''' , type_name ( salt ) ) )
if not isinstance ( iterations , int_types ) :
    raise TypeError ( pretty_message ( '''
            iterations must be an integer, not %s
            ''' , type_name ( iterations ) ) )
if iterations < 1 :
    raise ValueError ( 'iterations must be greater than 0' )
if not isinstance ( key_length , int_types ) :
    raise TypeError ( pretty_message ( '''
            key_length must be an integer, not %s
            ''' , type_name ( key_length ) ) )
if key_length < 1 :
    raise ValueError ( 'key_length must be greater than 0' )
if hash_algorithm not in set ( [ 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' ] ) :
    raise ValueError ( pretty_message ( '''
            hash_algorithm must be one of "sha1", "sha224", "sha256", "sha384",
            "sha512", not %s
            ''' , repr ( hash_algorithm ) ) )
algo = { 'sha1' : CommonCryptoConst . kCCPRFHmacAlgSHA1 , 'sha224' : CommonCryptoConst . kCCPRFHmacAlgSHA224 , 'sha256' : CommonCryptoConst . kCCPRFHmacAlgSHA256 , 'sha384' : CommonCryptoConst . kCCPRFHmacAlgSHA384 , 'sha512' : CommonCryptoConst . kCCPRFHmacAlgSHA512 } [ hash_algorithm ]
output_buffer = buffer_from_bytes ( key_length )
result = CommonCrypto . CCKeyDerivationPBKDF ( CommonCryptoConst . kCCPBKDF2 , password , len ( password ) , salt , len ( salt ) , algo , iterations , output_buffer , key_length )
if result != 0 :
    raise OSError ( _extract_error ( ) )
return bytes_from_buffer ( output_buffer )


signature:
def rand_bytes ( length ) :
    """Returns a number of random bytes suitable for cryptographic purposes
 : param length :
 The desired number of bytes
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 OSError - when an error is returned by the OS crypto library
 : return :
 A byte string"""

implementation:
if not isinstance ( length , int_types ) :
    raise TypeError ( pretty_message ( '''
            length must be an integer, not %s
            ''' , type_name ( length ) ) )
if length < 1 :
    raise ValueError ( 'length must be greater than 0' )
if length > 1024 :
    raise ValueError ( 'length must not be greater than 1024' )
buffer = buffer_from_bytes ( length )
result = Security . SecRandomCopyBytes ( Security . kSecRandomDefault , length , buffer )
if result != 0 :
    raise OSError ( _extract_error ( ) )
return bytes_from_buffer ( buffer )


signature:
def cf_number_to_number ( value ) :
    """Converts a CFNumber object to a python float or integer
 : param value :
 The CFNumber object
 : return :
 A python number ( float or integer )"""

implementation:
type_ = CoreFoundation . CFNumberGetType ( _cast_pointer_p ( value ) )
c_type = { 1 : c_byte , # kCFNumberSInt8Type
2 : ctypes . c_short , # kCFNumberSInt16Type
3 : ctypes . c_int32 , # kCFNumberSInt32Type
4 : ctypes . c_int64 , # kCFNumberSInt64Type
5 : ctypes . c_float , # kCFNumberFloat32Type
6 : ctypes . c_double , # kCFNumberFloat64Type
7 : c_byte , # kCFNumberCharType
8 : ctypes . c_short , # kCFNumberShortType
9 : ctypes . c_int , # kCFNumberIntType
10 : c_long , # kCFNumberLongType
11 : ctypes . c_longlong , # kCFNumberLongLongType
12 : ctypes . c_float , # kCFNumberFloatType
13 : ctypes . c_double , # kCFNumberDoubleType
14 : c_long , # kCFNumberCFIndexType
15 : ctypes . c_int , # kCFNumberNSIntegerType
16 : ctypes . c_double , # kCFNumberCGFloatType
} [ type_ ]
output = c_type ( 0 )
CoreFoundation . CFNumberGetValue ( _cast_pointer_p ( value ) , type_ , byref ( output ) )
return output . value


signature:
def cf_dictionary_to_dict ( dictionary ) :
    """Converts a CFDictionary object into a python dictionary
 : param dictionary :
 The CFDictionary to convert
 : return :
 A python dict"""

implementation:
dict_length = CoreFoundation . CFDictionaryGetCount ( dictionary )
keys = ( CFTypeRef * dict_length ) ( )
values = ( CFTypeRef * dict_length ) ( )
CoreFoundation . CFDictionaryGetKeysAndValues ( dictionary , _cast_pointer_p ( keys ) , _cast_pointer_p ( values ) )
output = { }
for index in range ( 0 , dict_length ) :
    output [ CFHelpers . native ( keys [ index ] ) ] = CFHelpers . native ( values [ index ] )
return output


signature:
def native ( cls , value ) :
    """Converts a CF * object into its python equivalent
 : param value :
 The CF * object to convert
 : return :
 The native python object"""

implementation:
type_id = CoreFoundation . CFGetTypeID ( value )
if type_id in cls . _native_map :
    return cls . _native_map [ type_id ] ( value )
else :
    return value


signature:
def cf_string_to_unicode ( value ) :
    """Creates a python unicode string from a CFString object
 : param value :
 The CFString to convert
 : return :
 A python unicode string"""

implementation:
string = CoreFoundation . CFStringGetCStringPtr ( _cast_pointer_p ( value ) , kCFStringEncodingUTF8 )
if string is None :
    buffer = buffer_from_bytes ( 1024 )
    result = CoreFoundation . CFStringGetCString ( _cast_pointer_p ( value ) , buffer , 1024 , kCFStringEncodingUTF8 )
    if not result :
        raise OSError ( 'Error copying C string from CFStringRef' )
    string = byte_string_from_buffer ( buffer )
if string is not None :
    string = string . decode ( 'utf-8' )
return string


signature:
def cf_data_to_bytes ( value ) :
    """Extracts a bytestring from a CFData object
 : param value :
 A CFData object
 : return :
 A byte string"""

implementation:
start = CoreFoundation . CFDataGetBytePtr ( value )
num_bytes = CoreFoundation . CFDataGetLength ( value )
return string_at ( start , num_bytes )


signature:
def cf_dictionary_from_pairs ( pairs ) :
    """Creates a CFDictionaryRef object from a list of 2 - element tuples
 representing the key and value . Each key should be a CFStringRef and each
 value some sort of CF * type .
 : param pairs :
 A list of 2 - element tuples
 : return :
 A CFDictionaryRef"""

implementation:
length = len ( pairs )
keys = [ ]
values = [ ]
for pair in pairs :
    key , value = pair
    keys . append ( key )
    values . append ( value )
keys = ( CFStringRef * length ) ( * keys )
values = ( CFTypeRef * length ) ( * values )
return CoreFoundation . CFDictionaryCreate ( CoreFoundation . kCFAllocatorDefault , _cast_pointer_p ( byref ( keys ) ) , _cast_pointer_p ( byref ( values ) ) , length , kCFTypeDictionaryKeyCallBacks , kCFTypeDictionaryValueCallBacks )


signature:
def cf_array_from_list ( values ) :
    """Creates a CFArrayRef object from a list of CF * type objects .
 : param values :
 A list of CF * type object
 : return :
 A CFArrayRef"""

implementation:
length = len ( values )
values = ( CFTypeRef * length ) ( * values )
return CoreFoundation . CFArrayCreate ( CoreFoundation . kCFAllocatorDefault , _cast_pointer_p ( byref ( values ) ) , length , kCFTypeArrayCallBacks )


signature:
def cf_number_from_integer ( integer ) :
    """Creates a CFNumber object from an integer
 : param integer :
 The integer to create the CFNumber for
 : return :
 A CFNumber"""

implementation:
integer_as_long = c_long ( integer )
return CoreFoundation . CFNumberCreate ( CoreFoundation . kCFAllocatorDefault , kCFNumberCFIndexType , byref ( integer_as_long ) )


implementation:
type_ = CoreFoundation . CFNumberGetType ( value )
type_name_ = { 1 : 'int8_t' , # kCFNumberSInt8Type
2 : 'in16_t' , # kCFNumberSInt16Type
3 : 'int32_t' , # kCFNumberSInt32Type
4 : 'int64_t' , # kCFNumberSInt64Type
5 : 'float' , # kCFNumberFloat32Type
6 : 'double' , # kCFNumberFloat64Type
7 : 'char' , # kCFNumberCharType
8 : 'short' , # kCFNumberShortType
9 : 'int' , # kCFNumberIntType
10 : 'long' , # kCFNumberLongType
11 : 'long long' , # kCFNumberLongLongType
12 : 'float' , # kCFNumberFloatType
13 : 'double' , # kCFNumberDoubleType
14 : 'long' , # kCFNumberCFIndexType
15 : 'int' , # kCFNumberNSIntegerType
16 : 'double' , # kCFNumberCGFloatType
} [ type_ ]
output = new ( CoreFoundation , type_name_ + ' *' )
CoreFoundation . CFNumberGetValue ( value , type_ , output )
return deref ( output )


implementation:
string_ptr = CoreFoundation . CFStringGetCStringPtr ( value , kCFStringEncodingUTF8 )
string = None if is_null ( string_ptr ) else ffi . string ( string_ptr )
if string is None :
    buffer = buffer_from_bytes ( 1024 )
    result = CoreFoundation . CFStringGetCString ( value , buffer , 1024 , kCFStringEncodingUTF8 )
    if not result :
        raise OSError ( 'Error copying C string from CFStringRef' )
    string = byte_string_from_buffer ( buffer )
if string is not None :
    string = string . decode ( 'utf-8' )
return string


implementation:
start = CoreFoundation . CFDataGetBytePtr ( value )
num_bytes = CoreFoundation . CFDataGetLength ( value )
return ffi . buffer ( start , num_bytes ) [ : ]


implementation:
length = len ( pairs )
keys = [ ]
values = [ ]
for pair in pairs :
    key , value = pair
    keys . append ( key )
    values . append ( value )
return CoreFoundation . CFDictionaryCreate ( CoreFoundation . kCFAllocatorDefault , keys , values , length , ffi . addressof ( CoreFoundation . kCFTypeDictionaryKeyCallBacks ) , ffi . addressof ( CoreFoundation . kCFTypeDictionaryValueCallBacks ) )


implementation:
length = len ( values )
return CoreFoundation . CFArrayCreate ( CoreFoundation . kCFAllocatorDefault , values , length , ffi . addressof ( CoreFoundation . kCFTypeArrayCallBacks ) )


implementation:
integer_as_long = ffi . new ( 'long *' , integer )
return CoreFoundation . CFNumberCreate ( CoreFoundation . kCFAllocatorDefault , kCFNumberCFIndexType , integer_as_long )


signature:
def dump_dh_parameters ( dh_parameters , encoding = 'pem' ) :
    """Serializes an asn1crypto . algos . DHParameters object into a byte string
 : param dh _ parameters :
 An asn1crypto . algos . DHParameters object
 : param encoding :
 A unicode string of " pem " or " der "
 : return :
 A byte string of the encoded DH parameters"""

implementation:
if encoding not in set ( [ 'pem' , 'der' ] ) :
    raise ValueError ( pretty_message ( '''
            encoding must be one of "pem", "der", not %s
            ''' , repr ( encoding ) ) )
if not isinstance ( dh_parameters , algos . DHParameters ) :
    raise TypeError ( pretty_message ( '''
            dh_parameters must be an instance of asn1crypto.algos.DHParameters,
            not %s
            ''' , type_name ( dh_parameters ) ) )
output = dh_parameters . dump ( )
if encoding == 'pem' :
    output = pem . armor ( 'DH PARAMETERS' , output )
return output


signature:
def dump_public_key ( public_key , encoding = 'pem' ) :
    """Serializes a public key object into a byte string
 : param public _ key :
 An oscrypto . asymmetric . PublicKey or asn1crypto . keys . PublicKeyInfo object
 : param encoding :
 A unicode string of " pem " or " der "
 : return :
 A byte string of the encoded public key"""

implementation:
if encoding not in set ( [ 'pem' , 'der' ] ) :
    raise ValueError ( pretty_message ( '''
            encoding must be one of "pem", "der", not %s
            ''' , repr ( encoding ) ) )
is_oscrypto = isinstance ( public_key , PublicKey )
if not isinstance ( public_key , keys . PublicKeyInfo ) and not is_oscrypto :
    raise TypeError ( pretty_message ( '''
            public_key must be an instance of oscrypto.asymmetric.PublicKey or
            asn1crypto.keys.PublicKeyInfo, not %s
            ''' , type_name ( public_key ) ) )
if is_oscrypto :
    public_key = public_key . asn1
output = public_key . dump ( )
if encoding == 'pem' :
    output = pem . armor ( 'PUBLIC KEY' , output )
return output


signature:
def dump_certificate ( certificate , encoding = 'pem' ) :
    """Serializes a certificate object into a byte string
 : param certificate :
 An oscrypto . asymmetric . Certificate or asn1crypto . x509 . Certificate object
 : param encoding :
 A unicode string of " pem " or " der "
 : return :
 A byte string of the encoded certificate"""

implementation:
if encoding not in set ( [ 'pem' , 'der' ] ) :
    raise ValueError ( pretty_message ( '''
            encoding must be one of "pem", "der", not %s
            ''' , repr ( encoding ) ) )
is_oscrypto = isinstance ( certificate , Certificate )
if not isinstance ( certificate , x509 . Certificate ) and not is_oscrypto :
    raise TypeError ( pretty_message ( '''
            certificate must be an instance of oscrypto.asymmetric.Certificate
            or asn1crypto.x509.Certificate, not %s
            ''' , type_name ( certificate ) ) )
if is_oscrypto :
    certificate = certificate . asn1
output = certificate . dump ( )
if encoding == 'pem' :
    output = pem . armor ( 'CERTIFICATE' , output )
return output


signature:
def dump_private_key ( private_key , passphrase , encoding = 'pem' , target_ms = 200 ) :
    """Serializes a private key object into a byte string of the PKCS # 8 format
 : param private _ key :
 An oscrypto . asymmetric . PrivateKey or asn1crypto . keys . PrivateKeyInfo
 object
 : param passphrase :
 A unicode string of the passphrase to encrypt the private key with .
 A passphrase of None will result in no encryption . A blank string will
 result in a ValueError to help ensure that the lack of passphrase is
 intentional .
 : param encoding :
 A unicode string of " pem " or " der "
 : param target _ ms :
 Use PBKDF2 with the number of iterations that takes about this many
 milliseconds on the current machine .
 : raises :
 ValueError - when a blank string is provided for the passphrase
 : return :
 A byte string of the encoded and encrypted public key"""

implementation:
if encoding not in set ( [ 'pem' , 'der' ] ) :
    raise ValueError ( pretty_message ( '''
            encoding must be one of "pem", "der", not %s
            ''' , repr ( encoding ) ) )
if passphrase is not None :
    if not isinstance ( passphrase , str_cls ) :
        raise TypeError ( pretty_message ( '''
                passphrase must be a unicode string, not %s
                ''' , type_name ( passphrase ) ) )
    if passphrase == '' :
        raise ValueError ( pretty_message ( '''
                passphrase may not be a blank string - pass None to disable
                encryption
                ''' ) )
is_oscrypto = isinstance ( private_key , PrivateKey )
if not isinstance ( private_key , keys . PrivateKeyInfo ) and not is_oscrypto :
    raise TypeError ( pretty_message ( '''
            private_key must be an instance of oscrypto.asymmetric.PrivateKey
            or asn1crypto.keys.PrivateKeyInfo, not %s
            ''' , type_name ( private_key ) ) )
if is_oscrypto :
    private_key = private_key . asn1
output = private_key . dump ( )
if passphrase is not None :
    cipher = 'aes256_cbc'
    key_length = 32
    kdf_hmac = 'sha256'
    kdf_salt = rand_bytes ( key_length )
    iterations = pbkdf2_iteration_calculator ( kdf_hmac , key_length , target_ms = target_ms , quiet = True )
    # Need a bare minimum of 10,000 iterations for PBKDF2 as of 2015
    if iterations < 10000 :
        iterations = 10000
    passphrase_bytes = passphrase . encode ( 'utf-8' )
    key = pbkdf2 ( kdf_hmac , passphrase_bytes , kdf_salt , iterations , key_length )
    iv , ciphertext = aes_cbc_pkcs7_encrypt ( key , output , None )
    output = keys . EncryptedPrivateKeyInfo ( { 'encryption_algorithm' : { 'algorithm' : 'pbes2' , 'parameters' : { 'key_derivation_func' : { 'algorithm' : 'pbkdf2' , 'parameters' : { 'salt' : algos . Pbkdf2Salt ( name = 'specified' , value = kdf_salt ) , 'iteration_count' : iterations , 'prf' : { 'algorithm' : kdf_hmac , 'parameters' : core . Null ( ) } } } , 'encryption_scheme' : { 'algorithm' : cipher , 'parameters' : iv } } } , 'encrypted_data' : ciphertext } ) . dump ( )
if encoding == 'pem' :
    if passphrase is None :
        object_type = 'PRIVATE KEY'
    else :
        object_type = 'ENCRYPTED PRIVATE KEY'
    output = pem . armor ( object_type , output )
return output


signature:
def dump_openssl_private_key ( private_key , passphrase ) :
    """Serializes a private key object into a byte string of the PEM formats used
 by OpenSSL . The format chosen will depend on the type of private key - RSA ,
 DSA or EC .
 Do not use this method unless you really must interact with a system that
 does not support PKCS # 8 private keys . The encryption provided by PKCS # 8 is
 far superior to the OpenSSL formats . This is due to the fact that the
 OpenSSL formats don ' t stretch the passphrase , making it very easy to
 brute - force .
 : param private _ key :
 An oscrypto . asymmetric . PrivateKey or asn1crypto . keys . PrivateKeyInfo
 object
 : param passphrase :
 A unicode string of the passphrase to encrypt the private key with .
 A passphrase of None will result in no encryption . A blank string will
 result in a ValueError to help ensure that the lack of passphrase is
 intentional .
 : raises :
 ValueError - when a blank string is provided for the passphrase
 : return :
 A byte string of the encoded and encrypted public key"""

implementation:
if passphrase is not None :
    if not isinstance ( passphrase , str_cls ) :
        raise TypeError ( pretty_message ( '''
                passphrase must be a unicode string, not %s
                ''' , type_name ( passphrase ) ) )
    if passphrase == '' :
        raise ValueError ( pretty_message ( '''
                passphrase may not be a blank string - pass None to disable
                encryption
                ''' ) )
is_oscrypto = isinstance ( private_key , PrivateKey )
if not isinstance ( private_key , keys . PrivateKeyInfo ) and not is_oscrypto :
    raise TypeError ( pretty_message ( '''
            private_key must be an instance of oscrypto.asymmetric.PrivateKey or
            asn1crypto.keys.PrivateKeyInfo, not %s
            ''' , type_name ( private_key ) ) )
if is_oscrypto :
    private_key = private_key . asn1
output = private_key . unwrap ( ) . dump ( )
headers = None
if passphrase is not None :
    iv = rand_bytes ( 16 )
    headers = OrderedDict ( )
    headers [ 'Proc-Type' ] = '4,ENCRYPTED'
    headers [ 'DEK-Info' ] = 'AES-128-CBC,%s' % binascii . hexlify ( iv ) . decode ( 'ascii' )
    key_length = 16
    passphrase_bytes = passphrase . encode ( 'utf-8' )
    key = hashlib . md5 ( passphrase_bytes + iv [ 0 : 8 ] ) . digest ( )
    while key_length > len ( key ) :
        key += hashlib . md5 ( key + passphrase_bytes + iv [ 0 : 8 ] ) . digest ( )
    key = key [ 0 : key_length ]
    iv , output = aes_cbc_pkcs7_encrypt ( key , output , iv )
if private_key . algorithm == 'ec' :
    object_type = 'EC PRIVATE KEY'
elif private_key . algorithm == 'rsa' :
    object_type = 'RSA PRIVATE KEY'
elif private_key . algorithm == 'dsa' :
    object_type = 'DSA PRIVATE KEY'
return pem . armor ( object_type , output , headers = headers )


signature:
def handle_sec_error ( error , exception_class = None ) :
    """Checks a Security OSStatus error code and throws an exception if there is an
 error to report
 : param error :
 An OSStatus
 : param exception _ class :
 The exception class to use for the exception if an error occurred
 : raises :
 OSError - when the OSStatus contains an error"""

implementation:
if error == 0 :
    return
if error in set ( [ SecurityConst . errSSLClosedNoNotify , SecurityConst . errSSLClosedAbort ] ) :
    raise TLSDisconnectError ( 'The remote end closed the connection' )
if error == SecurityConst . errSSLClosedGraceful :
    raise TLSGracefulDisconnectError ( 'The remote end closed the connection' )
cf_error_string = Security . SecCopyErrorMessageString ( error , null ( ) )
output = CFHelpers . cf_string_to_unicode ( cf_error_string )
CoreFoundation . CFRelease ( cf_error_string )
if output is None or output == '' :
    output = 'OSStatus %s' % error
if exception_class is None :
    exception_class = OSError
raise exception_class ( output )


signature:
def _get_func_info ( docstring , def_lineno , code_lines , prefix ) :
    """Extracts the function signature and description of a Python function
 : param docstring :
 A unicode string of the docstring for the function
 : param def _ lineno :
 An integer line number that function was defined on
 : param code _ lines :
 A list of unicode string lines from the source file the function was
 defined in
 : param prefix :
 A prefix to prepend to all output lines
 : return :
 A 2 - element tuple :
 - [ 0 ] A unicode string of the function signature with a docstring of
 parameter info
 - [ 1 ] A markdown snippet of the function description"""

implementation:
def_index = def_lineno - 1
definition = code_lines [ def_index ]
definition = definition . rstrip ( )
while not definition . endswith ( ':' ) :
    def_index += 1
    definition += '\n' + code_lines [ def_index ] . rstrip ( )
definition = textwrap . dedent ( definition ) . rstrip ( ':' )
definition = definition . replace ( '\n' , '\n' + prefix )
description = ''
found_colon = False
params = ''
for line in docstring . splitlines ( ) :
    if line and line [ 0 ] == ':' :
        found_colon = True
    if not found_colon :
        if description :
            description += '\n'
        description += line
    else :
        if params :
            params += '\n'
        params += line
description = description . strip ( )
description_md = ''
if description :
    description_md = "%s%s" % ( prefix , description . replace ( '\n' , '\n' + prefix ) )
    description_md = re . sub ( '\n>(\\s+)\n' , '\n>\n' , description_md )
params = params . strip ( )
if params :
    definition += ( ':\n%s    """\n%s    ' % ( prefix , prefix ) )
    definition += params . replace ( '\n' , '\n%s    ' % prefix )
    definition += ( '\n%s    """' % prefix )
    definition = re . sub ( '\n>(\\s+)\n' , '\n>\n' , definition )
for search , replace in definition_replacements . items ( ) :
    definition = definition . replace ( search , replace )
return ( definition , description_md )


signature:
def _find_sections ( md_ast , sections , last , last_class , total_lines = None ) :
    """Walks through a CommonMark AST to find section headers that delineate
 content that should be updated by this script
 : param md _ ast :
 The AST of the markdown document
 : param sections :
 A dict to store the start and end lines of a section . The key will be
 a two - element tuple of the section type ( " class " , " function " ,
 " method " or " attribute " ) and identifier . The values are a two - element
 tuple of the start and end line number in the markdown document of the
 section .
 : param last :
 A dict containing information about the last section header seen .
 Includes the keys " type _ name " , " identifier " , " start _ line " .
 : param last _ class :
 A unicode string of the name of the last class found - used when
 processing methods and attributes .
 : param total _ lines :
 An integer of the total number of lines in the markdown document -
 used to work around a bug in the API of the Python port of CommonMark"""

implementation:
def child_walker ( node ) :
    for child , entering in node . walker ( ) :
        if child == node :
            continue
        yield child , entering
for child , entering in child_walker ( md_ast ) :
    if child . t == 'heading' :
        start_line = child . sourcepos [ 0 ] [ 0 ]
        if child . level == 2 :
            if last :
                sections [ ( last [ 'type_name' ] , last [ 'identifier' ] ) ] = ( last [ 'start_line' ] , start_line - 1 )
                last . clear ( )
        if child . level in set ( [ 3 , 5 ] ) :
            heading_elements = [ ]
            for heading_child , _ in child_walker ( child ) :
                heading_elements . append ( heading_child )
            if len ( heading_elements ) != 2 :
                continue
            first = heading_elements [ 0 ]
            second = heading_elements [ 1 ]
            if first . t != 'code' :
                continue
            if second . t != 'text' :
                continue
            type_name = second . literal . strip ( )
            identifier = first . literal . strip ( ) . replace ( '()' , '' ) . lstrip ( '.' )
            if last :
                sections [ ( last [ 'type_name' ] , last [ 'identifier' ] ) ] = ( last [ 'start_line' ] , start_line - 1 )
                last . clear ( )
            if type_name == 'function' :
                if child . level != 3 :
                    continue
            if type_name == 'class' :
                if child . level != 3 :
                    continue
                last_class . append ( identifier )
            if type_name in set ( [ 'method' , 'attribute' ] ) :
                if child . level != 5 :
                    continue
                identifier = last_class [ - 1 ] + '.' + identifier
            last . update ( { 'type_name' : type_name , 'identifier' : identifier , 'start_line' : start_line , } )
    elif child . t == 'block_quote' :
        find_sections ( child , sections , last , last_class )
if last :
    sections [ ( last [ 'type_name' ] , last [ 'identifier' ] ) ] = ( last [ 'start_line' ] , total_lines )


signature:
def walk_ast ( node , code_lines , sections , md_chunks ) :
    """A callback used to walk the Python AST looking for classes , functions ,
 methods and attributes . Generates chunks of markdown markup to replace
 the existing content .
 : param node :
 An _ ast module node object
 : param code _ lines :
 A list of unicode strings - the source lines of the Python file
 : param sections :
 A dict of markdown document sections that need to be updated . The key
 will be a two - element tuple of the section type ( " class " , " function " ,
 " method " or " attribute " ) and identifier . The values are a two - element
 tuple of the start and end line number in the markdown document of the
 section .
 : param md _ chunks :
 A dict with keys from the sections param and the values being a unicode
 string containing a chunk of markdown markup ."""

implementation:
if isinstance ( node , _ast . FunctionDef ) :
    key = ( 'function' , node . name )
    if key not in sections :
        return
    docstring = ast . get_docstring ( node )
    def_lineno = node . lineno + len ( node . decorator_list )
    definition , description_md = _get_func_info ( docstring , def_lineno , code_lines , '> ' )
    md_chunk = textwrap . dedent ( """
            ### `%s()` function

            > ```python
            > %s
            > ```
            >
            %s
        """ ) . strip ( ) % ( node . name , definition , description_md ) + "\n"
    md_chunks [ key ] = md_chunk . replace ( '>\n\n' , '' )
elif isinstance ( node , _ast . ClassDef ) :
    if ( 'class' , node . name ) not in sections :
        return
    for subnode in node . body :
        if isinstance ( subnode , _ast . FunctionDef ) :
            node_id = node . name + '.' + subnode . name
            method_key = ( 'method' , node_id )
            is_method = method_key in sections
            attribute_key = ( 'attribute' , node_id )
            is_attribute = attribute_key in sections
            is_constructor = subnode . name == '__init__'
            if not is_constructor and not is_attribute and not is_method :
                continue
            docstring = ast . get_docstring ( subnode )
            def_lineno = subnode . lineno + len ( subnode . decorator_list )
            if not docstring :
                continue
            if is_method or is_constructor :
                definition , description_md = _get_func_info ( docstring , def_lineno , code_lines , '> > ' )
                if is_constructor :
                    key = ( 'class' , node . name )
                    class_docstring = ast . get_docstring ( node ) or ''
                    class_description = textwrap . dedent ( class_docstring ) . strip ( )
                    if class_description :
                        class_description_md = "> %s\n>" % ( class_description . replace ( "\n" , "\n> " ) )
                    else :
                        class_description_md = ''
                    md_chunk = textwrap . dedent ( """
                            ### `%s()` class

                            %s
                            > ##### constructor
                            >
                            > > ```python
                            > > %s
                            > > ```
                            > >
                            %s
                        """ ) . strip ( ) % ( node . name , class_description_md , definition , description_md )
                    md_chunk = md_chunk . replace ( '\n\n\n' , '\n\n' )
                else :
                    key = method_key
                    md_chunk = textwrap . dedent ( """
                            >
                            > ##### `.%s()` method
                            >
                            > > ```python
                            > > %s
                            > > ```
                            > >
                            %s
                        """ ) . strip ( ) % ( subnode . name , definition , description_md )
                if md_chunk [ - 5 : ] == '\n> >\n' :
                    md_chunk = md_chunk [ 0 : - 5 ]
            else :
                key = attribute_key
                description = textwrap . dedent ( docstring ) . strip ( )
                description_md = "> > %s" % ( description . replace ( "\n" , "\n> > " ) )
                md_chunk = textwrap . dedent ( """
                        >
                        > ##### `.%s` attribute
                        >
                        %s
                    """ ) . strip ( ) % ( subnode . name , description_md )
            md_chunks [ key ] = re . sub ( '[ \\t]+\n' , '\n' , md_chunk . rstrip ( ) )
elif isinstance ( node , _ast . If ) :
    for subast in node . body :
        walk_ast ( subast , code_lines , sections , md_chunks )
    for subast in node . orelse :
        walk_ast ( subast , code_lines , sections , md_chunks )


signature:
def run ( ) :
    """Looks through the docs / dir and parses each markdown document , looking for
 sections to update from Python docstrings . Looks for section headers in
 the format :
 - # # # ` ClassName ( ) ` class
 - # # # # # ` . method _ name ( ) ` method
 - # # # # # ` . attribute _ name ` attribute
 - # # # ` function _ name ( ) ` function
 The markdown content following these section headers up until the next
 section header will be replaced by new markdown generated from the Python
 docstrings of the associated source files .
 By default maps docs / { name } . md to { modulename } / { name } . py . Allows for
 custom mapping via the md _ source _ map variable ."""

implementation:
print ( 'Updating API docs...' )
md_files = [ ]
for root , _ , filenames in os . walk ( os . path . join ( package_root , 'docs' ) ) :
    for filename in filenames :
        if not filename . endswith ( '.md' ) :
            continue
        md_files . append ( os . path . join ( root , filename ) )
parser = CommonMark . Parser ( )
for md_file in md_files :
    md_file_relative = md_file [ len ( package_root ) + 1 : ]
    if md_file_relative in md_source_map :
        py_files = md_source_map [ md_file_relative ]
        py_paths = [ os . path . join ( package_root , py_file ) for py_file in py_files ]
    else :
        py_files = [ os . path . basename ( md_file ) . replace ( '.md' , '.py' ) ]
        py_paths = [ os . path . join ( package_root , package_name , py_files [ 0 ] ) ]
        if not os . path . exists ( py_paths [ 0 ] ) :
            continue
    with open ( md_file , 'rb' ) as f :
        markdown = f . read ( ) . decode ( 'utf-8' )
    original_markdown = markdown
    md_lines = list ( markdown . splitlines ( ) )
    md_ast = parser . parse ( markdown )
    last_class = [ ]
    last = { }
    sections = OrderedDict ( )
    find_sections ( md_ast , sections , last , last_class , markdown . count ( "\n" ) + 1 )
    md_chunks = { }
    for index , py_file in enumerate ( py_files ) :
        py_path = py_paths [ index ]
        with open ( os . path . join ( py_path ) , 'rb' ) as f :
            code = f . read ( ) . decode ( 'utf-8' )
            module_ast = ast . parse ( code , filename = py_file )
            code_lines = list ( code . splitlines ( ) )
        for node in ast . iter_child_nodes ( module_ast ) :
            walk_ast ( node , code_lines , sections , md_chunks )
    added_lines = 0
    def _replace_md ( key , sections , md_chunk , md_lines , added_lines ) :
        start , end = sections [ key ]
        start -= 1
        start += added_lines
        end += added_lines
        new_lines = md_chunk . split ( '\n' )
        added_lines += len ( new_lines ) - ( end - start )
        # Ensure a newline above each class header
        if start > 0 and md_lines [ start ] [ 0 : 4 ] == '### ' and md_lines [ start - 1 ] [ 0 : 1 ] == '>' :
            added_lines += 1
            new_lines . insert ( 0 , '' )
        md_lines [ start : end ] = new_lines
        return added_lines
    for key in sections :
        if key not in md_chunks :
            raise ValueError ( 'No documentation found for %s' % key [ 1 ] )
        added_lines = _replace_md ( key , sections , md_chunks [ key ] , md_lines , added_lines )
    markdown = '\n' . join ( md_lines ) . strip ( ) + '\n'
    if original_markdown != markdown :
        with open ( md_file , 'wb' ) as f :
            f . write ( markdown . encode ( 'utf-8' ) )


signature:
def ec_generate_pair ( curve ) :
    """Generates a EC public / private key pair
 : param curve :
 A unicode string . Valid values include " secp256r1 " , " secp384r1 " and
 " secp521r1 " .
 : raises :
 ValueError - when any of the parameters contain an invalid value
 TypeError - when any of the parameters are of the wrong type
 : return :
 A 2 - element tuple of ( asn1crypto . keys . PublicKeyInfo ,
 asn1crypto . keys . PrivateKeyInfo )"""

implementation:
if curve not in set ( [ 'secp256r1' , 'secp384r1' , 'secp521r1' ] ) :
    raise ValueError ( pretty_message ( '''
            curve must be one of "secp256r1", "secp384r1", "secp521r1", not %s
            ''' , repr ( curve ) ) )
curve_num_bytes = CURVE_BYTES [ curve ]
curve_base_point = { 'secp256r1' : SECP256R1_BASE_POINT , 'secp384r1' : SECP384R1_BASE_POINT , 'secp521r1' : SECP521R1_BASE_POINT , } [ curve ]
while True :
    private_key_bytes = rand_bytes ( curve_num_bytes )
    private_key_int = int_from_bytes ( private_key_bytes , signed = False )
    if private_key_int > 0 and private_key_int < curve_base_point . order :
        break
private_key_info = keys . PrivateKeyInfo ( { 'version' : 0 , 'private_key_algorithm' : keys . PrivateKeyAlgorithm ( { 'algorithm' : 'ec' , 'parameters' : keys . ECDomainParameters ( name = 'named' , value = curve ) } ) , 'private_key' : keys . ECPrivateKey ( { 'version' : 'ecPrivkeyVer1' , 'private_key' : private_key_int } ) , } )
private_key_info [ 'private_key' ] . parsed [ 'public_key' ] = private_key_info . public_key
public_key_info = private_key_info . public_key_info
return ( public_key_info , private_key_info )