Esempio n. 1
0
def invertGalois2(toInv: object):
    """
    Invert given {array of bits, bytes, int} in GF()

    ! You need to initialize the Galois_Field before !
    ! You need to have a dictionary file available !

    Output: bytes

    """

    d = int(config.DEGREE / 8)
    toInv = bm.mult_to_bytes(toInv)

    if config.GALOIS_WATCH or config.IN_CREATION:
        config.WATCH_INVERSION_NUMBER += 1
        exTime = time.time()

        # A(x) . A(x)^-1 congruent to 1 mod P(x)
        # where P(x) irreductible polynomial of given degree
        # A ^ p^n - 2 = inverted

        inv = poly_exp_mod_2(bm.bytes_to_int(toInv), config.NBR_ELEMENTS - 2,
                             config.IRRED_POLYNOMIAL)
        inv = inv.to_bytes(bm.bytes_needed(inv), "big")

        config.WATCH_GLOBAL_INVERSION += time.time() - exTime

    else:
        inv = config.INVERSIONS_BOX[bm.bytes_to_int(toInv)]

    return bm.zfill_b(inv, d)
Esempio n. 2
0
    def GHASH64(H, A, C, X, i):
        n = len(C)
        m = len(A)

        if i <= m:
            # A1 = A[1-1]
            return gz2.poly_mult_mod_2(
                bm.bytes_to_int(bm.b_op(X, A[i - 1], "XOR")), H, p)

        if i <= m + n:
            return gz2.poly_mult_mod_2(
                bm.bytes_to_int(bm.b_op(X, C[i - m - 1], "XOR")), H, p)

        if i == m + n + 1:
            return gz2.poly_mult_mod_2(
                a=bm.bytes_to_int(
                    bm.b_op(
                        b1=gz2.poly_mult_mod_2(
                            bm.bytes_to_int(bm.b_op(X, lenb(A), "XOR")), H,
                            p).to_bytes(8, "big"),
                        b2=lenb(C),
                        ope="XOR",
                    )),
                b=H,
                mod=p,
            )
Esempio n. 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
Esempio n. 4
0
def IV(arr, key="y/B?E(H+MbQeThVm".encode()):
    """
    The IV must, in addition to being unique, be unpredictable at encryption time.

    Return a 8 bytes array.
    """

    # Select a random encrypted message as initial vector to transform.
    import secrets as sr

    r1 = sr.randbelow(len(arr))
    r2 = sr.randbits(8)
    message = bm.bytes_to_int(arr[r1]) ^ r2
    message = bm.mult_to_bytes(message)

    # Let's use the principle of hmac
    # The basic idea is to concatenate the key and the message, and hash them together.
    # https://pymotw.com/3/hmac/

    import hmac
    import hashlib

    # Default algorithm for hmac is MD5, it's not the most secure
    # so let's use SHA-1

    digest_maker = hmac.new(key, message, hashlib.sha1)
    digest = digest_maker.hexdigest()

    return bytearray(bytes.fromhex(digest)[:8])
Esempio n. 5
0
def verifying(M: bytes, sign: int, pK: tuple = None):
    """
    Verify given signature of message M with corresponding public key's.
    """

    assert isinstance(M, (bytes, bytearray))

    from ..hashbased import hashFunctions as hashF

    if not pK:
        pK = it.extractKeyFromFile("public_key")

    size = it.getKeySize(pK)

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

    # If the signature is in base64
    if not isinstance(sign, int):
        sign = it.getIntKey(sign)

    n, e = pK
    # raises the signature to the power of e (modulo n)
    # (as when encrypting a message)
    if sign > n:
        print("Signature > modulus")

    test = ut.square_and_multiply(sign, e, n)

    if test == (hm % n):
        return True

    return False
Esempio n. 6
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
Esempio n. 7
0
def verifying(M: bytes, sign: tuple, publicKey: tuple = None):
    """
    Verify given signature of message M with corresponding public key's.
    """
    assert isinstance(M, (bytes, bytearray))

    from ..hashbased import hashFunctions as hashF

    if not publicKey:
        publicKey = it.extractKeyFromFile("public_key")

    p, g, h = publicKey
    size = it.getKeySize(publicKey)

    hm = hashF.sponge(M, size)

    hm = bm.bytes_to_int(bm.mult_to_bytes(hm))

    if not isinstance(sign, tuple):
        b64data = sign
        sign = it.getIntKey(b64data[1:], b64data[0])

    s1, s2 = sign

    if (0 < s1 < p) and (0 < s2 < p - 1):

        test1 = (ut.square_and_multiply(h, s1, p) *
                 ut.square_and_multiply(s1, s2, p)) % p
        test2 = ut.square_and_multiply(g, hm, p)

        if test1 == test2:
            return True
        return False

    raise ValueError
