예제 #1
0
def insecureVerify(params, public_key, message, tag):
    r, s = tag[0], tag[1]

    hash_obj = sha256.SHA256()
    hash_obj.Update(message)
    msg_hash = hash_obj.Sum() % params["q"]
    s_inv = GroupOp.find_inverse(s, params["q"])
    arg1 = GroupOp.mod_exp(params["g"], (s_inv * msg_hash) % params["q"],
                           params["p"])
    arg2 = GroupOp.mod_exp(public_key, (r * s_inv) % params["q"], params["p"])
    lhs = ((arg1 * arg2) % params["p"]) % params["q"]
    return (lhs == r)
예제 #2
0
def RSAVerifyPKCS15(pub_key, msg, sig):
    verify_against = (GroupOp.mod_exp(sig, pub_key[1], pub_key[0])).to_bytes(
        pub_key[0].bit_length() // 8, byteorder="big")
    begin_correct = verify_against.startswith(b"\x00\x01")
    # strip all of the ff's
    ff_strip = verify_against[2:]
    while ff_strip[0] == 0xff:
        ff_strip = ff_strip[1:]
    correct0 = ff_strip.startswith(b"\x00")
    hash_id_length = SHA1_ASNBitLen // 8
    hash_identifier = int.from_bytes(ff_strip[1:hash_id_length + 1],
                                     byteorder="big")

    if hash_identifier == SHA1_ASN:
        hash_obj = sha1.SHA1()
    elif hash_identifier == SHA256_ASN:
        hash_obj = sha256.SHA256()
    else:
        raise ValueError("Was unable to identify hash alg")

    hash_obj.Update(msg)
    hashed_msg = hash_obj.Sum()

    hash_from_sig = ff_strip[hash_id_length + 1:hash_id_length + 1 + SHA1Len]
    check_val = (hash_from_sig == hashed_msg)
    return check_val and correct0 and begin_correct
예제 #3
0
def generate_public_key(generator, prime):
    secret_val = random.getrandbits(prime.bit_length())
    if secret_val > prime:
        secret_val = secret_val ^ prime
    assert secret_val < prime
    public_val = GroupOp.mod_exp(generator, secret_val, prime)
    assert public_val < prime
    return (secret_val, public_val)
예제 #4
0
def generate_shared_key(secret_val, public_val_from_other, prime):
    print("Secret value is {}, shared value is {}".format(
        secret_val, public_val_from_other))
    shared_key = GroupOp.mod_exp(public_val_from_other, secret_val, prime)
    print(shared_key)
    assert shared_key < prime
    hash_feed = SHA1.SHA1()
    hash_feed.Update(
        shared_key.to_bytes(shared_key.bit_length() + 7 // 8, byteorder='big'))
    return hash_feed.Sum()
예제 #5
0
def insecureSign(params, private_key, message):
    k = random.randrange(1, params["q"])
    r = GroupOp.mod_exp(params["g"], k, params["p"]) % params["q"]

    init_hash = sha1.SHA1()
    init_hash.Update(message)
    hashed_msg_val = int.from_bytes(init_hash.Sum(),
                                    byteorder="big") % params["q"]
    k_inv = GroupOp.find_inverse(k, params["q"])
    s = (k_inv * (hashed_msg_val + private_key * r)) % params["q"]

    return (r, s)
예제 #6
0
def encrypt(pub_key, message):
    if type(message) is str or type(message) is bytes:
        if type(message) is str:
            message = message.encode()
        msg_as_number = int.from_bytes(message, byteorder="big")
    elif type(message) is int:
        msg_as_number = message
    mod, e = pub_key[0], pub_key[1]
    if msg_as_number > mod:
        raise ValueError("Message must be in range of the modulus")
    ct = GroupOp.mod_exp(msg_as_number, e, mod)
    ct = ct.to_bytes((ct.bit_length() + 7) // 8, byteorder="big")
    return ct
예제 #7
0
def attacker(pub_key, old_ct):
    #pick a number rel. prime with the modulus
    random_s = random.randrange(1, pub_key[0])
    while GroupOp.find_gcd(random_s, pub_key[0]) != 1:
        random_s = random.randrange(1, pub_key[0])
    inv_s = GroupOp.find_inverse(random_s, pub_key[0])
    old_ct_as_number = int.from_bytes(old_ct, byteorder="big")
    new_ct = (GroupOp.mod_exp(random_s, pub_key[1], pub_key[0]) *
              old_ct_as_number) % pub_key[0]
    oracle_res = recovery_oracle(
        new_ct.to_bytes((new_ct.bit_length() + 7) // 8, byteorder="big"))
    val = (inv_s * int.from_bytes(oracle_res, byteorder="big")) % pub_key[0]
    print("Original message was {}".format(
        val.to_bytes((val.bit_length() + 7) // 8, byteorder="big")))
예제 #8
0
def DSASign(params, private_key, message, print_k=False, k=0):
    r = 0
    s = 0
    while r == 0 and s == 0:
        if k == 0:
            k = random.randrange(1, params["q"])
        if print_k:
            print("K value is {:x}".format(k))
        r = GroupOp.mod_exp(params["g"], k, params["p"]) % params["q"]

        if r != 0:
            init_hash = sha1.SHA1()
            init_hash.Update(message)
            hashed_msg_val = int.from_bytes(init_hash.Sum(),
                                            byteorder="big") % params["q"]
            k_inv = GroupOp.find_inverse(k, params["q"])
            s = (k_inv * (hashed_msg_val + private_key * r)) % params["q"]

    return (r, s)
예제 #9
0
def main():
    global challenge_params

    # assuming we want to keep the same public key because if we didn't
    # and it was based on the bogus generator then we have big problems

    tag = insecureSign(challenge_params, recovered_priv_key, b"A message")

    # r will be 0 here, s will be k^inv * H(msg)
    # but it really doesn't matter, because the other side needs to
    #  find the inverse of s so as long as s is invertible, you'll
    # validate. This signature would "work" for every message and moreover
    # ANYTHING will work as long as r=0 and s is invert.
    message = b"If music be the food of love, play on; Give me excess of it, that, surfeiting,The appetite may sicken, and so die. --Twelfth Night"
    res = insecureVerify(challenge_params, challenge_public_key, message,
                         (0, 0xdeadbeef))
    print("Generator g = 0\n")
    print("Message: {}, Sig: (0x{:x},0x{:x}), Result: {}".format(
        message, 0, 0xdeadbeef, res))
    # change the generator is p+1 and not
    challenge_params["g"] = challenge_params["p"] + 1
    # I'm going to assume the key was genereated honestly, because if it wasn't
    # we would get g**x = (p+1)**x mod p which is just 1

    choose_random = random.randrange(1, challenge_params["q"])
    r = GroupOp.mod_exp(challenge_public_key, choose_random,
                        challenge_params["p"]) % challenge_params["q"]
    s = (r * GroupOp.find_inverse(
        choose_random, challenge_params["q"])) % challenge_params["q"]
    result = insecureVerify(challenge_params, challenge_public_key,
                            b"Hello, world", (r, s))
    res2 = insecureVerify(challenge_params, challenge_public_key,
                          b"Goodbye, world", (r, s))
    print("Generator g = p + 1")
    print("Message: {}, Random val: 0x{:x}, Sig: (0x{:x},0x{:x}), Result: {}".
          format(b"Hello, world", choose_random, r, s, result))
    print("Message: {}, Random val: 0x{:x}, Sig: (0x{:x}, 0x{:x}), Result: {}".
          format(b"Goodbye, world", choose_random, r, s, res2))
    return
예제 #10
0
def RSASignPKCS15(priv_key, msg):
    msg_encoded = EncodeMessage(msg, priv_key[0])
    sig = GroupOp.mod_exp(msg_encoded, priv_key[1], priv_key[0])
    return sig
예제 #11
0
def generate_generator(prime_p, prime_q):
    g = 1
    while g == 1:
        h = random.randrange(1, prime_p)
        g = GroupOp.mod_exp(h, (prime_p - 1) // prime_q, prime_p)
    return g
예제 #12
0
def DSAKeyGen(params, print_x=False):
    private_key = random.randrange(1, params["q"])
    public_key = GroupOp.mod_exp(params["g"], private_key, params["p"])
    if print_x:
        print("Secret key was {:x}".format(private_key))
    return public_key, private_key
예제 #13
0
def main():
    """
    parameters = DSAParamGen(42, 256)
    pub_key, priv_key = DSAKeyGen(parameters)
    test_msg = b"Lost Lenore"
    tag = DSASign(parameters, priv_key, test_msg)  
    verify = DSAVerify(parameters, pub_key, test_msg, tag)

    if verify:
        print("Passed simple test")
    else:
        print("Failed simple test")

    print("Attempting to use stolen attacker knowledge to recover the private key...")
    for i in range(3):
        temp_pub_key, temp_priv_key = DSAKeyGen(parameters, print_x=True)
        msg = input("Type in message to sign: ").encode("utf-8")
        tag = DSASign(parameters, temp_priv_key, msg, print_k=True)
        k_val = input("Give k value in hex: 0x")
        k = int("0x" + k_val, 16)
        recovered_private_key = AttackerWithKnownSubKeyK(parameters, temp_pub_key, k, msg, tag)
        print("Recovered secret key was {:x}".format(recovered_private_key))
    """
    print("Attempting to crack private key from challenge...")
    msg_str = "For those that envy a MC it can be hazardous to your health\nSo be friendly, a matter of life and death, just like a etch-a-sketch\n"
    print("Checking to make sure the message string is correct...")
    hash_obj = sha1.SHA1()
    hash_obj.Update(msg_str.encode('utf-8'))
    result_hash = int.from_bytes(hash_obj.Sum(), byteorder="big")
    if not hex(result_hash) == "0xd2d0714f014a9784047eaeccf956520045c45265":
        raise ValueError("Object hash is incorrect")

    challenge_tag = (548099063082341131477253921760299949438196259240,
                     857042759984254168557880549501802188789837994940)

    challenge_params = {
        "p":
        0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1,
        "q":
        0xf4f47f05794b256174bba6e9b396a7707e563c5b,
        "g":
        0x5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291
    }
    challenge_public_key = 0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17
    sha_key_fp = 0x0954edd5e0afe5542a4adf012611a91912a3ec16
    for i in range(0, 2**16):
        selector = GroupOp.mod_exp(
            challenge_params["g"], i,
            challenge_params["p"]) % challenge_params["q"]
        if selector == challenge_tag[0]:
            print("Calculated a correct r value!")
            # test k
            potential_priv_key = AttackerWithKnownSubKeyK(
                challenge_params, challenge_public_key, i, msg_str,
                challenge_tag, result_hash)
            key_obj = sha1.SHA1()
            string_feed = hex(potential_priv_key)[2:]
            key_obj.Update(string_feed)
            key = int.from_bytes(key_obj.Sum(), byteorder="big")
            print("Key fp is {:x}".format(key))
            compute_tag = DSASign(challenge_params, potential_priv_key,
                                  msg_str.encode("utf-8"), False, i)
            if compute_tag[1] == challenge_tag[1]:
                print("Success! Key is {}".format(potential_priv_key))
                return
            else:
                print("Failure, correct r but incorrect s")

    return
예제 #14
0
def decrypt(priv_key, ciphertext):
    cipherint = int.from_bytes(ciphertext, byteorder="big")
    mod, d = priv_key[0], priv_key[1]
    pt = GroupOp.mod_exp(cipherint, d, mod)
    pt = pt.to_bytes((pt.bit_length() + 7) // 8, byteorder="big")
    return pt