Esempio n. 1
0
def _import_openssh_private_ecc(data, password):

    from ._openssh import (import_openssh_private_generic, read_bytes,
                           read_string, check_padding)

    ssh_name, decrypted = import_openssh_private_generic(data, password)

    name, decrypted = read_string(decrypted)
    if name not in _curves:
        raise UnsupportedEccFeature("Unsupported ECC curve %s" % name)
    curve = _curves[name]
    modulus_bytes = (curve.modulus_bits + 7) // 8

    public_key, decrypted = read_bytes(decrypted)

    if bord(public_key[0]) != 4:
        raise ValueError("Only uncompressed OpenSSH EC keys are supported")
    if len(public_key) != 2 * modulus_bytes + 1:
        raise ValueError("Incorrect public key length")

    point_x = Integer.from_bytes(public_key[1:1 + modulus_bytes])
    point_y = Integer.from_bytes(public_key[1 + modulus_bytes:])
    point = EccPoint(point_x, point_y, curve=name)

    private_key, decrypted = read_bytes(decrypted)
    d = Integer.from_bytes(private_key)

    _, padded = read_string(decrypted)  # Comment
    check_padding(padded)

    return EccKey(curve=name, d=d, point=point)
Esempio n. 2
0
 def byte_init(cls, key, bytestring):
     '''Returns a Ciphertext from a bytestring containing c1 and c2'''
     padded_size = int(np.round(key.p.size_in_bits() / 8))
     assert (len(bytestring) == 2 * padded_size)
     c1 = Integer.from_bytes(bytestring[:padded_size])
     c2 = Integer.from_bytes(bytestring[padded_size:])
     return cls(key, c1, c2)
Esempio n. 3
0
def deserialize_ElGamalPrivateKey(bytestring):
    '''constructs an ElGamal Public Key from a bytestring'''
    padded_size = len(bytestring) // 4
    assert padded_size * 4 == len(bytestring), "Wrong bytestring length"
    p = Integer.from_bytes(bytestring[:padded_size])
    g = Integer.from_bytes(bytestring[padded_size:2 * padded_size])
    y = Integer.from_bytes(bytestring[2 * padded_size:3 * padded_size])
    x = Integer.from_bytes(bytestring[3 * padded_size:])
    return ElGamal.construct((p, g, y, x))
Esempio n. 4
0
def _import_public_der(ec_point, curve_oid=None, curve_name=None):
    """Convert an encoded EC point into an EccKey object

    ec_point: byte string with the EC point (SEC1-encoded)
    curve_oid: string with the name the curve
    curve_name: string with the OID of the curve

    Either curve_id or curve_name must be specified

    """

    for _curve_name, curve in _curves.items():
        if curve_oid and curve.oid == curve_oid:
            break
        if curve_name == _curve_name:
            break
    else:
        if curve_oid:
            raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" %
                                        curve_oid)
        else:
            raise UnsupportedEccFeature("Unsupported ECC curve (%s)" %
                                        curve_name)

    # See 2.2 in RFC5480 and 2.3.3 in SEC1
    # The first byte is:
    # - 0x02:   compressed, only X-coordinate, Y-coordinate is even
    # - 0x03:   compressed, only X-coordinate, Y-coordinate is odd
    # - 0x04:   uncompressed, X-coordinate is followed by Y-coordinate
    #
    # PAI is in theory encoded as 0x00.

    modulus_bytes = curve.p.size_in_bytes()
    point_type = bord(ec_point[0])

    # Uncompressed point
    if point_type == 0x04:
        if len(ec_point) != (1 + 2 * modulus_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:modulus_bytes + 1])
        y = Integer.from_bytes(ec_point[modulus_bytes + 1:])
    # Compressed point
    elif point_type in (0x02, 0x03):
        if len(ec_point) != (1 + modulus_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:])
        # Right now, we only support Short Weierstrass curves
        y = (x**3 - x * 3 + curve.b).sqrt(curve.p)
        if point_type == 0x02 and y.is_odd():
            y = curve.p - y
        if point_type == 0x03 and y.is_even():
            y = curve.p - y
    else:
        raise ValueError("Incorrect EC point encoding")

    return construct(curve=_curve_name, point_x=x, point_y=y)
Esempio n. 5
0
    def test_several_lengths(self):
        prng = SHAKE128.new().update(b('Test'))
        for length in range(1, 100):
            base = Integer.from_bytes(prng.read(length))
            modulus2 = Integer.from_bytes(prng.read(length)) | 1
            exponent2 = Integer.from_bytes(prng.read(length))

            expected = pow(base, exponent2, modulus2)
            result = monty_pow(base, exponent2, modulus2)
            self.assertEqual(result, expected)
