I am looking at A SAT-based Public Key Cryptography Scheme and got inspired to challenge myself to write an implementation of this Cryptography Scheme on Python.
A part of the cipher encoding would be to generate random Boolean functions in Algebraic Normal Form in a certain set of binary variables. I am new to coding and I can not figure out how to generate the required random functions.
EDIT
I have already written some code in sage (and made several runs in Python as well) for the key generation. Since I can't put the code in a comment I am putting it here. While I am conscious that the code might be naive I have checked with small examples and it looks okay to me.
#n-number of binary variables
#m-number of clauses
#k-number of literals in each clause
def key_gen(n,m,k):
print("the list of variables")
print([var('x'+str(n)) for n in range(n+1)]) #listing the variables
print("")
priv=[randint(0,1) for x in range(n)] #choose randomly the private key
pub=matrix(m,k,0) #store the variables used as a m*k matrix
signs=matrix(m,k,0) #store the signs as a m*k matrix
i=0
j=0
while j<m:
clause=sorted((sample(xrange(0,n),k))) #choose k variables at random
sgn=[randint(0,1) for x in range(k)] #choose their signs at random
value=0
for i in xrange(0,k):
value += (mod(sgn[i]+priv[clause[i]],2)) #check the truth value of the clause
if value!=0: #the clause is accepted iff there is
pub[j]=clause #at least one literal with truth value one
signs[j]=sgn
j=j+1
i=i+1
print("")
print("private key")
print(priv)
print("")
print("the matrix of variables ")
print(pub)
print("")
print("the matrix of signs")
print(signs)
I have tried to do something regarding encryption.
#encryption
#n-number of variables
#pub is a m*k-matrix, where in its rows are stored the clauses
#signs-a m*k matrix where are stored the signs of literals
#y-bit to be encrypted
#alpha, beta encryption parameters
def encrypt(n,pub,signs,alpha,beta,y):
if ((beta > len(pub.rows())) or (beta >= alpha)):
print("Encryption is not possible")
else:
m=len(pub.rows())
k=len(pub.columns())
g_alpha=0
for i in xrange(0,alpha):
block=matrix(beta,k,0) #store the tuples of clauses as beta*k matrix
nr=sorted((sample(xrange(0,m),beta))) #choose at random beta clauses
g_beta=0
for j in xrange(0,beta):
block[j]=pub[nr[j]] #store clauses according to their position
B=BooleanPolynomialRing(n,'x')
used_var=[B.gens()[pub[nr[j]][i]] for i in xrange(k)] #store the
c_j=0 #used variables
for i in xrange(0,k):
c_j+=(B.gen(pub[nr[j]][i]) + signs[nr[j]][i]+1) #calculate the negation
zero_list=[0 for x in xrange(k)]
dict={key:value for key,value in zip(used_var,zero_list)}
f=B.random_element()
R=f.subs(dict) #generate R
g_beta+= c_j*R
g_alpha+=g_beta
g=y+g_alpha
print("the encrypted bit is",g)
Decryption:
#priv- a list of numbers
#g-a symbolic expression-the cipher
def decrypt(priv,g):
n=len(priv)
B=BooleanPolynomialRing(n,'x')
A=[B.gen(i) for i in xrange(n)]
f=B(g) #get a Boolean Polynomial from symbolic expression
dict={key:value for key,value in zip(A,priv)}
s=f.subs(dict) #evaluate g(priv)
print('decrypted bit is',s)