Package: tno.mpc.encryption-schemes.dgk
TNO MPC Lab - Encryption Schemes - DGKThe TNO MPC lab consists of generic software components, procedures, and functionalities developed and maintained on a regular basis to facilitate and aid in the development of MPC solutions. The lab is a cross-project initiative allowing us to integrate and reuse previously developed MPC functionalities to boost the development of new protocols and solutions.The package tno.mpc.encryption_schemes.dgk is part of the TNO Python Toolbox.Implementation of the DGK encryption scheme with support for precomputation of randomness. The
encryption scheme supports positive and negative numbers, as well as fixed point encoding of
numbers. Homomorphic addition of ciphertexts, negation of ciphertexts, and multiplication of
ciphertexts with integral scalars has been included as well.Limitations in (end-)use: the content of this software package may solely be used for applications that comply with international export control laws.This implementation of cryptographic software has not been audited. Use at your own risk.DocumentationDocumentation of the tno.mpc.encryption_schemes.dgk package can be foundhere.InstallEasily install the tno.mpc.encryption_schemes.dgk package using pip:$python-mpipinstalltno.mpc.encryption_schemes.dgkNote:A significant performance improvement can be achieved by installing the GMPY2 library.$python-mpipinstall'tno.mpc.encryption_schemes.dgk[gmpy]'If you wish to use the tno.mpc.communication module you can use:$python-mpipinstall'tno.mpc.encryption_schemes.dgk[communication]'If you wish to run the tests you can use:$python-mpipinstall'tno.mpc.encryption_schemes.dgk[tests]'UsageThe DGK scheme can be used with and without support for full decryptions. When full decryptions are not supported one
can only use the private key to determine whether a ciphertext is zero or not.Full decryption support requires the scheme to pre-compute and store a lookup table for all possible plaintexts. This
table can become impractically large when the plaintext space is big.Below we list usage examples in both cases.Basic usage (with full decryption):fromtno.mpc.encryption_schemes.dgkimportDGKif__name__=="__main__":# initialize DGK (with full decryption support) with v_p and v_q of length t=160 bits, n of length 1000 bits.# The message space contains 10009 values and the precision of this scheme is 1 decimaldgk_scheme=DGK.from_security_parameter(v_bits=160,n_bits=1000,u=10009,precision=1)# encrypt the number 8.1ciphertext1=dgk_scheme.encrypt(8.1)# add 0.9 to the original plaintextciphertext1+=0.9# multiply the original plaintext by 10ciphertext1*=10# encrypt the number 10ciphertext2=dgk_scheme.encrypt(10)# add both encrypted numbers togetherencrypted_sum=ciphertext1+ciphertext2# ...communication...# decrypt the encrypted sum to 100decrypted_sum=dgk_scheme.decrypt(encrypted_sum)assertdecrypted_sum==100Usage (without full decryption)fromtno.mpc.encryption_schemes.dgkimportDGKif__name__=="__main__":# initialize DGK (without full decryption support) with v_p and v_q of length t=160 bits, n of length 2048 bits.# The message space contains 10009 values and the precision of this scheme is 1 decimaldgk_scheme=DGK.from_security_parameter(v_bits=160,n_bits=1000,u=10009,precision=1,full_decryption=False)# encrypt the number 8.1ciphertext1=dgk_scheme.encrypt(8.1)# add 0.9 to the original plaintextciphertext1+=0.9# multiply the original plaintext by 10ciphertext1*=10# encrypt the number 10ciphertext2=dgk_scheme.encrypt(10)# add both encrypted numbers togetherencrypted_sum=ciphertext1+ciphertext2# ...communication...# check that encrypted sum is not zero (in fact it is 100)assertnotencrypted_sum.is_zero()# subtract the number 100encrypted_sum-=100# check that encrypted sum is zeroassertencrypted_sum.is_zero()Running the examples above will show several warnings. The remainder of this documentation explains why the warnings are issued and how to get rid of them depending on the users' preferences.Fresh and unfresh ciphertextsAn encrypted message is called a ciphertext. A ciphertext in the current package has a propertyis_freshthat indicates whether this ciphertext has fresh randomness, in which case it can be communicated to another player securely. More specifically, a ciphertextcis fresh if another user, knowledgeable of all prior communication and all current ciphertexts marked as fresh, cannot deduce any more private information from learningc.The package understands that the freshness of the result of a homomorphic operation depends on the freshness of the inputs, and that the homomorphic operation renders the inputs unfresh. For example, ifc1andc2are fresh ciphertexts, thenc12 = c1 + c2is marked as a fresh encryption (no rerandomization needed) of the sum of the two underlying plaintexts. After the operation, ciphertextsc1andc2are no longer fresh.The fact thatc1andc2were both fresh implies that, at some point, we randomized them. After the operationc12 = c1 + c2, onlyc12is fresh. This implies that one randomization was lost in the process. In particular, we wasted resources. An alternative approach was to have unfreshc1andc2then compute the unfresh resultc12and only randomize that ciphertext. This time, no resources were wasted. The package issues a warning to inform the user this and similar efficiency opportunities.The package integrates naturally withtno.mpc.communicationand if that is used for communication, its serialization logic will ensure that all sent ciphertexts are fresh. A warning is issued if a ciphertext was randomized in the proces. A ciphertext is always marked as unfresh after it is serialized. Similarly, all received ciphertexts are considered unfresh.Tailor behavior to your needsThe crypto-neutral developer is facilitated by the package as follows: the package takes care of all bookkeeping, and the serialization used bytno.mpc.communicationtakes care of all randomization. The warnings can bedisabledfor a smoother experience.The eager crypto-youngster can improve their understanding and hone their skills by learning from the warnings that the package provides in a safe environment. The package is safe to use when combined withtno.mpc.communication. It remains to be safe while you transform your code from 'randomize-early' (fresh encryptions) to 'randomize-late' (unfresh encryptions, randomize before exposure). At that point you have optimized the efficiency of the library while ensuring that all exposed ciphertexts are fresh before they are serialized. In particular, you no longer rely on our serialization for (re)randomizing your ciphertexts.Finally, the experienced cryptographer can turn off warnings / turn them into exceptions, or benefit from theis_freshflag for own purposes (e.g. different serializer or communication).WarningsBy default, thewarningspackage prints only the first occurrence of a warning for each location (module + line number) where the warning is issued. The user may easilychange this behaviourto never see warnings:fromtno.mpc.encryption_schemes.dgkimportEncryptionSchemeWarningwarnings.simplefilter("ignore",EncryptionSchemeWarning)Alternatively, the user may pass"once","always"or even"error".Finally, note that some operations issue two warnings, e.g.c1-c2issues a warning for computing-c2and a warning for computingc1 + (-c2).Advanced usageThebasic usagecan be improved upon by explicitly randomizing at late as possible.fromtno.mpc.encryption_schemes.dgkimportDGKif__name__=="__main__":dgk_scheme=DGK.from_security_parameter(v_bits=160,n_bits=1000,u=10009,precision=1,full_decryption=False)# unsafe_encrypt does NOT randomize the generated ciphertext; it is deterministic stillciphertext1=dgk_scheme.unsafe_encrypt(8.1)ciphertext1+=0.9ciphertext1*=10ciphertext2=dgk_scheme.unsafe_encrypt(10)# no randomness can be wasted by adding the two unfresh encryptionsencrypted_sum=ciphertext1+ciphertext2# randomize the result, which is now freshencrypted_sum.randomize()# ...communication...decrypted_sum=dgk_scheme.decrypt(encrypted_sum)assertdecrypted_sum==100As explainedabove, this implementation avoids wasted randomization forencrypted_sumand therefore is more efficient.