<commit_before># coding: utf-8
from __future__ import unicode_literals, division, absolute_import, print_function

import sys
import hashlib

from asn1crypto.keys import PublicKeyInfo
from asn1crypto import core

from .._ffi import new, null, buffer_from_bytes, deref, bytes_from_buffer, struct, struct_bytes, cast, unwrap, buffer_from_unicode
from ._cng import bcrypt, bcrypt_const, handle_error, open_alg_handle, close_alg_handle
from .._int import int_to_bytes, int_from_bytes, fill_width
from ..keys import parse_public, parse_certificate, parse_private, parse_pkcs12
from ..errors import SignatureError, PrivateKeyError

if sys.version_info < (3,):
    str_cls = unicode  #pylint: disable=E0602
    byte_cls = str
else:
    str_cls = str
    byte_cls = bytes



class PrivateKey():

    bcrypt_key_handle = None
    algo = None
    curve = None
    bit_size = None

    def __init__(self, bcrypt_key_handle, algo, curve=None, bit_size=None):
        self.bcrypt_key_handle = bcrypt_key_handle
        self.algo = algo
        self.curve = curve
        self.bit_size = bit_size

    def __del__(self):
        if self.bcrypt_key_handle:
            res = bcrypt.BCryptDestroyKey(self.bcrypt_key_handle)
            handle_error(res)
            self.bcrypt_key_handle = None


class PublicKey(PrivateKey):

    pass


class Certificate(PublicKey):

    pass


