|
2 | 2 |
|
3 | 3 | from cryptographic_functions import modulo_inverse_multiplicative
|
4 | 4 | from cryptographic_functions import shared_functions
|
| 5 | +from math import ceil, sqrt |
5 | 6 | from tabulate import tabulate
|
6 | 7 | import random
|
7 | 8 |
|
@@ -297,6 +298,7 @@ def homomorphic_multiplicative_scheme(public_key, private_key, c_1, c_2, print_m
|
297 | 298 | f'<AUXILIARY 1>Achtung: Die Namen der Variablen können abweichen!</AUXILIARY 1>\n'
|
298 | 299 | f'm = {a_i} * {(b_1 * b_2) % p}\n'
|
299 | 300 | f'm = {m}', end='\n\n')
|
| 301 | + return m |
300 | 302 |
|
301 | 303 |
|
302 | 304 | # ElGamal homomorphic multiplicative decryption
|
@@ -360,3 +362,115 @@ def homomorphic_multiplicative_decryption(public_key, private_key, m_1, c_1, c_2
|
360 | 362 | f'{m} = {m_1} * {m_2} mod {p}\n'
|
361 | 363 | f'{m} = {(m_1 * m_2) % p}', end='\n\n')
|
362 | 364 | return m_2
|
| 365 | + |
| 366 | + |
| 367 | +# ElGamal homomorphic multiplicative decryption with identical random value |
| 368 | +def homomorphic_multiplicative_decryption_k(public_key, m_1, c_1, c_2, print_matrix=False, |
| 369 | + print_linear_factorization=True): |
| 370 | + print(tabulate([['Homomorphe multiplikative Entschlüsselung mit identischem Zufallswert']], tablefmt='fancy_grid')) |
| 371 | + |
| 372 | + # Unpack the public key into its components |
| 373 | + p, g, e = public_key |
| 374 | + |
| 375 | + # Unpack both ciphertexts into its components |
| 376 | + a_1, b_1 = c_1 |
| 377 | + a_2, b_2 = c_2 |
| 378 | + |
| 379 | + # Calculation of m_2 assuming that the random numbers of both ciphertexts are identical |
| 380 | + b_1_i = modulo_inverse_multiplicative.mim(p, b_1, print_matrix, print_linear_factorization, 1) |
| 381 | + m_2 = (b_1_i * b_2 * m_1) % p |
| 382 | + |
| 383 | + # Calculation of m_1_i |
| 384 | + m_1_i = modulo_inverse_multiplicative.mim(p, m_1, print_matrix, print_linear_factorization, 2) |
| 385 | + |
| 386 | + # Calculation path output |
| 387 | + print( |
| 388 | + f'Gegeben sind K(pub) = {{p, g, e}} = {{{p}, {g}, {e}}} mit den Geheimtexten c_1 = {{a_1, b_1}} = ' |
| 389 | + f'{{{a_1}, {b_1}}} und c_2 = {{a_2, b_2}} = {{{a_2}, {b_2}}}. Ebenfalls bekannt ist der zu c_1 zugehörige ' |
| 390 | + f'Klartext m_1 = {m_1}. Unter Ausnutzung des Zugriffs auf die Verschlüsselungsfunktion mit einem identischen ' |
| 391 | + f'Zufallswert k für die Berechnung der Geheimtexte kann nun der Klartext m_2 des Geheimtextes c_2 ermittelt ' |
| 392 | + f'werden.', end='\n\n') |
| 393 | + print( |
| 394 | + f'Der zum Geheimtext c_2 gehörende Klartext m_2 ergibt sich aus:\n' |
| 395 | + f'm_2 = b_1^-1 * b_2 * m_1 mod p\n' |
| 396 | + f'<AUXILIARY 1>Achtung: Die Namen der Variablen können abweichen!</AUXILIARY 1>\n' |
| 397 | + f'm_2 = {b_1_i} * {b_2} * {m_1} mod {p}\n' |
| 398 | + f'm_2 = {b_1_i * b_2 * m_1} mod {p}\n' |
| 399 | + f'm_2 = {m_2}', end='\n\n') |
| 400 | + print( |
| 401 | + f'Verifikation:\n' |
| 402 | + f'b_1^-1 * b_2 = m_1^-1 * m_2 mod p\n' |
| 403 | + f'<AUXILIARY 2>Achtung: Die Namen der Variablen können abweichen!</AUXILIARY 2>\n' |
| 404 | + f'{b_1_i} * {b_2} = {m_1_i} * {m_2} mod {p}\n' |
| 405 | + f'{(b_1_i * b_2) % p} = {(m_1_i * m_2) % p}', end='\n\n') |
| 406 | + return m_2 |
| 407 | + |
| 408 | + |
| 409 | +# ElGamal baby-step giant-step |
| 410 | +def bsgs(public_key, print_matrix=False, print_linear_factorization=True): |
| 411 | + print(tabulate([['ElGamal Babystep-Giantstep-Algorithmus']], tablefmt='fancy_grid')) |
| 412 | + |
| 413 | + # Unpack the public key into its components |
| 414 | + p, g, e = public_key |
| 415 | + |
| 416 | + # Print calculation message |
| 417 | + print('Berechnung, bitte warten...', end='\r') |
| 418 | + |
| 419 | + # Calculation of g_i |
| 420 | + g_i = modulo_inverse_multiplicative.mim(p, g, print_matrix, print_linear_factorization, 1) |
| 421 | + |
| 422 | + # Calculation of m |
| 423 | + m = ceil(sqrt(p - 1)) |
| 424 | + |
| 425 | + # Calculation of g^{0...(m-1)} mod p (baby-step) |
| 426 | + tab = {(g ** r) % p: r for r in range(m)} |
| 427 | + |
| 428 | + # Calculation of y |
| 429 | + y = (g ** (m * (p - 2))) % p |
| 430 | + |
| 431 | + # Find match in table (giant-step) |
| 432 | + for q in range(m): |
| 433 | + z = (e * (y ** q)) % p |
| 434 | + if z in tab: |
| 435 | + d = q * m + tab[z] |
| 436 | + break |
| 437 | + |
| 438 | + # Removal of the calculation message |
| 439 | + print(' ' * len('Berechnung, bitte warten...'), end='\r') |
| 440 | + |
| 441 | + # The value of p must be identical in both keys |
| 442 | + if not 'd' in locals(): |
| 443 | + print(f'Der zum öffentlichen Schlüssel K(pub) = {{p, g, e}} = {{{p}, {g}, {e}}} zugehörige private Schlüssel ' |
| 444 | + f'K(priv) = {{p, d}} konnte nicht mittels des Babystep-Giantstep-Algorithmus bestimmt werden.') |
| 445 | + return -1 |
| 446 | + |
| 447 | + # Calculation path output |
| 448 | + print( |
| 449 | + f'Gegeben ist der öffentliche Schlüssel K(pub) = {{p, g, e}} = {{{p}, {g}, {e}}}. Unter Verwendung des' |
| 450 | + f'Babystep-Giantstep-Algorithmus zur Berechnung des diskreten Logarithmus im endlichen Zahlenkörper wird ' |
| 451 | + f'nachfolgend der private Schlüssel K(priv) = {{p, d}} bestimmt.', end='\n\n') |
| 452 | + print( |
| 453 | + f'Zunächst ist die Menge der Paare M = {{(e * g^-r, r) | 0 ≤ r < m}} mod p zu bestimmen.\n' |
| 454 | + f'm = ⌈√(p - 1)⌉\n' |
| 455 | + f'm = ⌈√({p - 1})⌉\n' |
| 456 | + f'm = ⌈{sqrt(p - 1)}⌉\n' |
| 457 | + f'm = {m}', end='\n\n') |
| 458 | + print( |
| 459 | + f'Dabei ergibt sich die folgende Menge der Paare über (e * g^-r, r) mod p\n' |
| 460 | + f'<AUXILIARY 1>Achtung: Die Namen der Variablen können abweichen!</AUXILIARY 1>\n' |
| 461 | + f'({e} * {g}^-{0}, {0}) = ({e} * {g_i ** 0}, {0}) = ({(e * (g_i ** 0)) % p}, {0}) mod {p}\n' |
| 462 | + f'[...]\n' |
| 463 | + f'({e} * {g}^-{d - 1}, {d - 1}) = ({e} * ({g}^-1)^{d - 1}, {d - 1}) = ({e} * {g_i}^{d - 1}, {d - 1}) = ' |
| 464 | + f'({(e * (g_i ** (d - 1))) % p}, {d - 1}) mod {p}\n' |
| 465 | + f'({e} * {g}^-{d}, {d}) = ({e} * ({g}^-1)^{d}, {d}) = ({e} * {g_i}^{d}, {d}) = ({(e * (g_i ** d)) % p}, {d}) ' |
| 466 | + f'mod {p}', end='\n\n') |
| 467 | + print( |
| 468 | + f'Dabei ist zu erkennen, dass das Paar ({(e * (g_i ** d)) % p}, {d}) die Lösung für den diskreten Logarithmus ' |
| 469 | + f'darstellt. Folglich entspricht der private Schlüssel K(priv) = {{p, d}} = {{{p}, {d}}}.', end='\n\n') |
| 470 | + print( |
| 471 | + f'Verifikation mit K(pub) = {{p, g, e}} = {{{p}, {g}, {e}}}:\n' |
| 472 | + f'e = g^d mod p\n' |
| 473 | + f'e = {g}^{d} mod {p}\n' |
| 474 | + f'e = {(g ** d) % p}\n' |
| 475 | + f'{e} = {(g ** d) % p}', end='\n\n') |
| 476 | + return d |
0 commit comments