Beispiel #1
0
def key_gen(size: int = 2048, randomFunction=None, saving=False, Verbose=False):
    """
    RSA key generation.

    n: number of bits for safe prime generation.\n

    randomFunction: prng choosen for random prime number generation (default = randbits from secrets module).

    As a transitional measure, the use of RSA-based signature and confidentiality mechanisms with a key size of at least 2000 bits remain conform for the year 2023.

    saving: True if you want to save the private key to a file.
    """

    sizeB = size // 2

    # 1- Choose two distinct prime numbers p and q

    if Verbose:
        print(f"Let's try to generate two distinct prime numbers p and q of {size} bits.")

    p, q = prng.randomPrime(sizeB, randomFunction, Verbose=Verbose), prng.randomPrime(sizeB, randomFunction, Verbose=Verbose)

    # 2- Compute n = pq.
    n = p * q  # new modulus

    # 3- Compute λ(n), where λ is Carmichael's totient function.
    # since p and q are prime, λ(p) = φ(p) = p − 1 and likewise λ(q) = q − 1. Hence λ(n) = lcm(p − 1, q − 1).
    carmichaelTotient = ut.lcm(p - 1, q - 1)

    # 4- Choosing e, part of the public key
    e = rd.randrange(1, carmichaelTotient)

    while not ut.coprime(e, carmichaelTotient) or bm.hammingWeight(e) > (0.995 * sizeB):
        e = rd.randrange(1, carmichaelTotient)
        # e having a short bit-length and small Hamming weight results in more efficient encryption
        # https://en.wikipedia.org/wiki/Hamming_weight

    # 5- Chossing d, modular multiplicative inverse of e modulo carmichaelTotient(n)
    d = multGroup.inv(e, carmichaelTotient)  # Private Key exponent

    #  p, q, and λ(n) must also be kept secret because they can be used to calculate d. In fact, they can all be discarded after d has been computed.
    del p, q, carmichaelTotient

    public_key, private_key = (n, e), (n, d)

    if saving:
        public_key = it.writeKeytoFile(public_key, "public_key", config.DIRECTORY_PROCESSING, ".kpk")
        it.writeKeytoFile(private_key, "private_key", config.DIRECTORY_PROCESSING, ".kpk")

    if Verbose:
        print("\nYour private key has been generated Bob, keep it safe and never distibute them !")
        print("\nThe public key has been generated, send this to your Alice: ", end="")

        it.prGreen(public_key)

    if not saving:
        return (public_key, private_key)
Beispiel #2
0
def chooseAndSend(accord: tuple,
                  secret=None,
                  n: int = 2048,
                  saving=False,
                  Verbose=False):
    """
    Choose a secret integer randomly and send a ciphered result to someone.

    n number of bits choosen for generating the integer randomly.
    """

    p, g = accord

    if not secret:
        secret_integer = rd.randrange(2, n)
        if Verbose:
            print(
                f"This is your secret integer, keep it safe: {secret_integer}")
    else:
        secret_integer = secret

    toSend = ut.square_and_multiply(g, secret_integer, p)

    if saving:
        toSend = it.writeKeytoFile(toSend, "dH_sendable")

    if Verbose:
        print("Here's what to send to the other one: ", end="")
        it.prGreen(toSend)

    return secret_integer
