data61 / python-paillier

A library for Partially Homomorphic Encryption in Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Serialisation of the private/public key

YannisDuhamelle opened this issue · comments

I would like to serialize the private and public key to save them inside a file. I would like to serialize directly the python object generated by phe.generate_paillier_keypair(), but apparently (according to the doc) there is no way to do it like this.
So, I tried to use the command line to use public/private key saved in JSON file. But the problem with this method is that is not handling well encryption of negative number. For example, with this simple code:

import os

os.system("pheutil genpkey --keysize 1024 example_private_key.json")
os.system("pheutil extract example_private_key.json example_public_key.json")

# Generation of the plaintext
m_plaintext = -2
print("m = ",m_plaintext)

# Encryption of the plaintext
os.system("pheutil encrypt example_public_key.json --output test.enc "+str(m_plaintext))

I obtain the following result:

Generating a paillier keypair with keysize of 1024
Keys generated
Private key written to example_private_key.json
Loading paillier keypair
Public key written to example_public_key.json
m =  -2
Usage: pheutil encrypt [OPTIONS] PUBLIC PLAINTEXT
Try 'pheutil encrypt --help' for help.

Error: no such option: -2

What can I do to fix my problem ?
Thanks

The help from the encrypt option describes the problem (see the note paragraph before the "Options" section)

$ pheutil encrypt --help
Usage: pheutil encrypt [OPTIONS] PUBLIC PLAINTEXT

  Encrypt a number with public key.

  The PLAINTEXT input will be interpreted as a floating point number.

  Output will be a JSON object with a "v" attribute containing the
  ciphertext as a string, and "e" the exponent as a Number, where possible
  fixed at -32.

  Note if you are passing a negative number to encrypt, you will need to
  include a "--" between the public key and your plaintext.

Options:
  --output FILENAME  Save to file instead of stdout
  --help             Show this message and exit.

Thus running the following works:

os.system("pheutil encrypt example_public_key.json --output test.enc -- "+str(m_plaintext))

E.g. (after having run the previous command to create the keys):

$ pheutil encrypt example_public_key.json --output test.enc -- -2
Loading public key
Encrypting: -2.0000000000000000

Note that adding "--" before a positive number also works.

Perhaps worth taking a step back.

I would like to serialize the private and public key to save them inside a file. I would like to serialize directly the python object generated by phe.generate_paillier_keypair(), but apparently (according to the doc) there is no way to do it like this.

Where do the docs say there is no way to do this? You get a PaillierPrivateKey instance back from generate_paillier_keypair which is just a standard Python object - you can serialize the attributes into a file.

Also there is almost certainly no need to "shell out" in order to do anything with python-paillier from Python. Each time you spawn a new process it will add quite a bit of overhead.

Yes, I'm sorry I think I misunderstood a little bit the documentation, but I remember that I had an error when I tried to do that...
Anyway, I found a solution later by just using a bit of your code from the phe.command_line in my code to serialize (maybe it is too much for what I want to do but it worked).
I put here my code if someone has the same problem than me

def serialization_paillier_keys(pub, priv, name_public, name_private):
    date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    jwk_public = {
        'kty': "DAJ",
        'alg': "PAI-GN1",
        "key_ops": ["encrypt"],
        'n': phe.util.int_to_base64(pub.n),
        'kid': "Paillier public key generated by pheutil on {}".format(date)
    }
    
    jwk_private = {
        'kty': "DAJ",
        'key_ops': ["decrypt"],
        'p': phe.util.int_to_base64(priv.p),
        'q': phe.util.int_to_base64(priv.q),
        'pub': jwk_public,
        'kid': "Paillier private key generated by pheutil on {}".format(date)
    }
    
    with open(name_public,"w") as f:
        json.dump(jwk_public, f)
        f.write('\n')
    
    with open(name_private,"w") as f:
        json.dump(jwk_private, f)
        f.write('\n')

pki, ski = paillier.generate_paillier_keypair()
serialization_paillier_keys(pki, ski, "pki.json", "ski.json")

Thanks for your response anyway!