Some examples:
mod
, %
5 mod 12 = 5
14 mod 12 = 2
83 mod 10 = 3
5 + 3 mod 6 = 8 mod 6 = 2
Example: If we know $n$ which we need to find the $p$ and $q$ values where $p*q=n$:
n = 35
To obtain the possible factors, is needed to brute force trying different combinations, until we find:
p = 5
q = 7
In this case is easy as it's a simple example with small numbers. The idea is to do this with big prime numbers
Another exmample with more bigger prime numbers:
n = 272604817800326282194810623604278579733
From $n$, I don't have a 'direct' way to obtain $p$ and $q$. I need to try by brute force the different values until finding a correct combination.
p = 17975460804519255043
q = 15165386899666573831
n = 17975460804519255043 * 15165386899666573831 = 272604817800326282194810623604278579733
If we do this with non prime numbers:
n = 32
We can factorize 32 = 2 * 2 * 2 * 2 * 2
combining that values in two values X * Y
for example (2*2*2) * (2*2) = 8*4 = 32
we can also take 2 * (2*2*2*2) = 2 * 16 = 32
...
One example with bigger non prime numbers:
n = 272604817800326282227951471308464408608
We can take:
p = 17975460804519255044
q = 15165386899666573832
Or also:
p = 2
q = 136302408900163141113975735654232204304
...
In the real world:
So, we are basing this in the fact that is not easy to factorize big numbers composed by big primes.
p = 3
q = 11
e = 7
value choosen between 1 and λ(n)=20, where λ(n) is not divisible by this valuen = 3 * 11 = 33
λ(n) = (3-1) * (11-1) = 2 * 10 = 20
d
such as 7 * d = 1 mod 20
d = 3
e=7, n=33
d=3, n=33
def egcd(a, b):
if a == 0:
return (b, 0, 1)
g, y, x = egcd(b%a,a)
return (g, x - (b//a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('No modular inverse')
return x%m
def newKeys():
p = number.getPrime(n_length)
q = number.getPrime(n_length)
# pubK e, n
e = 65537
n = p*q
pubK = PubK(e, n)
# privK d, n
phi = (p-1) * (q-1)
d = modinv(e, phi)
privK = PrivK(d, n)
return({'pubK': pubK, 'privK': privK})
m
to Alice, so, will use the Public Key from Alice to encrypt m
m
powered at e
of the public key from Alicen
m = 5
e=7, n=33
c = 5 ^ 7 mod 33 = 78125 mod 33 = 14
def encrypt(pubK, m):
c = (m ** pubK.e) % pubK.n
return c
c
c
powered at d
of the private key of the person to who the message was encryptedn
d=3, n=33
m = 14 ^ 3 mod 33 = 2744 mod 33 = 5
def decrypt(privK, c):
m_d = (c ** privK.d) % privK.n
return m_d
n = pq
e
phi = (p-1)(q-1)
d = e^-1 mod (phi) = e^-1 mod (p-1)(q-1)
# encrypt
c = m^e mod n = m^e mod pq
# decrypt
m' = c^d mod n = c ^(e^-1 mod (p-1)(q-1)) mod pq =
= (m^e)^(e^-1 mod (p-1)(q-1)) mod pq =
= m^(e * e^-1 mod (p-1)(q-1)) mod pq =
= m^(1 mod (p-1)(q-1)) mod pq =
[theorem in which we're not going into details]
a ^ (1 mod λ(N)) mod N = a mod N
[/theorem]
= m mod pq
encryption operation but using PrivK instead of PubK, and PubK instead of PrivK
having a message m
power of m
at d
of the private key from the signer person
evaluated at modulus n
d = 3, n = 33
m=5
s = 5 ** 3 % 33 = 26
def sign(privK, m):
s = (m ** privK.d) % privK.n
return s
m
and the signature s
m
at e
of the public key from the signern
e=7, n=33
m=5
s=26
v = 26**7 % 33 = 5
m
is equivalent to v
) m = 5 = v = 5
def verifySign(pubK, s, m):
v = (s ** pubK.e) % privK.n
return v==m
from two values $a$ and $b$
encrypted are $a_{encr}$ and $b_{encr}$
we can compute the multiplication of the two encrypted values, obtaining the result encrypted
the encrypted result from the multiplication is calculated doing: $c_{encr} = a_{encr} * b_{encr} mod n$
we can decrypt $c_{encr}$ and we will obtain $c$, equivalent to $a * b$
Why:
((a^e mod n) * (b^e mod n)) mod n =
= (a^e * b^e mod n) mod n = (a*b)^e mod n
e=7, n=33
d=3, n=33
a = 5
b = 8
a_encr = 5^7 mod 33 = 78125 mod 33 = 14
b_encr = 8^7 mod 33 = 2097152 mod 33 = 2
c_encr = (14 * 2) mod 33 = 28 mod 33 = 28
c = 28 ^ 3 mod 33 = 21952 mod 33 = 7
c = 7 = a * b % n = 5 * 8 % 33 = 7
, on 5*8 mod 33 = 7
n
enough big, if not the result will be cropped by the modulusdef homomorphic_mul(pubK, a, b):
c = (a*b) % pubK.n
return c
[...]