Esempio n. 1
0
def test_dsa_attack():
    x = randint(1, q)
    y = pow(g, x, p)
    test_keypair = DSAKeypair(y, x, g, p, q)
    k = 710184121617032319901844589822607487992346783541
    sig = dsa_sign(SIGN_MSG, test_keypair, k=k)

    attack_keypair = get_attack_keypair(SIGN_MSG, sig, y, k)
    assert attack_keypair.private == x

    dsa_sign(SIGN_MSG, attack_keypair, k=k)
Esempio n. 2
0
def BreakDSA(m1, m2, publicKey, dsa_params):
    # m1 and m2 are interchangeable, but if you compute m1['s'] - m2['s']
    # (and the rest accordingly), you get a negative K, which is not valid
    # according to the spec, and our implementation hangs trying to sign
    # a message.
    k = rsa.invmod((m2['s'] - m1['s']), dsa_params['Q'])
    k *= (int(m2['m'], 16) - int(m1['m'], 16))

    top = (m1['s'] * k) - int(m1['m'], 16)
    bottom = rsa.invmod(m1['r'], dsa_params['Q'])
    privateKey = (top * bottom) % dsa_params['Q']

    # Derive the public key from the private key and compare it
    # with the one we know.
    testPub = dsa.modexp(dsa_params['G'], privateKey, dsa_params['P'])
    if testPub == publicKey:
        print('[**] Success!')
        print('K:', k)
        print('X:', privateKey)

        # Sign one of the two messages with the private key and compare
        # the signature with the one we got from the file.
        sig = dsa.dsa_sign(dsa_params['Q'],
                           dsa_params['P'],
                           dsa_params['G'],
                           privateKey,
                           int('0x' + m1['m'], 16),
                           k=k)
        if sig == (m1['r'], m1['s']):
            print('[**] Broken private key passes validation')
            return True

    return False
Esempio n. 3
0
def BreakDSA(m1, m2, publicKey, dsa_params):
	# m1 and m2 are interchangeable, but if you compute m1['s'] - m2['s']
	# (and the rest accordingly), you get a negative K, which is not valid
	# according to the spec, and our implementation hangs trying to sign
	# a message.
	k = rsa.invmod((m2['s'] - m1['s']), dsa_params['Q'])
	k *= (int(m2['m'], 16) - int(m1['m'], 16))

	top = (m1['s'] * k) - int(m1['m'], 16)
	bottom = rsa.invmod(m1['r'], dsa_params['Q'])
	privateKey = (top * bottom) % dsa_params['Q']

	# Derive the public key from the private key and compare it
	# with the one we know.
	testPub = dsa.modexp(dsa_params['G'], privateKey, dsa_params['P'])
	if testPub == publicKey:
		print('[**] Success!')
		print('K:', k)
		print('X:', privateKey)

		# Sign one of the two messages with the private key and compare
		# the signature with the one we got from the file.
		sig = dsa.dsa_sign(dsa_params['Q'], dsa_params['P'], dsa_params['G'], privateKey,
						   int('0x' + m1['m'], 16), k=k)
		if sig == (m1['r'], m1['s']):
			print('[**] Broken private key passes validation')
			return True

	return False
Esempio n. 4
0
def test_find_repeated_nonce():
    # This is just a brute force attack
    for sig1, sig2 in combinations(map(itemgetter(0), SIGNATURES), 2):
        assert sig1 != sig2
        # r = g^k % p % q so if k is repeated so is r
        if sig1.r == sig2.r:
            break

    s_inv = mod_inverse(sig1.s - sig2.s, q)
    k = ((hash_msg(sig1.msg) - hash_msg(sig2.msg)) * s_inv) % q
    attack_keypair = get_attack_keypair(sig1.msg, sig1, y, k)
    assert dsa_sign(sig1.msg, attack_keypair, k) == sig1
    assert dsa_sign(sig2.msg, attack_keypair, k) == sig2
    secret_str = '{:02x}'.format(attack_keypair.private)
    hash_obj = sha1(secret_str.encode('utf-8'))
    digest = hash_obj.hexdigest()
    assert digest == 'ca8f6f7c66fa362d40760d135b763eb8527d3d52'