Esempio n. 8
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
Esempio n. 9
0
    def pad(N, r):
        iN = bm.bytes_to_int(N)
        lN = int.bit_length(iN)

        # Number of 0 to add
        b = (r - ((lN + 3) % r)) % r

        # Padding using the SHA-3 pattern 10*1: a 1 bit, followed by zero or more 0 bits (maximum r − 1) and a final 1 bit.
        op = ((iN | (1 << b + lN + 1)) << 1) ^ 1

        return bm.mult_to_bytes(op)
Esempio n. 10
0
def xorshiftperso(evenOrodd: int = 0, nBits: int = 512):
    """
    Personal implementation of a random number generator using XORshift

    nBits: number of bits needed (e.g 2048 bits to output 2048 bits lenght's number).

    return even or odd number:
         - 0 odd
         - 1 even
         - both
    """

    assert nBits > 23
    bytesT = int(nBits / 8)

    # Unpredictable random seed
    state1, state2 = os.urandom(bytesT), os.urandom(bytesT)

    a, b = bm.bytes_to_int(state1), bm.bytes_to_int(state2)

    a ^= bm.bytes_to_int(bm.circularRotation(state1, 0, 23))
    b ^= bm.bytes_to_int(bm.circularRotation(state2, 1, 17))

    # Generate full bytes of 1 of the size of the array
    size = int("0x" + "".join(["FF" for _ in range(0, nBits)]), 16)
    # For n bits
    a &= size
    b &= size

    r = b + a

    if evenOrodd and r & 1:
        # Bitwsing and with "-2" (number with all bits set to one except lowest one)
        # always kills just the LSB of your number and forces it to be even
        r &= -2
    elif not evenOrodd and not (r & 1):
        # Force the number to the next odd
        r |= 1

    return r