Esempio n. 6
0
    def test_several_lengths(self):
        prng = SHAKE128.new().update(b('Test'))
        for length in range(1, 100):
            base = Integer.from_bytes(prng.read(length))
            modulus2 = Integer.from_bytes(prng.read(length)) | 1
            exponent2 = Integer.from_bytes(prng.read(length))

            expected = pow(base, exponent2, modulus2)
            result = monty_pow(base, exponent2, modulus2)
            self.assertEqual(result, expected)
Esempio n. 7
0
def _generate_domain(L, randfunc):
    """Generate a new set of DSA domain parameters"""

    N = {1024: 160, 2048: 224, 3072: 256}.get(L)
    if N is None:
        raise ValueError("Invalid modulus length (%d)" % L)

    outlen = SHA256.digest_size * 8
    n = (L + outlen - 1) // outlen - 1  # ceil(L/outlen) -1
    b_ = L - 1 - (n * outlen)

    # Generate q (A.1.1.2)
    q = Integer(4)
    upper_bit = 1 << (N - 1)
    while test_probable_prime(q, randfunc) != PROBABLY_PRIME:
        seed = randfunc(64)
        U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1)
        q = U | upper_bit | 1

    assert (q.size_in_bits() == N)

    # Generate p (A.1.1.2)
    offset = 1
    upper_bit = 1 << (L - 1)
    while True:
        V = [
            SHA256.new(seed + Integer(offset + j).to_bytes()).digest()
            for j in range(n + 1)
        ]
        V = [Integer.from_bytes(v) for v in V]
        W = sum([V[i] * (1 << (i * outlen)) for i in range(n)],
                (V[n] & (1 << b_ - 1)) * (1 << (n * outlen)))

        X = Integer(W + upper_bit)  # 2^{L-1} < X < 2^{L}
        assert (X.size_in_bits() == L)

        c = X % (q * 2)
        p = X - (c - 1)  # 2q divides (p-1)
        if p.size_in_bits() == L and \
           test_probable_prime(p, randfunc) == PROBABLY_PRIME:
            break
        offset += n + 1

    # Generate g (A.2.3, index=1)
    e = (p - 1) // q
    for count in itertools.count(1):
        U = seed + b("ggen") + bchr(1) + Integer(count).to_bytes()
        W = Integer.from_bytes(SHA256.new(U).digest())
        g = pow(W, e, p)
        if g != 1:
            break

    return (p, q, g, seed)
Esempio n. 8
0
    def verify(self, msg_hash, signature):
        """Verify that a certain DSS signature is authentic.

        This function checks if the party holding the private half of the key
        really signed the message.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message.
            This is an object belonging to the `Cryptodome.Hash` module.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used in
            combination with SHA-512.

          signature : byte string
            The signature that needs to be validated.

        :Raise ValueError:
            If the signature is not authentic.
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash does not belong to SHS")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [
                Integer.from_bytes(x) for x in (signature[:self._order_bytes],
                                                signature[self._order_bytes:])
            ]
        else:
            try:
                der_seq = DerSequence().decode(signature)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError(
                    "The signature is not authentic (DER content)")
            r_prime, s_prime = der_seq[0], der_seq[1]

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Esempio n. 9
0
    def verify(self, msg_hash, signature):
        """Verify that a certain DSS signature is authentic.

        This function checks if the party holding the private half of the key
        really signed the message.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message.
            This is an object belonging to the `Cryptodome.Hash` module.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used in
            combination with SHA-512.

          signature : byte string
            The signature that needs to be validated.

        :Raise ValueError:
            If the signature is not authentic.
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash does not belong to SHS")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [Integer.from_bytes(x)
                                for x in (signature[:self._order_bytes],
                                          signature[self._order_bytes:])]
        else:
            try:
                der_seq = DerSequence().decode(signature)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError("The signature is not authentic (DER content)")
            r_prime, s_prime = der_seq[0], der_seq[1]

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Esempio n. 10
0
def _generate_domain(L, randfunc):
    """Generate a new set of DSA domain parameters"""

    N = { 1024:160, 2048:224, 3072:256 }.get(L)
    if N is None:
        raise ValueError("Invalid modulus length (%d)" % L)

    outlen = SHA256.digest_size * 8
    n = (L + outlen - 1) // outlen - 1  # ceil(L/outlen) -1
    b_ = L - 1 - (n * outlen)

    # Generate q (A.1.1.2)
    q = Integer(4)
    upper_bit = 1 << (N - 1)
    while test_probable_prime(q, randfunc) != PROBABLY_PRIME:
        seed = randfunc(64)
        U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1)
        q = U | upper_bit | 1

    assert(q.size_in_bits() == N)

    # Generate p (A.1.1.2)
    offset = 1
    upper_bit = 1 << (L - 1)
    while True:
        V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest()
              for j in iter_range(n + 1) ]
        V = [ Integer.from_bytes(v) for v in V ]
        W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)],
                (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen)))

        X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L}
        assert(X.size_in_bits() == L)

        c = X % (q * 2)
        p = X - (c - 1)  # 2q divides (p-1)
        if p.size_in_bits() == L and \
           test_probable_prime(p, randfunc) == PROBABLY_PRIME:
               break
        offset += n + 1

    # Generate g (A.2.3, index=1)
    e = (p - 1) // q
    for count in itertools.count(1):
        U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes()
        W = Integer.from_bytes(SHA256.new(U).digest())
        g = pow(W, e, p)
        if g != 1:
            break

    return (p, q, g, seed)