Esempio n. 5
0
def Generator0():
	dsa_params = {
		'Q': int("0xf4f47f05794b256174bba6e9b396a7707e563c5b", 16),
 		'P': int("0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1", 16),
		'G': 0,
	}

	privateKey, publicKey = dsa.generate_pair(dsa_params['P'], dsa_params['G'], dsa_params['Q'])

	sig = dsa.dsa_sign(dsa_params['Q'], dsa_params['P'], dsa_params['G'], privateKey, dsa.HashMessage(b'And now for something completely different'))
	print(sig)

	res = dsa.dsa_verify(sig[0], sig[1], dsa_params['G'], dsa_params['P'], dsa_params['Q'], publicKey, dsa.HashMessage(b'And now for something completely different'))
	print(res)
Esempio n. 6
0
def test_recover_keypair():
    y = 0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17
    sig = DSASignature(SIGN_MSG,
                       r=548099063082341131477253921760299949438196259240,
                       s=857042759984254168557880549501802188789837994940)

    # We know nonce is between 0 and 2^16
    for k in range(0, 2**16):
        attack_keypair = get_attack_keypair(SIGN_MSG, sig, y, k)
        test_sig = dsa_sign(SIGN_MSG, attack_keypair, k=k)
        if sig.r == test_sig.r and sig.s == test_sig.s:
            secret_str = '{:02x}'.format(attack_keypair.private)
            hash_obj = sha1(secret_str.encode('utf-8'))
            digest = hash_obj.hexdigest()
            assert digest == '0954edd5e0afe5542a4adf012611a91912a3ec16'
            break
Esempio n. 7
0
def GeneratorPPlus1():
	dsa_params = {
		'Q': int("0xf4f47f05794b256174bba6e9b396a7707e563c5b", 16),
 		'P': int("0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1", 16),
	}
	dsa_params['G'] = dsa_params['P'] + 1

	privateKey, publicKey = dsa.generate_pair(dsa_params['P'], dsa_params['G'], dsa_params['Q'])

	# The generated signature is verified against any string, provided the public
	# key is correct.
	sig = dsa.dsa_sign(dsa_params['Q'], dsa_params['P'], dsa_params['G'], privateKey, dsa.HashMessage(b'Hello world!'))
	res = dsa.dsa_verify(sig[0], sig[1], dsa_params['G'], dsa_params['P'], dsa_params['Q'], publicKey, dsa.HashMessage(b'Goodbye world!'))
	if res:
		print('[**] Attack with G=P+1 successful.')
	else:
		print('[!!] Attack with G=P+1 failed.')
Esempio n. 8
0
		return

	print('[**] Success!')
	print('K:', k)
	print('X:', brokenKey)
	return brokenKey, k
	

if __name__ == '__main__':
	message = b'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'
	r = 548099063082341131477253921760299949438196259240
	s = 857042759984254168557880549501802188789837994940

	dsa_params = {
    	'Q': int("0xf4f47f05794b256174bba6e9b396a7707e563c5b", 16),
    	'P': int("0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1", 16),
    	'G': int("5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291", 16),
    }

    # To verify we have found the right k and private key, we sign the same message
    # using both of them. If the signatures match with the one we got from the
    # challenge, it is correct.
	brokenKey, brokenK = BreakDSA(dsa_params['P'], dsa_params['G'], dsa_params['Q'], r, s)
	sig = dsa.dsa_sign(dsa_params['Q'], dsa_params['P'], dsa_params['G'], brokenKey,
					   dsa.HashMessage(message), k=brokenK)

	if sig == (r, s):
		print('[**] The signatures (with real and broken private key) match!')
	else:
		print('[!!] The signatures (with real and broken private key) do not match!')
Esempio n. 9
0
        'Q':
        int("0xf4f47f05794b256174bba6e9b396a7707e563c5b", 16),
        'P':
        int(
            "0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1",
            16),
        'G':
        int(
            "5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291",
            16),
    }

    # To verify we have found the right k and private key, we sign the same message
    # using both of them. If the signatures match with the one we got from the
    # challenge, it is correct.
    brokenKey, brokenK = BreakDSA(dsa_params['P'], dsa_params['G'],
                                  dsa_params['Q'], r, s)
    sig = dsa.dsa_sign(dsa_params['Q'],
                       dsa_params['P'],
                       dsa_params['G'],
                       brokenKey,
                       dsa.HashMessage(message),
                       k=brokenK)

    if sig == (r, s):
        print('[**] The signatures (with real and broken private key) match!')
    else:
        print(
            '[!!] The signatures (with real and broken private key) do not match!'
        )