hardbyte / paillier.jl Goto Github PK
View Code? Open in Web Editor NEWA Julia implementation of the Paillier partially homomorphic encryption system
A Julia implementation of the Paillier partially homomorphic encryption system
The REQUIRE file could not be found.
cc: @hardbyte
@JuliaRegistrator register()
Currently, AutoMerge complains that there is no [compat] section in the Project file as in my case:
JuliaRegistries/General#4907
It would be faster to precompute a bunch of n
bit random numbers for a given public key's n
so that during use (in particular during the obfuscation
step) the numbers are already to go.
One idea is that a Channel
is created with a specific sized buffer and a Task
has the job of keeping it full.
It would be worth benchmarking before and after this.
It is best practice to pass in io
streams and random number generators to functions, I need to modify the key generator and the obfuscate functions to allow/require a rng to be passed by the caller.
Not requiring the user to pass in a rng would be nice to keep.
@JuliaRegistrator register()
In cryptosystem.jl
I have a helper function to calculate the maximum plaintext integer:
max_int(n::BigInt) = BigInt(floor(n // 3))
This is used in the multiplication function:
function raw_multiply(public_key::PublicKey, ciphertext::Ciphertext, plaintext::Integer)::Ciphertext
@debug "Raw encrypted multiply by $plaintext"
if public_key.n - max_int(public_key) <= plaintext
neg_ciphertext = invmod(ciphertext, public_key.n_sq)
neg_scalar = public_key.n - plaintext
new_ciphertext = powermod(neg_ciphertext, neg_scalar, public_key.n_sq)
else
new_ciphertext = powermod(ciphertext, plaintext, public_key.n_sq)
end
return new_ciphertext
end
This is from copying python-paillier which doesn't make a clear distinction between raw unsigned integer encryption and working with encoded numbers.
In the case of Paillier.jl
I'd like to keep the concepts separate by supporting the full range for all operations for the raw cryptosystem.
I've been thinking about how Paillier.jl
composes with other parts of the Julia ecosystem, in particular the fact that users should be able to encode and encrypt/decrypt user defined types easily.
Currently using the library with Measurement.jl
numbers is messy. One method would be to create an array of both the value and the error from the measurement object:
> encoding = Encoding(Float64, publickey)
> Paillier.encode_and_encrypt(plaintext::Measurement, encoding::Encoding) = Paillier.encode_and_encrypt([plaintext.val, plaintext.err], encoding)
> encrypted_g_with_uncertainty = encode_and_encrypt(9.79 ± 0.02, encoding);
> decrypt_and_decode(privatekey, encrypted_g_with_uncertainty)
2-element Array{Float16,1}:
9.79
0.02
However as the encoding doesn't include the Measurement
type we can't nicely reconstruct a Measurement object after decryption and decoding.
Creating an encoding of a Measurement
doesn't work either:
> measurementencoding = Encoding(Measurement{Float64}, publickey)
> encrypted_g_2 = encode_and_encrypt(9.79 ± 0.02, measurementencoding)
MethodError: no method matching precision(::Type{Measurement{Float64}})
Closest candidates are:
precision(!Matched::BigFloat) at mpfr.jl:805
precision(!Matched::Type{Float16}) at float.jl:579
precision(!Matched::Type{Float32}) at float.jl:580
...
Stacktrace:
[1] encode(::Float64, ::Encoding) at src\Encoding.jl:200
As Julia tries to ascertain the precision of a Measurement
within the encode
method.
Now while we could probably hack the precision method to unwrap the measurement object, there is still a question of how to encode the measurement into one or more integers suitable for encryption. A better strategy for handling encoding of arbitrary user defined types might be to have users override encode
for their user defined Encoding
type.
So instead of Encoding
being defined as:
struct Encoding
datatype::DataType
public_key::PublicKey
base::Int64
end
Perhaps it should be a parametric type:
struct Encoding{T}
public_key::PublicKey
base::Int64
end
# Example use:
encoding = Encoding{Measurement{Float64}}(publickey, 16)
# Then a user can specialize the `encode` and `decode` methods for their data type. E.g.:
Paillier.encode(scalar::Measurement{Float64}, encoding::Encoding{Measurement{T}}) where T = Paillier.encode(
[scalar.val, scalar.err],
Encoding{T}(encoding.public_key, encoding.base)
)
# decode would need more work as decrypt_and_decode calls decode for each element
# of an encrypted array and not with an array of encodings. But that refactoring seems sensible
# at first glance. Which for our example of encoding a Measurement as an array of encrypted numbers give something like this for the decode method:
decode(encoded::Array{BigInt}, exponent, encoding::Encoding{Measurement{T}}) where T =
measurement(decode(encoded[1], exponent, T), decode(encoded[2], exponent, T))
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.