Esempio n. 11
0
    def verify(self, msg_hash, signature):
        """Check if a certain (EC)DSA signature is authentic.

        :parameter msg_hash:
            The hash that was carried out over the message.
            This is an object belonging to the :mod:`Cryptodome.Hash` module.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used in
            combination with SHA-512.
        :type msg_hash: hash object

        :parameter signature:
            The signature that needs to be validated
        :type signature: byte string

        :raise ValueError: if the signature is not authentic
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [
                Integer.from_bytes(x) for x in (signature[:self._order_bytes],
                                                signature[self._order_bytes:])
            ]
        else:
            try:
                der_seq = DerSequence().decode(signature, strict=True)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError(
                    "The signature is not authentic (DER content)")
            r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1])

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Esempio n. 12
0
def _import_public_der(curve_name, publickey):

    # We only support P-256 named curves for now
    if curve_name != _curve.oid:
        raise ValueError("Unsupport curve")

    # ECPoint ::= OCTET STRING

    # We support only uncompressed points
    order_bytes = _curve.order.size_in_bytes()
    if len(publickey) != (1 + 2 * order_bytes) or bord(publickey[0]) != 4:
        raise ValueError("Only uncompressed points are supported")

    point_x = Integer.from_bytes(publickey[1:order_bytes+1])
    point_y = Integer.from_bytes(publickey[order_bytes+1:])
    return construct(curve="P-256", point_x=point_x, point_y=point_y)
Esempio n. 13
0
def decode_hospital_shared_secrets_bytestring(key_public,
                                              ss_bytes,
                                              sketch_size=32):
    '''Decodes a bytestring of hospital shared secrets corresponding to an encrypted
    HLL bytestring from the transmit entry of hospital_round2a_hll'''
    padded_size = int(np.round(key_public.p.size_in_bits() / 8))
    array_item_num = len(ss_bytes) // padded_size
    assert array_item_num * padded_size == len(ss_bytes)

    num_buckets = array_item_num // sketch_size
    assert num_buckets * sketch_size == array_item_num

    ss_array = [[] for _ in range(num_buckets)]
    pointer = 0
    curr_bucket = 0
    val = 0
    while pointer < len(ss_bytes):
        ss = Integer.from_bytes(ss_bytes[pointer:pointer + padded_size])
        ss_array[curr_bucket].append(ss)

        pointer = pointer + padded_size
        val = val + 1
        if val == sketch_size:
            val = 0
            curr_bucket = curr_bucket + 1
    return ss_array
Esempio n. 14
0
def _import_public_der(curve_name, publickey):

    # We only support P-256 named curves for now
    if curve_name != _curve.oid:
        raise ValueError("Unsupport curve")

    # ECPoint ::= OCTET STRING

    # We support only uncompressed points
    order_bytes = _curve.order.size_in_bytes()
    if len(publickey) != (1 + 2 * order_bytes) or bord(publickey[0]) != 4:
        raise ValueError("Only uncompressed points are supported")

    point_x = Integer.from_bytes(publickey[1:order_bytes+1])
    point_y = Integer.from_bytes(publickey[order_bytes+1:])
    return construct(curve="P-256", point_x=point_x, point_y=point_y)
Esempio n. 15
0
    def verify(self, msg_hash, signature):
        """Check if a certain (EC)DSA signature is authentic.

        Args:
          msg_hash (hash object):
            The hash that was carried out over the message.
            This is an object belonging to the :mod:`Cryptodome.Hash` module.
            Under mode ``'fips-186-3'``, the hash must be a FIPS
            approved secure hash (SHA-2 or SHA-3).

          signature (``bytes``):
            The signature that needs to be validated.

        :raise ValueError: if the signature is not authentic
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        if self._encoding == 'binary':
            if len(signature) != (2 * self._order_bytes):
                raise ValueError("The signature is not authentic (length)")
            r_prime, s_prime = [
                Integer.from_bytes(x) for x in (signature[:self._order_bytes],
                                                signature[self._order_bytes:])
            ]
        else:
            try:
                der_seq = DerSequence().decode(signature, strict=True)
            except (ValueError, IndexError):
                raise ValueError("The signature is not authentic (DER)")
            if len(der_seq) != 2 or not der_seq.hasOnlyInts():
                raise ValueError(
                    "The signature is not authentic (DER content)")
            r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1])

        if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
            raise ValueError("The signature is not authentic (d)")

        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        result = self._key._verify(z, (r_prime, s_prime))
        if not result:
            raise ValueError("The signature is not authentic")
        # Make PyCryptodome code to fail
        return False
