This library does not enforce any particular serialisation scheme.

Every EncryptedNumber instance has a public_key attribute, and serialising each EncryptedNumber independently would be heinously inefficient when sending a large list of instances. It is up to you to serialise in a way that is efficient for your use case.

Basic JSON Serialisation

This basic serialisation method is an example of serialising a vector of encrypted numbers. Note that if you are only using the python-paillier library g will always be n + 1, so these is no need to serialise it as part of the public key.

To send a list of values encrypted against one public key, the following is one way to serialise:

>>> import json
>>> enc_with_one_pub_key = {}
>>> enc_with_one_pub_key['public_key'] = {'g': public_key.g,
...                                       'n': public_key.n}
>>> enc_with_one_pub_key['values'] = [
...     (str(x.ciphertext()), x.exponent) for x in encrypted_number_list
... ]
>>> serialised = json.dumps(enc_with_one_pub_key)

Deserialisation of the above scheme might look as follows:

>>> received_dict = json.loads(serialised)
>>> pk = received_dict['public_key']
>>> public_key_rec = paillier.PaillierPublicKey(g=int(pk['g']),
...                                             n=int(pk['n']))
>>> enc_nums_rec = [
...     paillier.EncryptedNumber(public_key_rec, int(x[0]), int(x[1]))
...     for x in received_dict['values']
... ]

If both parties already know public_key, then you might instead send a hash of the public key.

JWK Serialisation

This serialisation scheme is used by the Command Line Utility, and is based on the JSON Web Key (JWK) format. This serialisation scheme should be used to increase compatibility between libraries.

All cryptographic integers are represented as Base64UrlEncoded numbers. Note the existence of base64_to_int() and int_to_base64().

“kty” (Key Type) Parameter

We define the family for all Paillier keys as “DAJ” for Damgard Jurik.

“alg” (Algorithm) Parameter

We identify the algorithm for our Paillier keys as: “PAI-GN1”

“key_ops” (Key Operations) Parameter

Values will be “encrypt” and “decrypt” for public and private keys respectively. We decided not to add homomorphic properties to the key operations.

“kid” (Key Identifier)

The kid may be set to any ascii string. Useful for storing key names, generation tools, times etc.

Public Key

In addition to the “kty”, “kid”, “key_ops” and “alg” attributes, a public key will have:

Example of a 256 bit public key:

python -m phe.command_line genpkey --keysize 256 - | python -m phe.command_line extract - -
    "kty": "DAJ",
    "kid": "Example Paillier public key",
    "key_ops": [ "encrypt" ],
    "n": "m0lOEwDHVA_VieL2k3BKMjf_HIgagfhNIZy1YhgZF5M",
    "alg": "PAI-GN1"

Private Key


The serialised private key includes the public key.

In addition to the “kty”, “kid”, “key_ops” and “alg” attributes, a private key will have:

  • mu and lambda - The private key’s secrets. See Paillier’s paper for details.
  • pub - The Public Key serialised as described above.

Example of a 256 bit private key:

python -m phe.command_line genpkey --keysize 256 -
    "mu": "Dzq1_tz2qDX_-S4shia9Rw34Z9ix9b-fhPi3In76NaI",
    "kty": "DAJ",
    "key_ops": [ "decrypt" ],
    "kid": "Paillier private key generated by pheutil on 2016-05-24 14:18:25",
    "lambda": "haFTvA70KcI5XXReJUlQWRQdYHxaUS8baGQGug9dewA",
    "pub": {
        "alg": "PAI-GN1",
        "n": "haFTvA70KcI5XXReJUlQWoZus12aSJJ5EXAvu93xR7k",
        "kty": "DAJ",
        "key_ops": [ "encrypt" ],
        "kid": "Paillier public key generated by pheutil on 2016-05-24 14:18:25"


“kty” and “alg” values should be registered in the IANA “JSON Web Key Types” registry established by JWA. We have not registered DAJ or PAI-GN1 - however we intend to begin that conversation.