Esempio n. 11
0
def encrypt(M: bytes, publicKey, saving: bool = False):

    assert isinstance(M, (bytes, bytearray))

    p, g, h = publicKey

    def process(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(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(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
Esempio n. 12
0
def nullBits(H, nbZ):
    """
    Chech if the given hash ends with nBz null bits

    H -> bytearray of the hash
    nbZ -> number of null bits
    """
    H = bm.bytes_to_int(H)

    for i in range(0, nbZ):
        if ((H >> i) & 1) == 1:
            return False

    return True
Esempio n. 13
0
def getIntKey(data: bytes, keyNumber: int = 1):
    """
    Convert base64 key's into tuples of keyNumber integers.
    """
    assert isinstance(data, (bytes, bytearray))

    if isinstance(keyNumber, str):
        keyNumber = int(keyNumber)

    if keyNumber != 1:
        keys = ()
        kL = []
        for i in range(keyNumber):
            kL.append(int.from_bytes(data[i * 2:i * 2 + 2], "big"))

        padding = keyNumber * 2
        for i, s in enumerate(kL):
            keys += (int.from_bytes(data[padding:padding + s], "big"), )
            padding = padding + s
    else:
        keys = bm.bytes_to_int(data)

    return keys
Esempio n. 14
0
def md5(block):
    """
    Return md5 hash

    block: bytearray of data to hash
    """

    import math

    # Done using the Wikipedia algorithm

    def iToB(i):
        return int.to_bytes(i, 4, "little")

    def p32(a, b):
        return (a + b) % (1 << 32)

    s = [
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        7,
        12,
        17,
        22,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        5,
        9,
        14,
        20,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        4,
        11,
        16,
        23,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21,
        6,
        10,
        15,
        21,
    ]

    K = []
    for i in range(64):
        K.append((math.floor(2 ** 32 * abs(math.sin(i + 1)))) % (1 << 32))

    iN = bm.bytes_to_int(block)
    lN = len(block) * 8

    # Number of 0 to add
    b = 512 - ((lN + 1) % 512)

    lN = int.from_bytes(lN.to_bytes(8, byteorder="little"), byteorder="big", signed=False)

    iN = (((iN << 1) | 1) << b) ^ lN

    block = bm.mult_to_bytes(iN)

    b512 = bm.splitBytes(block, 64)

    h1 = 0x67452301
    h2 = 0xEFCDAB89
    h3 = 0x98BADCFE
    h4 = 0x10325476

    for b5 in b512:

        blocks = bm.splitBytes(b5, 4)

        A = h1
        B = h2
        C = h3
        D = h4

        for i in range(64):
            if i <= 15:
                F = (B & C) | (~B & D)
                g = i
            elif i <= 31:
                F = (D & B) | (~D & C)
                g = (5 * i + 1) % 16
            elif i <= 47:
                F = B ^ C ^ D
                g = (3 * i + 5) % 16
            else:
                # C xor (B or (not D))
                F = C ^ (B | ~D) % (1 << 32)
                g = (7 * i) % 16

            # F + A + K[i] + M[g]
            try:
                F = p32(p32(p32(F, A), K[i]), int.from_bytes(blocks[g], "little"))
            except IndexError:
                print(i, K, blocks[g])
                raise Exception("Error")

            A = D
            D = C
            C = B
            # B + leftrotate(F, s[i])
            B = p32(B, ((F << s[i]) | (F >> (32 - s[i]))))

        h1 = p32(A, h1)
        h2 = p32(B, h2)
        h3 = p32(C, h3)
        h4 = p32(D, h4)

    return bm.packSplittedBytes([iToB(h1), iToB(h2), iToB(h3), iToB(h4)])
Esempio n. 15
0
def GCM(arr, encrypt=True, aad=""):
    """
    GCM is CTR mode with authentification of additional data (AAD) authenticated with multiplication in a Galois Field

    arr: array of bytearray of 8 bytes of data to encrypt/decrypt
    encrypt: boolean, true to encypt
    aad: string of additional authenticated data
    """

    if encrypt:
        iv = IV(arr)
    else:
        iv = IV_action(arr)
        # Integrity Check Balue
        icv = IV_action(arr)

    # Additional authenticated data (AAD), which is denoted as A
    A = []

    if encrypt:
        if aad != "":
            aadc = aad.encode()

            if len(aadc) > 1 << 64:
                raise Exception("Too much AAD")

            A = bm.splitBytes(aadc, 8)
            A[-1] = bm.zfill_b(A[-1], 8)
    else:
        header = arr[0]
        epos = int.from_bytes(header, "big")
        A = arr[1:epos]
        arr = arr[epos:]

    # Encrypted message
    C = []

    # 1 + α + α3 + α4 + α64 - 64 field polynomial
    p = int(
        "10000000000000000000000000000000000000000000000000000000000001111", 2)

    def lenb(i):
        return (len(i) * 8).to_bytes(8, "big")

    def GHASH64(H, A, C, X, i):
        n = len(C)
        m = len(A)

        if i <= m:
            # A1 = A[1-1]
            return gz2.poly_mult_mod_2(
                bm.bytes_to_int(bm.b_op(X, A[i - 1], "XOR")), H, p)

        if i <= m + n:
            return gz2.poly_mult_mod_2(
                bm.bytes_to_int(bm.b_op(X, C[i - m - 1], "XOR")), H, p)

        if i == m + n + 1:
            return gz2.poly_mult_mod_2(
                a=bm.bytes_to_int(
                    bm.b_op(
                        b1=gz2.poly_mult_mod_2(
                            bm.bytes_to_int(bm.b_op(X, lenb(A), "XOR")), H,
                            p).to_bytes(8, "big"),
                        b2=lenb(C),
                        ope="XOR",
                    )),
                b=H,
                mod=p,
            )

    H = bm.bytes_to_int(kasu.kasumi(b"\x00" * 8))

    Y = GHASH64(H, b"", [iv], b"\x00", 1).to_bytes(8, "big")
    E0 = kasu.kasumi(Y)

    n = len(arr)
    m = len(A)

    # equivalent of CTR mode
    for i in range(n):
        config.WATCH_PERCENTAGE = (((n * 2 + m + 1) - ((n * 2 + m + 1) - i)) /
                                   (n * 2 + m + 1)) * 100
        exTime = time.time()

        # treats the rightmost 32bits of its argument as a nonnegative integer with the least significant bit on the right, and increments this value modulo 2^32
        Y = Y[:4] + (
            (int.from_bytes(Y[-4:], "big") + 1) % 1 << 32).to_bytes(4, "big")
        E = kasu.kasumi(Y)

        C.append(bm.b_op(arr[i], E, "XOR"))

        config.WATCH_GLOBAL_CIPHER += time.time() - exTime
        config.WATCH_BLOC_CIPHER = config.WATCH_GLOBAL_CIPHER / (i + 1)
        config.WATCH_BLOC_KASUMI = config.WATCH_GLOBAL_KASUMI / (i + 1)

    res = C

    # plaintext is in C when we decrypt, me must replace it with the ciphertext
    if not encrypt:
        C = arr

    # first init of X = GHASH64(i=0) = b'\x00'
    X = b"\x00"

    for i in range(n + m + 1):
        config.WATCH_PERCENTAGE = (((n * 2 + m + 1) - ((n * 2 + m + 1) -
                                                       (i + n))) /
                                   (n * 2 + m + 1)) * 100
        exTime = time.time()

        X = GHASH64(H, A, C, X, i + 1).to_bytes(8, "big")

        config.WATCH_GLOBAL_CIPHER += time.time() - exTime
        config.WATCH_BLOC_CIPHER = config.WATCH_GLOBAL_CIPHER / (i + 1)

    icvc = bm.b_op(E0, X, "XOR")

    if not encrypt:
        if icv != icvc:
            print(
                "\nYELLOW: INTEGRITY CHECK CONTROL INCORRECT, AAD HAVE BEEN MODIFIED !!"
            )

    if encrypt:
        IV_action(res, icvc, "store")
        # Adding the IV to the encrypted data
        IV_action(res, iv, "store")

        header = (1 + len(A)).to_bytes(8, "big")
        res = [header] + A + res

    return res