Esempio n. 16
0
def full_simulation_counts(key_template, hospital_counts):
    '''Runs a full simulation of an encrypted sum'''
    padded_size = int(np.round(key_template.p.size_in_bits() / 8))
    num_hospitals = len(hospital_counts)
    round0a = [hospital_round0a(key_template) for _ in range(num_hospitals)]
    round0a_transmissions = [x['transmit'] for x in round0a]
    round0b = hub_round0b(key_template, round0a_transmissions)
    key_public = round0b['key_public']
    hospital_keys = [x['private_key'] for x in round0a]

    round1a_start = time.perf_counter()
    round1a = [
        encrypt(key_public, pow(Integer(4), Integer(int(count)),
                                key_public.p)).export_val()
        for count in hospital_counts
    ]
    round1a_time = time.perf_counter() - round1a_start

    round1b_start = time.perf_counter()
    round1b = sum([CipherText.byte_init(key_public, x)
                   for x in round1a]).export_val()
    round1b_time = time.perf_counter() - round1b_start

    round2a_start = time.perf_counter()
    round2a = [
        shared_secret(hk, CipherText.byte_init(key_public,
                                               round1b)).to_bytes(padded_size)
        for hk in hospital_keys
    ]
    round2a_time = time.perf_counter() - round2a_start

    round2b_start = time.perf_counter()
    round2b_sec = Integer(1)
    encrypted_sum = CipherText.byte_init(key_public, round1b)
    for k in range(num_hospitals):
        round2b_sec = (round2b_sec *
                       Integer.from_bytes(round2a[k])) % key_public.p
    s_inv = pow(
        round2b_sec, key_public.p - 2, key_public.p
    )  # modular multiplicative inverse https://stackoverflow.com/questions/4798654/modular-multiplicative-inverse-function-in-python

    decrypted_sum = (s_inv * encrypted_sum.c2) % key_public.p

    load_precomputed_discrete_log4_table(
    )  # using precomputation instead of naive method

    logged_sum = discrete_log4(key_public, decrypted_sum)
    round2b_time = time.perf_counter() - round2b_start

    ans_dict = {}
    ans_dict['round0a_time'] = sum(x['time'] for x in round0a)
    ans_dict['round0b_time'] = round0b['time']
    ans_dict['round1a_time'] = round1a_time
    ans_dict['round1b_time'] = round1b_time
    ans_dict['round2a_time'] = round2a_time
    ans_dict['round2b_time'] = round2b_time
    return logged_sum, ans_dict
Esempio n. 17
0
    def _bits2int(self, bstr):
        """See 2.3.2 in RFC6979"""

        result = Integer.from_bytes(bstr)
        q_len = self._order.size_in_bits()
        b_len = len(bstr) * 8
        if b_len > q_len:
            result >>= (b_len - q_len)
        return result
Esempio n. 18
0
    def _bits2int(self, bstr):
        """See 2.3.2 in RFC6979"""

        result = Integer.from_bytes(bstr)
        q_len = self._order.size_in_bits()
        b_len = len(bstr) * 8
        if b_len > q_len:
            result >>= (b_len - q_len)
        return result
