Come generare funzioni booleane casuali in Algebraic Normal Form in Python?

2

Sto guardando uno schema di crittografia a chiave pubblica basato su SAT e mi sono ispirato a sfidarmi a scrivere un'implementazione di questo schema di crittografia su Python.

Una parte della codifica del codice sarebbe quella di generare funzioni booleane casuali in forma normale algebrica in un certo insieme di variabili binarie. Sono nuovo nella codifica e non riesco a capire come generare le funzioni casuali richieste.

Modifica
Ho già scritto del codice in sage (e fatto diverse esecuzioni in Python) per la generazione delle chiavi. Dal momento che non riesco a inserire il codice in un commento, lo sto mettendo qui. Mentre sono consapevole che il codice potrebbe essere ingenuo, ho controllato con piccoli esempi e mi sembra a posto.

#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)

Ho provato a fare qualcosa per quanto riguarda la crittografia.

#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)

Decodifica:

#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)
    
posta Kristina Dedndreaj 29.06.2016 - 17:55
fonte

1 risposta

1

Baso questa parte della sezione Algoritmi del documento, che è un po 'difficile da capire, quindi gradirei che qualcun altro lo verificasse. Inoltre, spero che tu lo stia facendo per divertimento e non pianifichi di usarlo per una vera crittografia senza un'analisi approfondita da parte di professionisti e accademici,

La funzione pubblica booleana (13) è una serie di clausole ANDed insieme, x -> ^ c_j(x) . Ogni clausola è una serie di sottosezioni ORed insieme, x -> V(...) . Ogni sottocreazione è un elemento dell'input x_[I(i, j)] XORed con qualche segno s(i, j) .

I segni provengono da una matrice di booleani e sono scelti casualmente come 1 o 0, il che è piuttosto semplice, ma prendere gli elementi dall'input è più complicato. L'input è un vettore di booleani e vogliamo un modo casuale per scegliere quale inserire in ogni sottopunto. Quindi, creiamo una matrice di numeri interi m, k e chiamiamola I . Per ogni riga in questa matrice, c_j(x) deve essere true per la chiave privata (poiché saranno ANDed insieme). Quindi, genera una riga di interi casuali (da 1 a n in modo da non uscire dai limiti dell'input) e una fila di segni casuali. Ognuno di questi dovrebbe essere k elementi, poiché saranno le righe delle loro matrici.

Una volta individuate le righe candidate, dobbiamo assicurarci che soddisfino la chiave privata. Quindi, per ogni indice nella riga, ricaviamo una proposizione secondaria per la funzione c_j e assicuriamoci che almeno una sia vera (poiché saranno OR insieme). Ad esempio, i primi elementi potrebbero essere 5 e 1, quindi eseguiamo XOR il quinto elemento della chiave privata con 1 e vediamo se è vero. Continua lungo le righe finché almeno uno è vero, e se lo è, aggiungi le righe alle tue matrici.

Pensando nella direzione opposta, se hai le matrici I e s , puoi controllare abbastanza facilmente una chiave candidata. Per ogni riga delle matrici, assicurati che con il numero intero da I indicizzazione della chiave, ottieni un valore che può essere XORed con il booleano da s .

Prendiamo le righe [1, 3, 2] e [1, 0, 0] e una chiave candidata [1, 1, 0] . Innanzitutto, prendi il primo elemento dalla chiave ( 1 ) e XOR con 1 . Questo ti dà 0 , quindi continua. Prendi il terzo elemento dalla chiave ( 0 ) e XORlo con 0 . Questo dà 0 , quindi continua. Infine, abbiamo XOR il secondo elemento ( 1 ) e il terzo segno ( 0 ) per ottenere 1 . Poiché abbiamo ottenuto un 1 , queste righe funzionano con questa chiave.

    
risposta data 29.06.2016 - 20:15
fonte

Leggi altre domande sui tag