一,Reference:
(1) https://github.com/tlepoint/multimap: this is an implementation of multilinear maps over the integers. used to perform a one-round n-party (unauthenticated) Diffie-Hellman key exchange.
(2)http://gas.dia.unisa.it/projects/jpbc/index.html: The Java Pairing-Based Cryptography Library (JPBC) also provides An implementation of Multilinear Maps based on the paper Practical Multilinear Maps over the Integers by Coron, Lepoint, and Tibouchi. The implementation supports multithreading and uses memory mapped files to save in primary memory requirements.
(3)相关paper支持请参见前几篇博文。
二,Experiments based on (1):
In cryptography, a multilinear map is a mapping between useful cryptographic groups, which allows the construction of new cryptographic schemes based on the reduction of one problem in one group to a different problem in the target group.
Install GMP:download it and configure it accordingly: ./configure --enable-cxx, sudo make install, make check
modify the makefile as:
IFLAGS = -I/usr/local/include
LFLAGS = -L/usr/local/lib -lgmpxx -lgmp
all: Multimap.cpp Multimap.h main.cpp Makefile
$(CC) $(CCFLAGS) $(IFLAGS) -c -o Multimap.o Multimap.cpp $(LFLAGS)
$(CC) $(CCFLAGS) $(IFLAGS) main.cpp Multimap.o -o multimap $(LFLAGS)
Then there will be no more complication errors:
g++ -Wall -O3 -fopenmp -I/usr/local/include -c -o Multimap.o Multimap.cpp -L/usr/local/lib -lgmpxx -lgmp
g++ -Wall -O3 -fopenmp -I/usr/local/include main.cpp Multimap.o -o multimap -L/usr/local/lib -lgmpxx -lgmp
Session keys of 160 bits
User #0: 386998600064854454291301789805079065417790031671
User #1: 386998600064854454291301789805079065417790031671
User #2: 386998600064854454291301789805079065417790031671
User #3: 386998600064854454291301789805079065417790031671
User #4: 386998600064854454291301789805079065417790031671
User #5: 386998600064854454291301789805079065417790031671
User #6: 386998600064854454291301789805079065417790031671
(Product+Extract): 0.887151s
下面我们具体看一下这个代码的内部实现:
(1) Multimap.h (https://github.com/vingstar/multimap/blob/master/Multimap.h) :
#define INSTANTIATION 1 // 1- Small, 2- Medium, 3- Large, 4- Extra
#define kappa 6 // Maximal level
#define hBits 80 // size of h_i's in v = BETA
#define ell 160 // number of elements during encoding
#define theta 15 // number of non-zero elements in subset sum during rerand
#define sessionKeyBits 160 // Bitsize of session key to derive
#define bound sessionKeyBits // bound to decide if it is zero or not
// bound must be >= sessionKeyBits
#define alpha 80 // size of g_i's and elements of A
#if INSTANTIATION == 1 // Small
#define N 540 // number of p_i's
#define delta 23 // sqrt(N)
#define eta 1838 // size of p_i's
#define etp 460 // Size of primes in p_i's; it is better to have eta%etp=0
#define rho 41 // size of r_i's in xp_i's and y
#elif INSTANTIATION == 2 // Medium
#define N 2085 // number of p_i's
#define delta 45 // sqrt(N)
#define eta 2043 // size of p_i's
#define etp 409 // Size of primes in p_i's; it is better to have eta%etp=0
#define rho 56 // size of r_i's in xp_i's and y
#elif INSTANTIATION == 3 // Large
#define N 8250 // number of p_i's
#define delta 90 // sqrt(N)
#define eta 2261 // size of p_i's
#define etp 453 // Size of primes in p_i's; it is better to have eta%etp=0
#define rho 72 // size of r_i's in xp_i's and y
#elif INSTANTIATION == 4 // Extra
#define N 26115 // number of p_i's
#define delta 161 // sqrt(N)
#define eta 2438 // size of p_i's
#define etp 407 // Size of primes in p_i's; it is better to have eta%etp=0
#define rho 85 // size of r_i's in xp_i's and y
#endif
double currentTime();
class MMKey;
/*
Class Ciphertext
Contain:
- ciphertext value (large integer) `cval'
- ciphertext degree `degree'
- pointer to the key associated with the ciphertext `key'
*/
class Ciphertext {
private:
mpz_class cval;
long degree;
MMKey* key;
public:
Ciphertext();
Ciphertext(const Ciphertext& c);
Ciphertext(MMKey* mmkey, mpz_class c, long deg);
void Decrypt_with_sk(mpz_class* m);
long get_noise();
long get_degree() const {return degree;};
mpz_class get_cval() const {return cval;};
mpz_class deriveSessionKey(); //相当于Extract
//以下都是进行运算符重载
Ciphertext& operator=(const Ciphertext&);
Ciphertext& operator+=(const Ciphertext&);
Ciphertext& operator+=(const mpz_class&);
Ciphertext& operator*=(const Ciphertext&);
Ciphertext& operator-=(const Ciphertext&);
Ciphertext& operator-=(const mpz_class&);
Ciphertext operator+(const Ciphertext& c) const {
Ciphertext c2(*this);
return (c2 += c);
}
Ciphertext operator+(const mpz_class a) const {
Ciphertext c2(*this);
return (c2 += a);
}
friend Ciphertext operator+(const mpz_class, const Ciphertext&);
Ciphertext operator-(const Ciphertext& c) const {
Ciphertext c2(*this);
return (c2 -= c);
}
Ciphertext operator-(const mpz_class a) const {
Ciphertext c2(*this);
return (c2 -= a);
}
friend Ciphertext operator-(const mpz_class, const Ciphertext&);
Ciphertext operator*(Ciphertext& c) const {
Ciphertext c2(*this);
return (c2 *= c);
}
};
/*
Class MMKey (Multilinear-Map Key)
Contain:
- pointer to the gmp pseudorandom generator `rng'
- pointer to secret primes `p'
- public key value `x0' (=prod(p))
- private value `z' and `zkappa'=z^kappa
- private value `zinv' = z^(-1) mod x0
- pointer to private elements `g'
- pointer to secret matrix `A'
- pointer to public values `xp'
- public value `y'
- public zero-tester `v'
- pointer to rerandomization values `varpi' (= x in the article)
*/
class MMKey {
private:
gmp_randclass* rng;
mpz_class* p; // [N];
mpz_class x0, z, zkappa;
mpz_class zinv; // [N];
mpz_class* crtCoeff; // [N];
mpz_class* g; // [N];
mpz_class* A; // [ell*N];
mpz_class* xp; // [ell];
mpz_class y;
mpz_class v;
mpz_class* varpi; // [2*delta];注意,这个就是论文中用来进行rerand的一系列x(level 1的encoding 0)
public:
MMKey(gmp_randclass* random);
~MMKey();
Ciphertext Encrypt(bool b[ell]);
mpz_class Encrypt_with_sk(mpz_class* m, long nbBits, long degree);
mpz_class Encrypt_with_sk(unsigned long m, long nbBits, long degree);
void Decrypt_with_sk(mpz_class* m, const Ciphertext& c);
mpz_class reduce(const mpz_class &c);
Ciphertext get_y();
long get_noise(const mpz_class& c, long degree);
mpz_class zero_test(const mpz_class &c, long degree);
long nbBits(const mpz_class &v);
bool is_zero(const Ciphertext &c);
Ciphertext Rerand(const Ciphertext & c);
mpz_class& get_x0() { return x0; };
};
#endif
// #ifndef __MULTIMAP_H
这里定义了基本的参数以及基本的数据结构类
不同的instantiation标志着不同的security level。其内分别制定了各个基本的参数,主要是各种size的值。
MMkey类制定了一个具体的MMAP instance的相关系统key。
Ciphertext封装了密文信息。
mpz_class 是GMP中的 C++ Interface Integers
为了能较好的理解这里的源代码,我们有必要了解基本的GMP最基本的一些知识,这些知识可以简要的从GMP的手册中学习掌握。
比如:
12.1 C++ Interface General
All the C++ classes and functions are available with
#include <gmpxx.h>
Programs should be linked with the libgmpxx and libgmp libraries. For example,
g++ mycxxprog.cc -lgmpxx -lgmp
The classes defined are
12.2 C++ Interface Integers
Construct an
mpz_class
. All the standard C++ types may be used, exceptlong long
andlong double
, and all the GMP C++ classes can be used, although conversions frommpq_class
andmpf_class
areexplicit
. Any necessary conversion follows the corresponding C function, for exampledouble
followsmpz_set_d
(see Assigning Integers).
Construct an
mpz_class
from anmpz_t
. The value in z is copied into the newmpz_class
, there won't be any permanent association between it andz.
12.5 C++ Interface Random Numbers
The C++ class interface to the GMP random number functions uses
gmp_randclass
to hold an algorithm selection and current state, as pergmp_randstate_t
.
Construct a
gmp_randclass
, using a call to the given randinit function (see Random State Initialization). The arguments expected are the same as randinit, but withmpz_class
instead ofmpz_t
. For example,gmp_randclass r1 (gmp_randinit_default); gmp_randclass r2 (gmp_randinit_lc_2exp_size, 32); gmp_randclass r3 (gmp_randinit_lc_2exp, a, c, m2exp); gmp_randclass r4 (gmp_randinit_mt);
Also there are no automatic conversions from the classes to the corresponding GMP C types, instead a reference to the underlying C object can be obtained with the following functions,
— Function: mpq_t mpq_class::get_mpq_t ()
— Function: mpf_t mpf_class::get_mpf_t ()
These can be used to call a C function which doesn't have a C++ class interface. For example to set a
to the GCD of b
and c
,
mpz_class a, b, c; ... mpz_gcd (a.get_mpz_t(), b.get_mpz_t(), c.get_mpz_t());
三, 基于JPBC的初步实验