Esempio n. 19
0
def _import_public_der(curve_oid, ec_point):
    """Convert an encoded EC point into an EccKey object

    curve_name: string with the OID of the curve
    ec_point: byte string with the EC point (not DER encoded)

    """

    # We only support P-256 named curves for now
    if curve_oid != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" %
                                    curve_oid)

    # See 2.2 in RFC5480 and 2.3.3 in SEC1
    # The first byte is:
    # - 0x02:   compressed, only X-coordinate, Y-coordinate is even
    # - 0x03:   compressed, only X-coordinate, Y-coordinate is odd
    # - 0x04:   uncompressed, X-coordinate is followed by Y-coordinate
    #
    # PAI is in theory encoded as 0x00.

    order_bytes = _curve.order.size_in_bytes()
    point_type = bord(ec_point[0])

    # Uncompressed point
    if point_type == 0x04:
        if len(ec_point) != (1 + 2 * order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:order_bytes + 1])
        y = Integer.from_bytes(ec_point[order_bytes + 1:])
    # Compressed point
    elif point_type in (0x02, 0x3):
        if len(ec_point) != (1 + order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:])
        y = (x**3 - x * 3 + _curve.b).sqrt(_curve.p)  #  Short Weierstrass
        if point_type == 0x02 and y.is_odd():
            y = _curve.p - y
        if point_type == 0x03 and y.is_even():
            y = _curve.p - y
    else:
        raise ValueError("Incorrect EC point encoding")

    return construct(curve="P-256", point_x=x, point_y=y)
Esempio n. 20
0
def _import_public_der(curve_oid, ec_point):
    """Convert an encoded EC point into an EccKey object

    curve_name: string with the OID of the curve
    ec_point: byte string with the EC point (not DER encoded)

    """

    # We only support P-256 named curves for now
    if curve_oid != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid)

    # See 2.2 in RFC5480 and 2.3.3 in SEC1
    # The first byte is:
    # - 0x02:   compressed, only X-coordinate, Y-coordinate is even
    # - 0x03:   compressed, only X-coordinate, Y-coordinate is odd
    # - 0x04:   uncompressed, X-coordinate is followed by Y-coordinate
    #
    # PAI is in theory encoded as 0x00.

    order_bytes = _curve.order.size_in_bytes()
    point_type = bord(ec_point[0])
    
    # Uncompressed point
    if point_type == 0x04:
        if len(ec_point) != (1 + 2 * order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:order_bytes+1])
        y = Integer.from_bytes(ec_point[order_bytes+1:])
    # Compressed point
    elif point_type in (0x02, 0x3):
        if len(ec_point) != (1 + order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:])
        y = (x**3 - x*3 + _curve.b).sqrt(_curve.p)    #  Short Weierstrass
        if point_type == 0x02 and y.is_odd():
            y = _curve.p - y
        if point_type == 0x03 and y.is_even():
            y = _curve.p - y
    else:
        raise ValueError("Incorrect EC point encoding")

    return construct(curve="P-256", point_x=x, point_y=y)
Esempio n. 21
0
def deserialize_ElGamalPublicKey(bytestring):
    '''constructs an ElGamal Public Key from a bytestring'''
    padded_size = len(bytestring) // 3
    assert padded_size * 3 == len(bytestring), "Wrong bytestring length"
    p = Integer.from_bytes(bytestring[:padded_size])
    g = Integer.from_bytes(bytestring[padded_size:2 * padded_size])
    y = Integer.from_bytes(bytestring[2 * padded_size:])
    return ElGamal.construct((p, g, y))

    def export_val(self):
        '''Returns a bytestring.'''
        padded_size = int(np.round(key.p.size_in_bits() / 8))
        return self.c1.to_bytes(padded_size) + self.c2.to_bytes(padded_size)

    @classmethod
    def byte_init(cls, key, bytestring):
        '''Returns a Ciphertext from a bytestring containing c1 and c2'''
        padded_size = int(np.round(key.p.size_in_bits() / 8))
        assert (len(bytestring) == 2 * padded_size)
        c1 = Integer.from_bytes(bytestring[:padded_size])
        c2 = Integer.from_bytes(bytestring[padded_size:])
        return cls(key, c1, c2)
