In [1]:
# all the imports
%pylab inline
from visual_cryptography.visual_cryptography import (ImageLayer,
produce_image_layer_from_real_image)
pylab.rcParams['figure.figsize'] = (18.0, 8.0)
In [2]:
black = 1
white = 0
def plot_matrix(data, title="", ax=None):
if ax is None:
fig, ax = pylab.subplots()
ax.imshow(data, cmap=plt.cm.gray, interpolation='nearest')
if title:
ax.set_title(title)
ax.axis('off')
#pylab.show()
def do_not_show_axis(ax):
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
def plot_function(f, xmin=-10, xmax=10, ax=None, title=""):
if ax is None:
fig, ax = pylab.subplots()
X = arange(xmin, xmax, 0.1)
Y = [f(x) for x in X]
ax.plot(X, Y)
if title:
ax.set_title(title)
def plot_function_in_finite_field(f, xmin=-10, xmax=10, ax=None, title=""):
if ax is None:
fig, ax = pylab.subplots()
X = arange(xmin, xmax, 1)
Y = [f(x) for x in X]
ax.plot(X, Y, 'r--', alpha=0.75)
ax.plot(X, Y, 'bo')
if title:
ax.set_title(title)
def show_sub_pixel(matrix, ax=None, title=""):
"""Draw Hinton diagram for visualizing a weight matrix."""
ax = ax or pylab.gca()
if title:
ax.set_title(title)
max_weight = 2**np.ceil(numpy.log(np.abs(matrix).max())/np.log(2))
ax.patch.set_facecolor('white')
ax.set_aspect('equal', 'box')
do_not_show_axis(ax)
for (x,y),w in np.ndenumerate(matrix):
if w == 0:
color = "white"
else:
color = "gray"
size = 0.8
rect = plt.Rectangle([y - size / 2, x - size / 2], size, size,
facecolor=color, edgecolor="black")
ax.add_patch(rect)
ax.autoscale_view()
ax.invert_yaxis()
#pylab.show()
def show_text(text, ax=None):
ax = ax or pylab.gca()
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
ax.text(0.5, 0.5,text , color='black',
fontsize=40,
#fontname='Courier',
horizontalalignment='center',
verticalalignment='center',
)
ax.axis('off')
def plot_tuple_of_pixels(pixel_1, pixel_2, axs):
show_text("(", axs[0])
show_sub_pixel(pixel_1, ax=axs[1])
show_text(",", axs[2])
show_sub_pixel(pixel_2, ax=axs[3])
show_text(")", axs[4])
Let's present the Shamir and Naor ideas to encrypt a message in a secure way such that the decrypting does not require any computers or calculations.
In [3]:
img = produce_image_layer_from_real_image("cat-512.png")
shares = img.produce_two_shares_from_image()
plot_matrix(shares[0], title='first transparent')
In [4]:
plot_matrix(shares[1], title='second transparent')
In [5]:
sum_of_the_shares = shares[0] * shares[1] # note that matplotlib associates 0 to black and 1 to white
plot_matrix(sum_of_the_shares, title="both transparents")
In [6]:
fig, (ax0, ax1, ax2 ) = plt.subplots(ncols=3)
img=matplotlib.image.imread('calvin_pixels.png')
do_not_show_axis(ax0)
ax0.imshow(img)
show_sub_pixel([[white]*10]*10, ax=ax1, title="transparent 1")
show_sub_pixel([[white]*10]*10, ax=ax2, title="transparent 2")
To encrypt a pixel, we'll decompose it in $m$ sub-pixel. Each sub-pixel can be black or white.
The humain eye will approximate the $m$ sub-pixel in a pixel
If there are enought black sub-pixels, the eye will see a black pixel
If there are not enought of black sub-pixels, the eye will see a white pixel
In [7]:
fig, (ax0, ax1, ax2 ) = plt.subplots(ncols=3)
show_sub_pixel([[black, black, black],
[black, black, black],
[black, black, black]],
ax=ax0,
title="a black pixel")
show_sub_pixel([[white, black, black],
[black, black, white],
[white, black, black]],
ax=ax1,
title="a black pixel")
show_sub_pixel([[white, white, black],
[white, black, white],
[white, black, white]],
ax=ax2,
title="a white pixel")
To help the humain, we need the black to be as dark as possible and the white to be as bright as possible
A pixel is said to be black if it is made of at least $d \leq m$ black sub-pixels
A pixel is said to be white if it is made of no more than $d - \alpha m$ black sub-pixels
In [8]:
import matplotlib as mpl
fig, ax = pylab.subplots()
cmap = mpl.cm.gray_r
norm = mpl.colors.Normalize(vmin=5, vmax=10)
cb = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
orientation='horizontal')
ax.set_axis_off()
ax.text(0.9, 0.5, 'black',
horizontalalignment='center',
verticalalignment='center',
rotation='vertical',
size="20",
color="white",
transform=ax.transAxes)
ax.text(0.1, 0.5, 'white',
horizontalalignment='center',
verticalalignment='center',
rotation='vertical',
size="20",
color="black",
transform=ax.transAxes)
pylab.show()
In [9]:
fig, (ax0, ax1, ax2 ) = plt.subplots(ncols=3)
plot_matrix(shares[0], title='first transparent', ax=ax0)
plot_matrix(shares[1], title='second transparent', ax=ax1)
plot_matrix(shares[1] * shares[0], title='stacked transparents', ax=ax2)
In [10]:
show_sub_pixel([[black, white, black],
[white, black, white],
[white, white, white]], title="[1 0 1 0 1 0 0 0 0]")
In [11]:
fig, (ax0, ax1, ax2, ax3, ax4 ) = plt.subplots(ncols=5)
show_sub_pixel([[black, white],
[black, white]], title="[1 0 1 0]", ax=ax0)
show_text("+", ax1)
show_sub_pixel([[black, black],
[white, white]], title="[1 1 0 0]", ax=ax2)
show_text("=", ax3)
show_sub_pixel([[black, black],
[black, white]], title="[1 1 1 0]", ax=ax4)
In [ ]:
$A \sim B$ if $A$ is the same colour as $B$
We create two sets
$W = \{ (r_1, l_1) , (r_2, l_2), \dots, (r_k, l_k) \}$
$K = \{ (g_1, d_1) , (g_2, d_2), \dots, (g_k, d_k) \}$
such that...
$r_i + l_i$ is white
$g_i + d_i$ is black
The cardinality of $x$ in the multiset $\{r_1, l_1, \dots r_k, l_k\}$ is the same in the multiset $\{g_1, d_1, \dots g_k, d_k\}$.
In [12]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b, c, d : [[a, b], [c, d]]
w, b = white, black
show_text("white={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b, w, b), pixel(w, b, w, b), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w, b, w), pixel(b, w, b, w), axs[8:])
show_text("}", axs[13])
In [13]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b, c, d : [[a, b], [c, d]]
w, b = white, black
show_text("black={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b, w, b), pixel(b, w, b, w), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w, b, w), pixel(w, b, w, b), axs[8:])
show_text("}", axs[13])
In [14]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b, c, d : [[a, b], [c, d]]
w, b = white, black
show_text("white={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b, b, w), pixel(w, b, b, w), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w, w, b), pixel(b, w, w, b), axs[8:])
show_text("}", axs[13])
In [15]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b, c, d : [[a, b], [c, d]]
w, b = white, black
show_text("black={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b, b, w), pixel(b, w, w, b), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w, w, b), pixel(w, b, b, w), axs[8:])
show_text("}", axs[13])
In [16]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b : [[a, b]]
w, b = white, black
show_text("white={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b), pixel(w, b), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w), pixel(b, w), axs[8:])
show_text("}", axs[13])
In [17]:
fig, axs = plt.subplots(ncols=14)
pixel = lambda a, b : [[a, b]]
w, b = white, black
show_text("black={ ", axs[0])
show_text(" ", axs[1])
plot_tuple_of_pixels(pixel(w, b), pixel(b, w), axs[2:])
show_text(",", axs[7])
plot_tuple_of_pixels(pixel(b, w), pixel(w, b), axs[8:])
show_text("}", axs[13])
In [18]:
cheated = produce_image_layer_from_real_image("dog-512.png")
cheated_share = cheated.produce_cheated_image_from_other_share(shares[0])
plot_matrix(cheated_share , title='crafted transparent')
savefig("crafted_transparen.pdf")
In [19]:
plot_matrix(cheated_share * shares[0], title='forged result')
Alice wants to share his swiss bank account number with Bob TheFirst, Bob TheSecond, Bob TheThird,... Bob TheNth such that...
If any $k$ Bobs comes togheter they need to be able to recover the bank account number
If any less that $k$ Bobs comes togheter they need to have no idea whatsoever about the bank account number
***********
***** ***********
** ****** *** ********
**** ****** ** *******
*** ******* ** ******
*** ** * **
*|/------ -------\ ** *
| |=| :===**
| O | | O | }|*
|---- | ---- | |*
| |___ |\/
| |
\ ----- |
\ |
-__ -- -/
In [20]:
fig, (ax0, ax1, ax2) = plt.subplots(ncols=3)
plot_function(lambda x : 2 * x + 1, title="$2 \cdot x + 1$", ax=ax0)
plot_function(lambda x : 2 * x**2 + 1, title="$2 \cdot x^2 + 1$", ax=ax1)
plot_function(lambda x : 2 * x**3 - 2 * x**2 + 1, title="$2 \cdot x^3 - 2 \cdot x^2 + 1$", ax=ax2)
In [21]:
fig, (ax0, ax1, ax2) = plt.subplots(ncols=3)
p = lambda x : 2 * x + 1
plot_function(p, title="$2 \cdot x + 1$", ax=ax0)
ax0.plot([-7, 7] , [p(-7), p(7)], "ro")
p = lambda x : 2 * x**2 + 1
plot_function(p, title="$2 \cdot x^2 + 1$", ax=ax1)
ax1.plot([-7, 0, 7], [p(-7), p(0), p(7)], "ro")
p = lambda x : 2 * x**3 - 2 * x**2 + 1
plot_function(p, title="$2 \cdot x^3 - 2 \cdot x^2 + 1$", ax=ax2)
ax2.plot([-7, -3, 3, 7], [p(-7), p(-3), p(3), p(7)], "ro")
show()
In [22]:
fig, ax = plt.subplots()
b = 0
d = 1
c = lambda a : -100 - 7**2 * a
P = lambda a : (lambda x: a * x**3 + b * x**2 + x * c(a) + d)
for i in range(-12, 12, 3):
plot_function(P(i), ax=ax)
p = P(1)
ax.plot([-7, 0, 7] , [p(-7), p(0), p(7)], "ro")
ax.set_title("Polynomials passing through $(-7, 701), (0, 1), (7, -699)$")
None
In [23]:
p = lambda x : 5243902191291828 + 7873787349 * x + 7893478934 * x ** 2
credit_card_number = 5243902191291828
valentin_secret = p(1) # keyboard random number
didier_secret = p(2)
... $$P(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 $$ $$5243949512782262 = a_0 + a_1 \cdot 2 + a_2 \cdot 4 $$ $$a_0 = 5243949512782262 - a_1 \cdot 2 - a_2 \cdot 4$$ $$a_0 = 5243949512782262 - 2\cdot(a_1 \cdot - 2 \cdot a_2)$$ $$a_0 = 5243949512782262 - \text{even number}$$
We could process the original message before wharing it
$$\underbrace{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}_\text{very random number}\underbrace{5243902191291828}_\text{the credit card number}$$
We could work in a more appropriate field
$$\mathbb{Z}/p\mathbb{Z}$$
| x | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 2 | 0 | 2 | 4 | 6 | 1 | 3 | 5 |
| 3 | 0 | 3 | 6 | 2 | 5 | 1 | 4 |
| 4 | 0 | 4 | 1 | 5 | 2 | 6 | 3 |
| 5 | 0 | 5 | 3 | 1 | 6 | 4 | 2 |
| 6 | 0 | 6 | 5 | 4 | 3 | 2 | 1 |
| + | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 1 | 2 | 3 | 4 | 5 | 6 | 0 |
| 2 | 2 | 3 | 4 | 5 | 6 | 0 | 1 |
| 3 | 3 | 4 | 5 | 6 | 0 | 1 | 2 |
| 4 | 4 | 5 | 6 | 0 | 1 | 2 | 3 |
| 5 | 5 | 6 | 0 | 1 | 2 | 3 | 4 |
| 6 | 6 | 0 | 1 | 2 | 3 | 4 | 5 |
In [24]:
fig, (ax0, ax1, ax2) = plt.subplots(ncols=3)
plot_function_in_finite_field(lambda x : (2 * x + 1) % 7, title="$2 \cdot x + 1$ mod 7", ax=ax0)
plot_function_in_finite_field(lambda x : (2 * x**2 + 1) % 7, title="$2 \cdot x^2 + 1$ mod 7", ax=ax1)
plot_function_in_finite_field(lambda x : (2 * x**3 - 2 * x**2 + 1) % 7, title="$2 \cdot x^3 - 2 \cdot x^2 + 1$ mod 7", ax=ax2)
In [25]:
fig, ax = plt.subplots()
f = lambda x : (2 * x**3 - 2 * x**2 + 1) % 7
plot_function_in_finite_field(f, title="$2 \cdot x^3 - 2 \cdot x^2 + 1 mod 7$", ax=ax)
ax.plot([-7, 0, 7], [f(-7), f(0), f(7)], 'rD')
None
In [26]:
fig, ax = plt.subplots()
b = 0
d = 1
c = lambda a : -100 - 7**2 * a
P = lambda a : (lambda x: (a * x**3 + b * x**2 + x * c(a) + d) % 7)
for i in range(-12, 12, 3):
plot_function_in_finite_field(P(i), ax=ax)
p = P(1)
ax.plot([-7, 0, 7] , [p(-7), p(0), p(7)], "ro")
ax.set_title("Polynomials passing through $(-7, 1), (0, 1), (7, 1)$")
None
If Francis would have choosen polynomials in $\mathbb{Z}/p\mathbb{Z}$ with $p$ big enough...
Didier could not have easely discarted some numbers
For Didier, a large $p$ in infinite even with the help of $aws$
The objective of this sections is to present the idea of the article how to proof yourself, an article publish by Fiat and Shamir in the year of grace 1987.
In [27]:
fig, (ax0, ax1, ax2 ) = plt.subplots(ncols=3)
img = matplotlib.image.imread('susie.png')
do_not_show_axis(ax0)
ax0.imshow(img)
do_not_show_axis(ax1)
img = matplotlib.image.imread('calvin.gif')
do_not_show_axis(ax2)
ax2.imshow(img)
None
Sign up and send your password
username:
didierpassword:******
The server keeps the the hash of your password
user = {"username": "didier", "hash": "cXdlcnR5MTIzNA=="}
Each time you authenticate, the server verifies that the password you provides hashed to the same value
assert hash(password) == user["hash"]
Sign up and send the hash of your password
totally private password:
******username:didierhash:cXdlcnR5MTIzNA==
The server keeps the the hash
user = {"username": "didier", "hash": "cXdlcnR5MTIzNA=="}
Each time you authenticate, there is a dance between the you and the server to allow the server to gain the knowledge that you know something that
Bob and Alice exchange some information while they know they are talking to the each other (sign up)
In that exchange, Alice will tell Bob that she knows something
Each time Alice will authenticate, Alice will provide enough information to Bob to demonstrate that she knows the information but without giving any factual proofs.
There are some problems that are easy to solve in $\mathbb{R}$ but very hard to solve in $\mathbb{Z}/n\mathbb{Z}$
completeness: If Alice plays the game, she will be to proof that she is herself with probability 1
soundness: Bob as a probablylity $1/2$ to catch a cheeter, he needs to repeat the protocol until he is convinced
zero-knowledge: Proof by intimidation
In [ ]:
In [ ]: