mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-04-20 03:01:31 -04:00
SPDZ2k offline phase.
This commit is contained in:
committed by
Marcel Keller
parent
5a0413de7a
commit
881b4403ac
@@ -122,7 +122,7 @@ namespace Config {
|
||||
pubkeys[i].resize(crypto_sign_PUBLICKEYBYTES);
|
||||
infile.read((char*)&pubkeys[i][0],pubkeys[i].size());
|
||||
}
|
||||
} catch (ConfigError e) {
|
||||
} catch (ConfigError& e) {
|
||||
pubkeys.resize(0);
|
||||
}
|
||||
|
||||
|
||||
148
Tools/MMO.cpp
148
Tools/MMO.cpp
@@ -10,20 +10,27 @@
|
||||
#include "Math/gf2n.h"
|
||||
#include "Math/gfp.h"
|
||||
#include "Math/bigint.h"
|
||||
#include "Math/Z2k.h"
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
void MMO::zeroIV()
|
||||
{
|
||||
octet key[AES_BLK_SIZE];
|
||||
memset(key,0,AES_BLK_SIZE*sizeof(octet));
|
||||
setIV(key);
|
||||
if (N_KEYS > (1 << 8))
|
||||
throw not_implemented();
|
||||
for (int i = 0; i < N_KEYS; i++)
|
||||
{
|
||||
octet key[AES_BLK_SIZE];
|
||||
memset(key, 0, AES_BLK_SIZE * sizeof(octet));
|
||||
key[i] = i;
|
||||
setIV(i, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMO::setIV(octet key[AES_BLK_SIZE])
|
||||
void MMO::setIV(int i, octet key[AES_BLK_SIZE])
|
||||
{
|
||||
aes_schedule(IV,key);
|
||||
aes_schedule(IV[i],key);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,26 +57,91 @@ void MMO::encrypt_and_xor(void* output, const void* input, const octet* key,
|
||||
_mm_storeu_si128(((__m128i*)output) + indices[i], out[i]);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MMO::hashOneBlock<gf2n>(octet* output, octet* input)
|
||||
template <class T, int N>
|
||||
void MMO::hashBlocks(void* output, const void* input)
|
||||
{
|
||||
encrypt_and_xor<1>(output, input, IV);
|
||||
int n_blocks = DIV_CEIL(T::size(), 16);
|
||||
if (n_blocks > N_KEYS)
|
||||
throw runtime_error("not enough MMO keys");
|
||||
__m128i tmp[N];
|
||||
int block_size = sizeof(tmp[0]);
|
||||
for (int i = 0; i < n_blocks; i++)
|
||||
{
|
||||
encrypt_and_xor<N>(tmp, input, IV[i]);
|
||||
for (int j = 0; j < N; j++)
|
||||
memcpy((char*)output + j * sizeof(T) + i * block_size, &tmp[j],
|
||||
min(T::size() - i * block_size, block_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void MMO::hashOneBlock<gfp>(octet* output, octet* input)
|
||||
void MMO::hashBlocks<gfp, 1>(void* output, const void* input)
|
||||
{
|
||||
encrypt_and_xor<1>(output, input, IV);
|
||||
if (gfp::get_ZpD().get_t() != 2)
|
||||
throw not_implemented();
|
||||
encrypt_and_xor<1>(output, input, IV[0]);
|
||||
while (mpn_cmp((mp_limb_t*)output, gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
|
||||
encrypt_and_xor<1>(output, output, IV);
|
||||
encrypt_and_xor<1>(output, output, IV[0]);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MMO::hashBlockWise<gf2n,128>(octet* output, octet* input)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
encrypt_and_xor<8>(&((__m128i*)output)[i*8], &((__m128i*)input)[i*8], IV);
|
||||
encrypt_and_xor<8>(&((__m128i*)output)[i*8], &((__m128i*)input)[i*8], IV[0]);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MMO::hashBlocks<gfp, 8>(void* output, const void* input)
|
||||
{
|
||||
if (gfp::get_ZpD().get_t() != 2)
|
||||
throw not_implemented();
|
||||
__m128i* in = (__m128i*)input;
|
||||
__m128i* out = (__m128i*)output;
|
||||
encrypt_and_xor<8>(out, in, IV[0]);
|
||||
int left = 8;
|
||||
int indices[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
while (left)
|
||||
{
|
||||
int now_left = 0;
|
||||
for (int j = 0; j < left; j++)
|
||||
if (mpn_cmp((mp_limb_t*)&out[indices[j]], gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
|
||||
{
|
||||
indices[now_left] = indices[j];
|
||||
now_left++;
|
||||
}
|
||||
left = now_left;
|
||||
|
||||
// and now my favorite hack
|
||||
switch (left) {
|
||||
case 8:
|
||||
ecb_aes_128_encrypt<8>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 7:
|
||||
ecb_aes_128_encrypt<7>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 6:
|
||||
ecb_aes_128_encrypt<6>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 5:
|
||||
ecb_aes_128_encrypt<5>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 4:
|
||||
ecb_aes_128_encrypt<4>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 3:
|
||||
ecb_aes_128_encrypt<3>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 2:
|
||||
ecb_aes_128_encrypt<2>(out, out, IV[0], indices);
|
||||
break;
|
||||
case 1:
|
||||
ecb_aes_128_encrypt<1>(out, out, IV[0], indices);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -79,49 +151,11 @@ void MMO::hashBlockWise<gfp,128>(octet* output, octet* input)
|
||||
{
|
||||
__m128i* in = &((__m128i*)input)[i*8];
|
||||
__m128i* out = &((__m128i*)output)[i*8];
|
||||
encrypt_and_xor<8>(out, in, IV);
|
||||
int left = 8;
|
||||
int indices[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
while (left)
|
||||
{
|
||||
int now_left = 0;
|
||||
for (int j = 0; j < left; j++)
|
||||
if (mpn_cmp((mp_limb_t*)&out[indices[j]], gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
|
||||
{
|
||||
indices[now_left] = indices[j];
|
||||
now_left++;
|
||||
}
|
||||
left = now_left;
|
||||
|
||||
// and now my favorite hack
|
||||
switch (left) {
|
||||
case 8:
|
||||
ecb_aes_128_encrypt<8>(out, out, IV, indices);
|
||||
break;
|
||||
case 7:
|
||||
ecb_aes_128_encrypt<7>(out, out, IV, indices);
|
||||
break;
|
||||
case 6:
|
||||
ecb_aes_128_encrypt<6>(out, out, IV, indices);
|
||||
break;
|
||||
case 5:
|
||||
ecb_aes_128_encrypt<5>(out, out, IV, indices);
|
||||
break;
|
||||
case 4:
|
||||
ecb_aes_128_encrypt<4>(out, out, IV, indices);
|
||||
break;
|
||||
case 3:
|
||||
ecb_aes_128_encrypt<3>(out, out, IV, indices);
|
||||
break;
|
||||
case 2:
|
||||
ecb_aes_128_encrypt<2>(out, out, IV, indices);
|
||||
break;
|
||||
case 1:
|
||||
ecb_aes_128_encrypt<1>(out, out, IV, indices);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hashBlocks<gfp,8>(out, in);
|
||||
}
|
||||
}
|
||||
|
||||
#define ZZ(F,N) \
|
||||
template void MMO::hashBlocks<F,N>(void*, const void*);
|
||||
#define Z(F) ZZ(F,1) ZZ(F,2) ZZ(F,8)
|
||||
Z(gf2n) Z(Z2<64>) Z(Z2<128>) Z(Z2<160>) Z(Z2<256>)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
// Matyas-Meyer-Oseas hashing
|
||||
class MMO
|
||||
{
|
||||
octet IV[176] __attribute__((aligned (16)));
|
||||
static const int N_KEYS = 2;
|
||||
octet IV[N_KEYS][176] __attribute__((aligned (16)));
|
||||
|
||||
template<int N>
|
||||
static void encrypt_and_xor(void* output, const void* input,
|
||||
@@ -25,9 +26,11 @@ class MMO
|
||||
public:
|
||||
MMO() { zeroIV(); }
|
||||
void zeroIV();
|
||||
void setIV(octet key[AES_BLK_SIZE]);
|
||||
void setIV(int i, octet key[AES_BLK_SIZE]);
|
||||
template <class T>
|
||||
void hashOneBlock(octet* output, octet* input);
|
||||
void hashOneBlock(void* output, const void* input) { hashBlocks<T, 1>((T*)output, input); }
|
||||
template <class T, int N>
|
||||
void hashBlocks(void* output, const void* input);
|
||||
template <class T, int N>
|
||||
void hashBlockWise(octet* output, octet* input);
|
||||
template <class T>
|
||||
|
||||
@@ -18,7 +18,6 @@ typedef unsigned char octet;
|
||||
typedef unsigned long word;
|
||||
#endif
|
||||
|
||||
|
||||
inline int CEIL_LOG2(int x)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
19
Tools/oct.h
Normal file
19
Tools/oct.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef TOOLS_OCT_H_
|
||||
#define TOOLS_OCT_H_
|
||||
|
||||
typedef unsigned char octet;
|
||||
|
||||
inline void PRINT_OCTET(const octet* bytes, size_t size) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
cout << hex << (int) bytes[i];
|
||||
cout << flush << endl;
|
||||
}
|
||||
|
||||
inline bool OCTETS_EQUAL(const octet* left, const octet* right, int size) {
|
||||
for (int i = 0; i < size; ++i)
|
||||
if (left[i] != right[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -36,16 +36,6 @@ void octetStream::assign(const octetStream& os)
|
||||
}
|
||||
|
||||
|
||||
void octetStream::swap(octetStream& os)
|
||||
{
|
||||
const size_t size = sizeof(octetStream);
|
||||
char tmp[size];
|
||||
memcpy(tmp, this, size);
|
||||
memcpy(this, &os, size);
|
||||
memcpy(&os, tmp, size);
|
||||
}
|
||||
|
||||
|
||||
octetStream::octetStream(size_t maxlen)
|
||||
{
|
||||
mxlen=maxlen; len=0; ptr=0;
|
||||
|
||||
@@ -42,10 +42,10 @@ class octetStream
|
||||
|
||||
void resize(size_t l);
|
||||
void resize_precise(size_t l);
|
||||
void reserve(size_t l);
|
||||
void clear();
|
||||
|
||||
void assign(const octetStream& os);
|
||||
void swap(octetStream& os);
|
||||
|
||||
octetStream() : len(0), mxlen(0), ptr(0), data(0) {}
|
||||
octetStream(size_t maxlen);
|
||||
@@ -177,6 +177,11 @@ inline void octetStream::resize_precise(size_t l)
|
||||
mxlen=l;
|
||||
}
|
||||
|
||||
inline void octetStream::reserve(size_t l)
|
||||
{
|
||||
if (len + l > mxlen)
|
||||
resize_precise(len + l);
|
||||
}
|
||||
|
||||
inline void octetStream::append(const octet* x, const size_t l)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "Tools/random.h"
|
||||
#include "Math/bigint.h"
|
||||
#include "Auth/Subroutines.h"
|
||||
#include <stdio.h>
|
||||
#include <sodium.h>
|
||||
|
||||
@@ -38,6 +39,12 @@ void PRNG::SetSeed(PRNG& G)
|
||||
SetSeed(tmp);
|
||||
}
|
||||
|
||||
void PRNG::SecureSeed(Player& player)
|
||||
{
|
||||
Create_Random_Seed(seed, player, SEED_SIZE);
|
||||
InitSeed();
|
||||
}
|
||||
|
||||
void PRNG::InitSeed()
|
||||
{
|
||||
#ifdef USE_AES
|
||||
@@ -136,7 +143,25 @@ unsigned int PRNG::get_uint()
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
unsigned int PRNG::get_uint(int upper)
|
||||
{
|
||||
// adopting Java 7 implementation of bounded nextInt here
|
||||
if (upper <= 0)
|
||||
throw invalid_argument("Must be positive");
|
||||
// power of 2 case
|
||||
if ((upper & (upper - 1)) == 0) {
|
||||
unsigned int r = (upper < 255) ? get_uchar() : get_uint();
|
||||
// zero out higher order bits
|
||||
return r % upper;
|
||||
}
|
||||
// not power of 2
|
||||
int r, reduced;
|
||||
do {
|
||||
r = (upper < 255) ? get_uchar() : get_uint();
|
||||
reduced = r % upper;
|
||||
} while (r - reduced + (upper - 1) < 0);
|
||||
return reduced;
|
||||
}
|
||||
|
||||
unsigned char PRNG::get_uchar()
|
||||
{
|
||||
@@ -147,7 +172,6 @@ unsigned char PRNG::get_uchar()
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
__m128i PRNG::get_doubleword()
|
||||
{
|
||||
if (cnt > RAND_SIZE - 16)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Tools/octetStream.h"
|
||||
#include "Tools/sha1.h"
|
||||
#include "Tools/aes.h"
|
||||
#include "Tools/avx_memcpy.h"
|
||||
|
||||
#define USE_AES
|
||||
|
||||
@@ -19,6 +20,7 @@
|
||||
#define RAND_SIZE (PIPELINES * AES_BLK_SIZE)
|
||||
#endif
|
||||
|
||||
class Player;
|
||||
|
||||
/* This basically defines a randomness expander, if using
|
||||
* as a real PRG on an input stream you should first collapse
|
||||
@@ -62,12 +64,14 @@ class PRNG
|
||||
// Set seed from array
|
||||
void SetSeed(const unsigned char*);
|
||||
void SetSeed(PRNG& G);
|
||||
void SecureSeed(Player& player);
|
||||
void InitSeed();
|
||||
|
||||
double get_double();
|
||||
bool get_bit() { return get_uchar() & 1; }
|
||||
unsigned char get_uchar();
|
||||
unsigned int get_uint();
|
||||
unsigned int get_uint(int upper);
|
||||
void get_bigint(bigint& res, int n_bits, bool positive = true);
|
||||
void get(bigint& res, int n_bits, bool positive = true);
|
||||
void get(int& res, int n_bits, bool positive = true);
|
||||
@@ -82,9 +86,34 @@ class PRNG
|
||||
__m128i get_doubleword();
|
||||
void get_octetStream(octetStream& ans,int len);
|
||||
void get_octets(octet* ans, int len);
|
||||
template <int L>
|
||||
void get_octets_(octet* ans);
|
||||
|
||||
template <class T>
|
||||
T get();
|
||||
|
||||
const octet* get_seed() const
|
||||
{ return seed; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T PRNG::get()
|
||||
{
|
||||
T res;
|
||||
res.randomize(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<int L>
|
||||
inline void PRNG::get_octets_(octet* ans)
|
||||
{
|
||||
if (L < RAND_SIZE - cnt)
|
||||
{
|
||||
avx_memcpy(ans, random + cnt, L);
|
||||
cnt += L;
|
||||
}
|
||||
else
|
||||
get_octets(ans, L);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user