Esempio n. 22
0
def _import_private_der(encoded, passphrase, curve_oid=None):

    # See RFC5915 https://tools.ietf.org/html/rfc5915
    #
    # ECPrivateKey ::= SEQUENCE {
    #           version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
    #           privateKey     OCTET STRING,
    #           parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
    #           publicKey  [1] BIT STRING OPTIONAL
    #    }

    private_key = DerSequence().decode(encoded, nr_elements=(3, 4))
    if private_key[0] != 1:
        raise ValueError("Incorrect ECC private key version")

    try:
        parameters = DerObjectId(explicit=0).decode(private_key[2]).value
        if curve_oid is not None and parameters != curve_oid:
            raise ValueError("Curve mismatch")
        curve_oid = parameters
    except ValueError:
        pass

    if curve_oid is None:
        raise ValueError("No curve found")

    for curve_name, curve in _curves.items():
        if curve.oid == curve_oid:
            break
    else:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" %
                                    curve_oid)

    scalar_bytes = DerOctetString().decode(private_key[1]).payload
    modulus_bytes = curve.p.size_in_bytes()
    if len(scalar_bytes) != modulus_bytes:
        raise ValueError("Private key is too small")
    d = Integer.from_bytes(scalar_bytes)

    # Decode public key (if any)
    if len(private_key) == 4:
        public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value
        public_key = _import_public_der(public_key_enc, curve_oid=curve_oid)
        point_x = public_key.pointQ.x
        point_y = public_key.pointQ.y
    else:
        point_x = point_y = None

    return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y)