Beispiel #3
0
def encrypt(M: bytes, publicKey, saving: bool = False):
    """
    Encrypt a message M to make him sendable.
    """

    assert isinstance(M, bytes)

    n, e = publicKey

    def process(m):
        return ut.square_and_multiply(m, e, n)

    # First, turn M into int
    Mint = bm.bytes_to_int(M)

    if Mint < n:
        # That's a short message
        m = Mint
        e = process(m)

    else:
        # M is a longer message, so it's divided into blocks
        size = (it.getKeySize(publicKey) // 8) - 1

        e = [process(bm.bytes_to_int(elt)) for elt in bm.splitBytes(M, size)]

    if saving:
        e = it.writeKeytoFile(e, "encrypted", config.DIRECTORY_PROCESSING, ".kat")

    return e
Beispiel #4
0
def signing(M: bytes, privateK: tuple = None, saving: bool = False, Verbose: bool = False):
    """
    Signing the message (M).
    You need to attach this signature to the message.
    """

    assert isinstance(M, bytes)

    from ..hashbased import hashFunctions as hashF

    if not privateK:
        privateK = it.extractKeyFromFile("private_key")

    size = it.getKeySize(privateK)  # Get key size

    if Verbose:
        print("Hashing in progress...")

    hm = hashF.sponge(M, size)
    # base64 to int
    hm = bm.bytes_to_int(bm.mult_to_bytes(hm))

    if Verbose:
        print(f"hm = {hm}")
        print("Hashing done.\n")

    # raises it to the power of d (modulo n)
    # same thing as decrypting
    n, d = privateK
    sign = ut.square_and_multiply(hm, d, n)

    if saving:
        sign = it.writeKeytoFile(sign, "RSA_signature")

    return sign
Beispiel #5
0
def signing(M: bytes,
            privateK: tuple = None,
            saving: bool = False,
            Verbose: bool = False):
    """
    Signing a message M (bytes).
    """

    from ..hashbased import hashFunctions as hashF

    # y choosed randomly between 1 and p-2 with condition than y coprime to p-1
    if not privateK:
        privateK = it.extractKeyFromFile("private_key")

    p, g, x = privateK

    size = it.getKeySize(privateK)

    # M = bm.fileToBytes(M)
    # M = "Blablabla".encode()

    if Verbose:
        print("Hashing in progress...")

    hm = hashF.sponge(M, size)
    # #base64 to int
    hm = bm.bytes_to_int(bm.mult_to_bytes(hm))

    if Verbose:
        print("Hashing done.\n")

    p1 = p - 1

    k = rd.randrange(2, p - 2)

    while not ut.coprime(k, p1):
        k = rd.randrange(2, p - 2)

    if Verbose:
        print(f"Your secret integer is: {k}")

    s1 = ut.square_and_multiply(g, k, p)

    s2 = (multGroup.inv(k, p1) * (hm - x * s1)) % p1

    # In the unlikely event that s2 = 0 start again with a different random k.

    if s2 == 0:
        if Verbose:
            print("Unlikely, s2 is equal to 0. Restart signing...")
        signing(M, privateK, saving, Verbose)

    else:
        sign = (s1, s2)

        if saving:
            sign = it.writeKeytoFile(sign, "elG_signature")

        return sign
Beispiel #6
0
def compute(accord: tuple, L: list, saving=False):
    """
    accord <= common agreement
    L <= (secret_int, sended)
    """
    secret_int, sended = L

    shared_secret = ut.square_and_multiply(sended, secret_int, accord[0])

    if saving:
        return it.writeKeytoFile(shared_secret, "dH_shared_key")

    return shared_secret
Beispiel #7
0
def encrypt(M: bytes, publicKey, saving: bool = False):

    assert isinstance(M, bytes) or isinstance(M, bytearray)

    p, g, h = publicKey

    def process_of_c1_c2(m):
        y = rd.randrange(1, p - 1)

        # shared secret -> g^xy
        c1 = ut.square_and_multiply(g, y, p)

        s = ut.square_and_multiply(h, y, p)
        c2 = (m * s) % p

        return (c1, c2)

    Mint = bm.bytes_to_int(M)

    if Mint < p:
        # That's a short message
        m = Mint
        e = process_of_c1_c2(m)

    else:
        # M is a longer message, so it's divided into blocks
        # You need to choose a different y for each block to prevent
        # from Eve's attacks.

        size = (it.getKeySize(publicKey) // 8) - 1

        e = [
            process_of_c1_c2(bm.bytes_to_int(elt))
            for elt in bm.splitBytes(M, size)
        ]

    if saving:
        e = it.writeKeytoFile(e, "encrypted", config.DIRECTORY_PROCESSING,
                              ".kat")

    return e
Beispiel #8
0
def key_gen(n: int = 2048,
            primeFount=True,
            easyGenerator: bool = False,
            randomFunction=None,
            saving=False,
            Verbose=False) -> tuple:
    """
    ElGamal key generation.

    n: number of bits for safe prime generation.\n

    primeFount = prime number's fountain used, put tuple of primes into this variable.\n

    easyGenerator: generate appropriated safe prime number according to quadratic residues properties.\n

    randomFunction: prng choosen for random prime number generation (default = randbits from secrets module).

    saving: True if you want to save the private key to a file.
    """

    if not primeFount:

        if Verbose:
            print(f"Let's try to generate a safe prime number of {n} bits.")

        s = prng.safePrime(n, randomFunction, easyGenerator)

    else:
        primeFount = it.extract_safe_primes(n, False, Verbose)
        s = primeFount

    p, q = s  # safe_prime and Sophie Germain prime

    if Verbose:
        print(f"Let's find the generator for p: {p} , safe prime number.\n")

    # Generate an efficient description of a cyclic group G, of order q with generator g.
    if easyGenerator:
        # https://en.wikipedia.org/wiki/Quadratic_residue#Table_of_quadratic_residues
        if Verbose:
            print(
                f"Easy generator => gen = 12 (condition in prime generation) or (4, 9) (for every prime)"
            )

        gen = rd.choice([12, 4, 9])

    else:
        gen = generator(p, q)

    if Verbose: print(f"generator found : {gen}\n")

    # The description of the group is (g, q, p)
    # When p=2q+1, they are the exact same group as Gq.
    # The prime order subgroup has no subgroups being prime.
    # This means, by using Gq, you don't have to worry about an adversary testing if certain numbers are quadratic residues or not.

    # The message space MUST be restrained to this prime order subgroup.

    x = rd.randrange(1, p - 1)  # gcd(x, p) = 1

    h = ut.square_and_multiply(gen, x, p)

    # The private key consists of the values (G, x).
    private_key = (p, gen, x)

    if saving:
        it.writeKeytoFile(private_key, "private_key",
                          config.DIRECTORY_PROCESSING, ".kpk")

    if Verbose:
        print(f"\nYour private key has been generated Alice, keep it safe !")

    # The public key consists of the values (G, q, g, h).
    # But we saved only (p, g, h) cause q = (p-1)//2

    public_key = (p, gen, h)

    if saving:
        public_key = it.writeKeytoFile(public_key, "public_key",
                                       config.DIRECTORY_PROCESSING, ".kpk")

    if Verbose:
        print(f"\nThe public key has been generated too : ", end="")

        print(public_key)

    if not saving:
        return (public_key, private_key)