aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/mcl/include/mcl/paillier.hpp
blob: 03e44cb1675e76e4d3d6be2701e140ab49e9a61e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#pragma once
/**
    @file
    @brief paillier encryption
    @author MITSUNARI Shigeo(@herumi)
    @license modified new BSD license
    http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/gmp_util.hpp>

namespace mcl { namespace paillier {

class PublicKey {
    size_t primeBitSize;
    mpz_class g;
    mpz_class n;
    mpz_class n2;
public:
    PublicKey() : primeBitSize(0) {}
    void init(size_t _primeBitSize, const mpz_class& _n)
    {
        primeBitSize = _primeBitSize;
        n = _n;
        g = 1 + _n;
        n2 = _n * _n;
    }
    void enc(mpz_class& c, const mpz_class& m, mcl::fp::RandGen rg = mcl::fp::RandGen()) const
    {
        if (rg.isZero()) rg = mcl::fp::RandGen::get();
        if (primeBitSize == 0) throw cybozu::Exception("paillier:PublicKey:not init");
        mpz_class r;
        mcl::gmp::getRand(r, primeBitSize, rg);
        mpz_class a, b;
        mcl::gmp::powMod(a, g, m, n2);
        mcl::gmp::powMod(b, r, n, n2);
        c = (a * b) % n2;
    }
    /*
        additive homomorphic encryption
        cz = cx + cy
    */
    void add(mpz_class& cz, mpz_class& cx, mpz_class& cy) const
    {
        cz = (cx * cy) % n2;
    }
};

class SecretKey {
    size_t primeBitSize;
    mpz_class n;
    mpz_class n2;
    mpz_class lambda;
    mpz_class invLambda;
public:
    SecretKey() : primeBitSize(0) {}
    /*
        the size of prime is half of bitSize
    */
    void init(size_t bitSize, mcl::fp::RandGen rg = mcl::fp::RandGen())
    {
        if (rg.isZero()) rg = mcl::fp::RandGen::get();
        primeBitSize = bitSize / 2;
        mpz_class p, q;
        mcl::gmp::getRandPrime(p, primeBitSize, rg);
        mcl::gmp::getRandPrime(q, primeBitSize, rg);
        lambda = (p - 1) * (q - 1);
        n = p * q;
        n2 = n * n;
        mcl::gmp::invMod(invLambda, lambda, n);
    }
    void getPublicKey(PublicKey& pub) const
    {
        pub.init(primeBitSize, n);
    }
    void dec(mpz_class& m, const mpz_class& c) const
    {
        mpz_class L;
        mcl::gmp::powMod(L, c, lambda, n2);
        L = ((L - 1) / n) % n;
        m = (L * invLambda) % n;
    }
};

} } // mcl::paillier