Esempio n. 23
0
    def sign(self, msg_hash):
        """Produce the DSA/ECDSA signature of a message.

        :parameter msg_hash:
            The hash that was carried out over the message.
            The object belongs to the :mod:`Cryptodome.Hash` package.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used
            in combination with SHA-512.
        :type msg_hash: hash object

        :return: The signature as a *byte string*
        :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key
        :raise TypeError: if the (EC)DSA key has no private half
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        # Generate the nonce k (critical!)
        nonce = self._compute_nonce(msg_hash)

        # Perform signature using the raw API
        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        sig_pair = self._key._sign(z, nonce)

        # Encode the signature into a single byte string
        if self._encoding == 'binary':
            output = b"".join([long_to_bytes(x, self._order_bytes)
                                 for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            # Ecdsa-Sig-Value  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            output = DerSequence(sig_pair).encode()

        return output
Esempio n. 24
0
    def sign(self, msg_hash):
        """Compute the DSA/ECDSA signature of a message.

        Args:
          msg_hash (hash object):
            The hash that was carried out over the message.
            The object belongs to the :mod:`Cryptodome.Hash` package.
            Under mode ``'fips-186-3'``, the hash must be a FIPS
            approved secure hash (SHA-2 or SHA-3).

        :return: The signature as ``bytes``
        :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key
        :raise TypeError: if the (EC)DSA key has no private half
        """

        if not self._key.has_private():
            raise TypeError("Private key is needed to sign")

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        # Generate the nonce k (critical!)
        nonce = self._compute_nonce(msg_hash)

        # Perform signature using the raw API
        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        sig_pair = self._key._sign(z, nonce)

        # Encode the signature into a single byte string
        if self._encoding == 'binary':
            output = b"".join(
                [long_to_bytes(x, self._order_bytes) for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            # Ecdsa-Sig-Value  ::=  SEQUENCE  {
            #   r   INTEGER,
            #   s   INTEGER
            # }
            output = DerSequence(sig_pair).encode()

        return output
Esempio n. 25
0
    def sign(self, msg_hash):
        """Produce the DSS signature of a message.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message.
            The object belongs to the `Cryptodome.Hash` package.

            Under mode *'fips-186-3'*, the hash must be a FIPS
            approved secure hash (SHA-1 or a member of the SHA-2 family),
            of cryptographic strength appropriate for the DSA key.
            For instance, a 3072/256 DSA key can only be used
            in combination with SHA-512.

        :Return: The signature encoded as a byte string.
        :Raise ValueError:
            If the hash algorithm is incompatible to the DSA key.
        :Raise TypeError:
            If the DSA key has no private half.
        """

        if not self._valid_hash(msg_hash):
            raise ValueError("Hash is not sufficiently strong")

        # Generate the nonce k (critical!)
        nonce = self._compute_nonce(msg_hash)

        # Perform signature using the raw API
        z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
        sig_pair = self._key._sign(z, nonce)

        # Encode the signature into a single byte string
        if self._encoding == 'binary':
            output = b("").join([long_to_bytes(x, self._order_bytes)
                                 for x in sig_pair])
        else:
            # Dss-sig  ::=  SEQUENCE  {
            #               r       OCTET STRING,
            #               s       OCTET STRING
            # }
            output = DerSequence(sig_pair).encode()

        return output
Esempio n. 26
0
    def _sign_message(privkey, msg, k=None):
        """
        create DSA signed message
        @arg privkey ... privatekey as DSA obj
        @arg msg     ... message to sign
        @arg k       ... override random k
        """

        k = k or random.StrongRandom().randint(2, privkey.q - 1)
        # generate msg hash
        # sign the messages using privkey
        h = SHA1.new(msg).digest()

        # taken from pycryptodome
        # Perform signature using the raw API
        order_bytes = (Integer(privkey.q).size_in_bits() - 1) // 8 + 1
        z = Integer.from_bytes(h[:order_bytes])
        r, s = privkey._sign(z, k)

        return h, (r, s), privkey.publickey()
Esempio n. 27
0
File: RSA.py Progetto: ZurTor/TorMe
def _import_openssh_private_rsa(data, password):

    from ._openssh import (import_openssh_private_generic, read_bytes,
                           read_string, check_padding)

    ssh_name, decrypted = import_openssh_private_generic(data, password)

    if ssh_name != "ssh-rsa":
        raise ValueError("This SSH key is not RSA")

    n, decrypted = read_bytes(decrypted)
    e, decrypted = read_bytes(decrypted)
    d, decrypted = read_bytes(decrypted)
    iqmp, decrypted = read_bytes(decrypted)
    p, decrypted = read_bytes(decrypted)
    q, decrypted = read_bytes(decrypted)

    _, padded = read_string(decrypted)  # Comment
    check_padding(padded)

    build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)]
    return construct(build)
Esempio n. 28
0
def hospital_round0a(key_template, key_x=None):
    '''The partial key generation phase

    If key_x is set, we'll use that instead of a new random integer

    Returns a dictionary with:
        key_x:      a new Elgamal private key secret share
        private_key: an ElGamal private key using key_x
        curr_y:     a partial public key share
        transmit:   a bytestring encoding of curr_y to send to hub
        time:       amount of time elapsed for this function
    '''
    start = time.perf_counter()
    if key_x:
        x = key_x
    else:
        x = Integer(randint(2, int(key_template.p - 1)))
    curr_y = pow(key_template.g, x, key_template.p)

    padded_size = int(np.round(key_template.p.size_in_bits() / 8))
    curr_y_bytestring = curr_y.to_bytes(padded_size)

    private_key = construct_key(key_template, x)
    assert (private_key.y == curr_y)

    elapsed = time.perf_counter() - start

    assert (Integer.from_bytes(curr_y_bytestring) == curr_y)

    answer_dict = {}
    answer_dict['key_x'] = x
    answer_dict['key_x_bytestring'] = x.to_bytes(padded_size)
    answer_dict['private_key'] = private_key
    answer_dict['private_key_export'] = serialize_ElGamalPrivateKey(
        private_key)
    answer_dict['curr_y'] = curr_y
    answer_dict['transmit'] = curr_y_bytestring
    answer_dict['time'] = elapsed
    return answer_dict
Esempio n. 29
0
def _import_private_der(encoded, passphrase, curve_name=None):

    # ECPrivateKey ::= SEQUENCE {
    #           version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
    #           privateKey     OCTET STRING,
    #           parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
    #           publicKey  [1] BIT STRING OPTIONAL
    #    }

    private_key = DerSequence().decode(encoded, nr_elements=(3, 4))
    if private_key[0] != 1:
        raise ValueError("Incorrect ECC private key version")

    try:
        curve_name = DerObjectId(explicit=0).decode(private_key[2]).value
    except ValueError:
        pass

    if curve_name != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" %
                                    curve_name)

    scalar_bytes = DerOctetString().decode(private_key[1]).payload
    order_bytes = _curve.order.size_in_bytes()
    if len(scalar_bytes) != order_bytes:
        raise ValueError("Private key is too small")
    d = Integer.from_bytes(scalar_bytes)

    # Decode public key (if any, it must be P-256)
    if len(private_key) == 4:
        public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value
        public_key = _import_public_der(curve_name, public_key_enc)
        point_x = public_key.pointQ.x
        point_y = public_key.pointQ.y
    else:
        point_x = point_y = None

    return construct(curve="P-256", d=d, point_x=point_x, point_y=point_y)
Esempio n. 30
0
def _import_private_der(encoded, passphrase, curve_name=None):

    # ECPrivateKey ::= SEQUENCE {
    #           version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
    #           privateKey     OCTET STRING,
    #           parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
    #           publicKey  [1] BIT STRING OPTIONAL
    #    }

    private_key = DerSequence().decode(encoded, nr_elements=(3, 4))
    if private_key[0] != 1:
        raise ValueError("Incorrect ECC private key version")

    try:
        curve_name = DerObjectId(explicit=0).decode(private_key[2]).value
    except ValueError:
        pass

    if curve_name != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_name)

    scalar_bytes = DerOctetString().decode(private_key[1]).payload
    order_bytes = _curve.order.size_in_bytes()
    if len(scalar_bytes) != order_bytes:
        raise ValueError("Private key is too small")
    d = Integer.from_bytes(scalar_bytes)

    # Decode public key (if any, it must be P-256)
    if len(private_key) == 4:
        public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value
        public_key = _import_public_der(curve_name, public_key_enc)
        point_x = public_key.pointQ.x
        point_y = public_key.pointQ.y
    else:
        point_x = point_y = None

    return construct(curve="P-256", d=d, point_x=point_x, point_y=point_y)
Esempio n. 31
0
def hub_round0b(key_template, hospital_public_shares):
    '''Generating the shared public key from a list of partial shares
    from the hospitals as bytestrings

    Returns a dictionary with:
        key_public: a new ElGamal public key
        time: amount of time elapsed for this function
    '''
    start = time.perf_counter()

    key_y = Integer(1)
    for bytestring_y in hospital_public_shares:
        curr_y = Integer.from_bytes(bytestring_y)
        key_y = (curr_y * key_y) % key_template.p
    key_public = ElGamal.construct((key_template.p, key_template.g, key_y))
    elapsed = time.perf_counter() - start

    answer_dict = {}
    answer_dict['key_public'] = key_public
    answer_dict['curr_y'] = key_y
    # answer_dict['transmit'] = key_y_bytestring
    answer_dict['transmit'] = serialize_ElGamalPublicKey(key_public)
    answer_dict['time'] = elapsed
    return answer_dict
Esempio n. 32
0
def hash(msg):
    h_obj = SHA3_256.new()
    h_obj.update(msg.encode())
    return Integer.from_bytes(h_obj.digest())
Esempio n. 33
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key (public or private).

    :Parameters:
      extern_key : (byte) string
        The DSA key to import.

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

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` (binary or PEM)
        - OpenSSH (one line of text, see `RFC4253`_)

        A DSA *private* key can be in any of the following formats:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSL/OpenSSH (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase : string
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

    :Return: A DSA key object (`DsaKey`).
    :Raise ValueError:
        When the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Esempio n. 34
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

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

        The following formats are supported for an RSA **private key**:

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

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.

    Returns: An RSA key object (:class:`RsaKey`).

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

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            l = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + l])
            keystring = keystring[4 + l:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Esempio n. 35
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b'-----'):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b'ssh-dss '):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b"ssh-dss":
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Esempio n. 36
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key (public or private).

    :Parameters:
      extern_key : (byte) string
        The DSA key to import.

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

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` (binary or PEM)
        - OpenSSH (one line of text, see `RFC4253`_)

        A DSA *private* key can be in any of the following formats:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSL/OpenSSH (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase : string
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

    :Return: A DSA key object (`DsaKey`).
    :Raise ValueError:
        When the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Esempio n. 37
0
File: RSA.py Progetto: ZurTor/TorMe
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private).

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        The following formats are supported for an RSA **private key**:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (text format, introduced in `OpenSSH 6.5`_)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string or byte string):
        For private keys only, the pass phrase that encrypts the key.

    Returns: An RSA key object (:class:`RsaKey`).

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

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    """

    from Cryptodome.IO import PEM

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
        text_encoded = tostr(extern_key)
        openssh_encoded, marker, enc_flag = PEM.decode(text_encoded,
                                                       passphrase)
        result = _import_openssh_private_rsa(openssh_encoded, passphrase)
        return result

    if extern_key.startswith(b'-----'):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b'ssh-rsa '):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if len(extern_key) > 0 and bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Esempio n. 38
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

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

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

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

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

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

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.
    :Type extern_key: string

    :Parameter passphrase:
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.
    :Type passphrase: string

    :Return: An RSA key object (`RsaKey`).

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

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """
    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
            # This is probably an OpenSSH key
            keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
            keyparts = []
            while len(keystring) > 4:
                l = struct.unpack(">I", keystring[:4])[0]
                keyparts.append(keystring[4:4 + l])
                keystring = keystring[4 + l:]
            e = Integer.from_bytes(keyparts[1])
            n = Integer.from_bytes(keyparts[2])
            return construct([n, e])

    if bord(extern_key[0]) == 0x30:
            # This is probably a DER encoded key
            return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Esempio n. 39
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")