예제 #1
0
파일: asn.py 프로젝트: zdzhjx/netius
def asn1_build(node):
    """
    Builds an asn.1 data structure based on pairs of (type, data),
    this function may be used as a generator of a buffer.

    :type node: Tuple
    :param node: The root node of the structure that is going to be
    used as reference for the generation of the asn.1 buffer.
    """

    tag, value = node

    if tag == BIT_STRING:
        yield netius.legacy.chr(BIT_STRING) + asn1_length(len(value)) + value

    elif tag == OCTET_STRING:
        yield netius.legacy.chr(OCTET_STRING) + asn1_length(len(value)) + value

    elif tag == INTEGER:
        value = util.integer_to_bytes(value)
        yield netius.legacy.chr(INTEGER) + asn1_length(len(value)) + value

    elif tag == NULL:
        assert value is None
        yield netius.legacy.chr(NULL) + asn1_length(0)

    elif tag == OBJECT_IDENTIFIER:
        yield netius.legacy.chr(OBJECT_IDENTIFIER) + asn1_length(
            len(value)) + value

    elif tag == SEQUENCE:
        buffer = []
        for item in value:
            generator = asn1_build(item)
            data = b"".join(generator)
            buffer.append(data)
        result = b"".join(buffer)
        yield netius.legacy.chr(SEQUENCE) + asn1_length(len(result)) + result

    else:
        raise netius.GeneratorError("Unexpected tag in template 0x%02x" % tag)
예제 #2
0
def dkim_sign(message,
              selector,
              domain,
              private_key,
              identity=None,
              separator=":"):
    separator = netius.legacy.bytes(separator)
    identity = identity or "@" + domain

    headers, body = mime.rfc822_parse(message, strip=False)

    if not identity.endswith(domain):
        raise netius.GeneratorError("Identity must end with domain")

    headers = dkim_headers(headers)
    body = dkim_body(body)

    include_headers = [name.lower() for name, _value in headers]
    sign_headers = [
        header for header in headers if header[0].lower() in include_headers
    ]
    sign_names = [name for name, _value in sign_headers]

    hash = hashlib.sha256()
    hash.update(body)

    body_digest = hash.digest()
    body_hash = base64.b64encode(body_digest)
    body_hash = netius.legacy.str(body_hash)

    creation = time.time()
    creation = int(creation)
    creation_s = str(creation)

    names = separator.join(sign_names)
    names = netius.legacy.str(names)

    sign_fields = [
        ("v", "1"),
        ("a", "rsa-sha256"),
        ("c", "simple/simple"),
        ("d", domain),
        ("i", identity),
        ("l", len(body)),
        ("q", "dns/txt"),
        ("s", selector),
        ("t", creation_s),
        ("h", names),
        ("bh", body_hash),
        ("b", ""),
    ]

    signature = "DKIM-Signature: " + "; ".join("%s=%s" % field
                                               for field in sign_fields)
    if type(signature) == netius.legacy.UNICODE:
        signature = signature.encode("utf-8")
    signature = dkim_fold(signature)

    hash = hashlib.sha256()
    for name, value in sign_headers:
        hash.update(name)
        hash.update(b":")
        hash.update(value + b"\r\n")

    hash.update(signature)
    digest = hash.digest()

    digest_info = asn.asn1_gen((asn.SEQUENCE, [
        (asn.SEQUENCE, [
            (asn.OBJECT_IDENTIFIER, asn.HASHID_SHA256),
            (asn.NULL, None),
        ]),
        (asn.OCTET_STRING, digest),
    ]))

    modulus = private_key["modulus"]
    exponent = private_key["private_exponent"]
    modulus_s = util.integer_to_bytes(modulus)
    modulus_l = len(modulus_s)

    digest_l = len(digest_info)
    delta_l = modulus_l - digest_l - 3
    delta_l = 0 if delta_l < 0 else delta_l

    if digest_l + 3 > modulus_l:
        raise netius.GeneratorError("Hash too large for modulus")

    base = b"\x00\x01" + b"\xff" * delta_l + b"\x00" + digest_info
    base_i = util.bytes_to_integer(base)

    signature_i = rsa.rsa_crypt(base_i, exponent, modulus)
    signature_s = util.integer_to_bytes(signature_i, length=modulus_l)

    signature += base64.b64encode(signature_s) + b"\r\n"
    return signature
예제 #3
0
파일: rsa.py 프로젝트: zdzhjx/netius
def rsa_exponents(prime_1, prime_2, number_bits, basic=True):
    """
    Generates both the public and the private exponents for
    the rsa cryptography system taking as base the provided
    prime numbers and the amount of bits for the values.

    :type prime_1: int
    :param prime_1: The first prime number use for rsa.
    :type prime_2: int
    :param prime_2: The second prime number use for rsa.
    :type number_bits: int
    :param number_bits: The number of bits that are going to be
    used for the generation of the values.
    :type basic: bool
    :param basic: If the basic approach to the generation of the
    public exponent should be taken into account.
    :rtype: Tuple
    :return: The tuple containing the generated public and
    private keys (properly tested).
    """

    # calculates the modulus and the phi value for the
    # modulus, as the y are going to be used for calculus
    modulus = prime_1 * prime_2
    phi_modulus = (prime_1 - 1) * (prime_2 - 1)

    # starts by setting the is first flag so that the first iteration
    # of the public exponent generation cycle is taking into account
    # the possible basic flag value for the public exponent
    is_first = True

    # iterates continuously to find a valid public exponent, one
    # that satisfies the relative prime
    while True:
        # make sure e has enough bits so we ensure "wrapping" through
        # modulus (n value) note that if the this is the first attempt
        # to create a public exponent and the basic mode is active the
        # number chosen is the "magic" number (compatibility)
        public_exponent = calc.prime(max(8, number_bits // 2))
        if is_first and basic:
            public_exponent = 65537
            is_first = False

        # checks if the exponent and the modulus are relative primes
        # and also checks if the exponent and the phi modulus are relative
        # primes, for that situation a valid public exponent has been fond
        # and the cycle may be broken
        is_relative = calc.relatively_prime(public_exponent, modulus)
        is_relative_phi = calc.relatively_prime(public_exponent, phi_modulus)
        if is_relative and is_relative_phi: break

    # retrieves the result of the extended euclid greatest common divisor,
    # this value is going to be used as the basis for the calculus of the
    # private exponent for the current operation
    d, l, _e = calc.egcd(public_exponent, phi_modulus)
    private_exponent = l

    # in case the greatest common divisor between both is not one, the values
    # are not relative primes and an exception must be raised
    if not d == 1:
        raise netius.GeneratorError(
            "The public exponent '%d' and the phi modulus '%d' are not relative primes"
            % (public_exponent, phi_modulus))

    # calculates the inverse modulus for both exponent and in case it's not one
    # an exception is raised about the problem
    inverse_modulus = (public_exponent * private_exponent) % phi_modulus
    if not inverse_modulus == 1:
        netius.GeneratorError(
            "The public exponent '%d' and private exponent '%d' are not multiplicative inverse modulus of phi modulus '%d'"
            % (public_exponent, private_exponent, phi_modulus))

    # creates the tuple that contains both the public and the private
    # exponent values that may be used for rsa based cryptography
    return (public_exponent, private_exponent)