class Signature(core.Sequence):
    _fields = [
        ('r', core.Integer),
        ('s', core.Integer),
    ]

    @classmethod
    def from_bcrypt(cls, data):
        """
        Reads a signature from a byte string created by Microsoft's
        BCryptSignHash() function.

        :param data:
            A byte string from BCryptSignHash()

        :return:
            A Signature object
        """

        r = int_from_bytes(data[0:len(data)//2])
        s = int_from_bytes(data[len(data)//2:])
        return cls({'r': r, 's': s})

    def to_bcrypt(self):
        """
        Dumps a signature to a byte string compatible with Microsoft's
        BCryptVerifySignature() function.

        :return:
            A byte string compatible with BCryptVerifySignature()
        """

        return int_to_bytes(self['r'].native) + int_to_bytes(self['s'].native)



def load_certificate(source, source_type):
    """
    Loads an x509 certificate into a format usable with rsa_verify()

    :param source:
        A byte string of file contents or a unicode string filename

    :param source_type:
        A unicode string describing the source - "file" or "bytes"

    :raises:
        ValueError - when any of the parameters are of the wrong type or value
        OSError - when an error is returned by the OS X Security Framework

    :return:
        A Certificate object
    """

    if source_type not in ('file', 'bytes'):
        raise ValueError('source_type is not one of "file" or "bytes"')

    if source_type == 'file':
        with open(source, 'rb') as f:
            source = f.read()

    elif not isinstance(source, byte_cls):
        raise ValueError('source is not a byte string')

    certificate, algo = parse_certificate(source)
    return _load_key(certificate['tbs_certificate']['subject_public_key_info'], algo, Certificate)


def _load_key(key_object, algo, container):
    """
    Loads a public or private key into a format usable with various functions

    :param key_object:
        An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo
        object

    :param algo:
        A unicode string of "rsa", "dsa" or "ec"

    :param container:
        The class of the object to hold the bcrypt_key_handle

    :return:
        A PrivateKey, PublicKey or Certificate object, based on container
    """

    key_type = 'public' if isinstance(key_object, PublicKeyInfo) else 'private'

    alg_handle = None
    key_handle = None
    curve_name = None
    bit_size = None

    try:
        if algo == 'ec':
            curve_type, curve_name = key_object.curve
            if curve_type != 'named':
                raise PrivateKeyError('Windows only supports EC keys using named curves')
            if curve_name not in ('secp256r1', 'secp384r1', 'secp521r1'):
                raise PrivateKeyError('Windows only supports EC keys using the named curves secp256r1, secp384r1 and secp521r1')

        elif algo == 'dsa':
            ver_info = sys.getwindowsversion()
            pair = (ver_info.major, ver_info.minor)
            if key_object.bit_size > 1024 and pair < (6, 2):
                raise PrivateKeyError('Windows Vista, 7 and Server 2008 only support DSA keys based on SHA1 (1024 bits or less) - this key is based on %s and is %s bits' % (key_object.hash_algo.upper(), key_object.bit_size))
            elif key_object.bit_size == 2048 and key_object.hash_algo == 'sha1':
                raise PrivateKeyError('Windows only supports 2048 bit DSA keys based on SHA2 - this key is 2048 bits and based on SHA1, a non-standard combination that is usually generated by old versions of OpenSSL')


        if algo != 'ec':
            bit_size = key_object.bit_size

        alg_selector = key_object.curve[1] if algo == 'ec' else algo
        alg_constant = {
            'rsa': bcrypt_const.BCRYPT_RSA_ALGORITHM,
            'dsa': bcrypt_const.BCRYPT_DSA_ALGORITHM,
            'secp256r1': bcrypt_const.BCRYPT_ECDSA_P256_ALGORITHM,
            'secp384r1': bcrypt_const.BCRYPT_ECDSA_P384_ALGORITHM,
            'secp521r1': bcrypt_const.BCRYPT_ECDSA_P521_ALGORITHM,
        }[alg_selector]
        alg_handle = open_alg_handle(alg_constant)

        if algo == 'rsa':
            if key_type == 'public':
                blob_type = bcrypt_const.BCRYPT_RSAPUBLIC_BLOB
                magic = bcrypt_const.BCRYPT_RSAPUBLIC_MAGIC
                parsed_key = key_object['public_key'].parsed
                prime1_size = 0
                prime2_size = 0
            else:
                blob_type = bcrypt_const.BCRYPT_RSAFULLPRIVATE_BLOB
                magic = bcrypt_const.BCRYPT_RSAFULLPRIVATE_MAGIC
                parsed_key = key_object['private_key'].parsed<commit_msg>Removed an extra line<commit_after># coding: utf-8
from __future__ import unicode_literals, division, absolute_import, print_function

import sys
import hashlib

from asn1crypto.keys import PublicKeyInfo
from asn1crypto import core

from .._ffi import new, null, buffer_from_bytes, deref, bytes_from_buffer, struct, struct_bytes, cast, unwrap, buffer_from_unicode
from ._cng import bcrypt, bcrypt_const, handle_error, open_alg_handle, close_alg_handle
from .._int import int_to_bytes, int_from_bytes, fill_width
from ..keys import parse_public, parse_certificate, parse_private, parse_pkcs12
from ..errors import SignatureError, PrivateKeyError

if sys.version_info < (3,):
    str_cls = unicode  #pylint: disable=E0602
    byte_cls = str
else:
    str_cls = str
    byte_cls = bytes



class PrivateKey():

    bcrypt_key_handle = None
    algo = None
    curve = None
    bit_size = None

    def __init__(self, bcrypt_key_handle, algo, curve=None, bit_size=None):
        self.bcrypt_key_handle = bcrypt_key_handle
        self.algo = algo
        self.curve = curve
        self.bit_size = bit_size

    def __del__(self):
        if self.bcrypt_key_handle:
            res = bcrypt.BCryptDestroyKey(self.bcrypt_key_handle)
            handle_error(res)
            self.bcrypt_key_handle = None


class PublicKey(PrivateKey):

    pass


class Certificate(PublicKey):

    pass


class Signature(core.Sequence):
    _fields = [
        ('r', core.Integer),
        ('s', core.Integer),
    ]

    @classmethod
    def from_bcrypt(cls, data):
        """
        Reads a signature from a byte string created by Microsoft's
        BCryptSignHash() function.

        :param data:
            A byte string from BCryptSignHash()

        :return:
            A Signature object
        """

        r = int_from_bytes(data[0:len(data)//2])
        s = int_from_bytes(data[len(data)//2:])
        return cls({'r': r, 's': s})

    def to_bcrypt(self):
        """
        Dumps a signature to a byte string compatible with Microsoft's
        BCryptVerifySignature() function.

        :return:
            A byte string compatible with BCryptVerifySignature()
        """

        return int_to_bytes(self['r'].native) + int_to_bytes(self['s'].native)



def load_certificate(source, source_type):
    """
    Loads an x509 certificate into a format usable with rsa_verify()

    :param source:
        A byte string of file contents or a unicode string filename

    :param source_type:
        A unicode string describing the source - "file" or "bytes"

    :raises:
        ValueError - when any of the parameters are of the wrong type or value
        OSError - when an error is returned by the OS X Security Framework

    :return:
        A Certificate object
    """

    if source_type not in ('file', 'bytes'):
        raise ValueError('source_type is not one of "file" or "bytes"')

    if source_type == 'file':
        with open(source, 'rb') as f:
            source = f.read()

    elif not isinstance(source, byte_cls):
        raise ValueError('source is not a byte string')

    certificate, algo = parse_certificate(source)
    return _load_key(certificate['tbs_certificate']['subject_public_key_info'], algo, Certificate)


def _load_key(key_object, algo, container):
    """
    Loads a public or private key into a format usable with various functions

    :param key_object:
        An asn1crypto.keys.PublicKeyInfo or asn1crypto.keys.PrivateKeyInfo
        object

    :param algo:
        A unicode string of "rsa", "dsa" or "ec"

    :param container:
        The class of the object to hold the bcrypt_key_handle

    :return:
        A PrivateKey, PublicKey or Certificate object, based on container
    """

    key_type = 'public' if isinstance(key_object, PublicKeyInfo) else 'private'

    alg_handle = None
    key_handle = None
    curve_name = None
    bit_size = None

    try:
        if algo == 'ec':
            curve_type, curve_name = key_object.curve
            if curve_type != 'named':
                raise PrivateKeyError('Windows only supports EC keys using named curves')
            if curve_name not in ('secp256r1', 'secp384r1', 'secp521r1'):
                raise PrivateKeyError('Windows only supports EC keys using the named curves secp256r1, secp384r1 and secp521r1')

        elif algo == 'dsa':
            ver_info = sys.getwindowsversion()
            pair = (ver_info.major, ver_info.minor)
            if key_object.bit_size > 1024 and pair < (6, 2):
                raise PrivateKeyError('Windows Vista, 7 and Server 2008 only support DSA keys based on SHA1 (1024 bits or less) - this key is based on %s and is %s bits' % (key_object.hash_algo.upper(), key_object.bit_size))
            elif key_object.bit_size == 2048 and key_object.hash_algo == 'sha1':
                raise PrivateKeyError('Windows only supports 2048 bit DSA keys based on SHA2 - this key is 2048 bits and based on SHA1, a non-standard combination that is usually generated by old versions of OpenSSL')

        if algo != 'ec':
            bit_size = key_object.bit_size

        alg_selector = key_object.curve[1] if algo == 'ec' else algo
        alg_constant = {
            'rsa': bcrypt_const.BCRYPT_RSA_ALGORITHM,
            'dsa': bcrypt_const.BCRYPT_DSA_ALGORITHM,
            'secp256r1': bcrypt_const.BCRYPT_ECDSA_P256_ALGORITHM,
            'secp384r1': bcrypt_const.BCRYPT_ECDSA_P384_ALGORITHM,
            'secp521r1': bcrypt_const.BCRYPT_ECDSA_P521_ALGORITHM,
        }[alg_selector]
        alg_handle = open_alg_handle(alg_constant)

        if algo == 'rsa':
            if key_type == 'public':
                blob_type = bcrypt_const.BCRYPT_RSAPUBLIC_BLOB
                magic = bcrypt_const.BCRYPT_RSAPUBLIC_MAGIC
                parsed_key = key_object['public_key'].parsed
                prime1_size = 0
                prime2_size = 0
            else:
                blob_type = bcrypt_const.BCRYPT_RSAFULLPRIVATE_BLOB
                magic = bcrypt_const.BCRYPT_RSAFULLPRIVATE_MAGIC
                parsed_key = key_object['private_key'].parsed
{'fraction_non_alphanumeric': 0.08170282439623414, 'fraction_numerical': 0.016209578387228817, 'mean_word_length': 2.6195555555555554, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2104974', 'n_tokens_mistral': 3914, 'n_tokens_neox': 3632, 'n_words': 1068}