Example #1
0
static void setup(ulong32 *dk, ulong32 *k, ulong32 *uk)
{
   int n, t;
   ulong32 p[2];

   p[0] = dk[0]; p[1] = dk[1];

   t = 4;
   n = 0;
      pi1(p);
      pi2(p, k);
      uk[n++] = p[0];
      pi3(p, k);
      uk[n++] = p[1];
      pi4(p, k);
      uk[n++] = p[0];
      pi1(p);
      uk[n++] = p[1];
      pi2(p, k+t);
      uk[n++] = p[0];
      pi3(p, k+t);
      uk[n++] = p[1];
      pi4(p, k+t);
      uk[n++] = p[0];
      pi1(p);
      uk[n++] = p[1];
}
Example #2
0
void KisStrokeBenchmark::benchmarkRandomLines(QString presetFileName)
{
    KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName);
    bool loadedOk = preset->load();
    if (!loadedOk){
        dbgKrita << "The preset was not loaded correctly. Done.";
        return;
    }else{
        dbgKrita << "preset : " << presetFileName;
    }

    m_painter->setPaintOpPreset(preset, m_layer, m_image);

    QBENCHMARK{
        KisDistanceInformation currentDistance;
        for (int i = 0; i < LINES; i++){
            KisPaintInformation pi1(m_startPoints[i], 0.0);
            KisPaintInformation pi2(m_endPoints[i], 1.0);
            m_painter->paintLine(pi1, pi2, &currentDistance);
        }
    }

#ifdef SAVE_OUTPUT
    m_layer->paintDevice()->convertToQImage(0).save(m_outputPath + presetFileName + "_randomLines" + OUTPUT_FORMAT);
#endif
}
Example #3
0
static 
void noekeon_round(uint32_t *key, uint32_t *state, uint8_t const1, uint8_t const2){
	((uint8_t*)state)[RC_POS] ^= const1;
	theta(key, state);
	((uint8_t*)state)[RC_POS] ^= const2;
	pi1(state);
	gamma_1(state);
	pi2(state);
}
Example #4
0
static void encrypt(ulong32 *p, int N, ulong32 *uk)
{
   int n, t;
   for (t = n = 0; ; ) {
      pi1(p); if (++n == N) break;
      pi2(p, uk+t); if (++n == N) break;
      pi3(p, uk+t); if (++n == N) break;
      pi4(p, uk+t); if (++n == N) break;
      t ^= 4;
   }
}
Example #5
0
static void decrypt(ulong32 *p, int N, ulong32 *uk)
{
   int n, t;
   for (t = 4*((N&1)^1), n = N; ;  ) {
      switch (n >= 4 ? 4 : 0) {
         case 4: pi4(p, uk+t); --n;
         case 3: pi3(p, uk+t); --n;
         case 2: pi2(p, uk+t); --n;
         case 1: pi1(p); --n; break;
         case 0: return;
      }
      t ^= 4;
   }
} 
Example #6
0
File: surf.cpp Project: wheam/pai
static bool IsQuadrangle(cv::Point2f p1,
                         cv::Point2f p2,
                         cv::Point2f p3,
                         cv::Point2f p4) {
  cv::Point2d pi1((int)p1.x, (int)p1.y);
  cv::Point2d pi2((int)p2.x, (int)p2.y);
  cv::Point2d pi3((int)p3.x, (int)p3.y);
  cv::Point2d pi4((int)p4.x, (int)p4.y);
  return !(IsOverlapped(pi1, pi2) ||
           IsOverlapped(pi1, pi3) ||
           IsOverlapped(pi1, pi4) ||
           IsOverlapped(pi2, pi3) ||
           IsOverlapped(pi2, pi4) ||
           IsOverlapped(pi3, pi4) ||
           IsLine(pi1, pi2, pi3) ||
           IsLine(pi1, pi2, pi4) ||
           IsLine(pi2, pi3, pi4));
}
Example #7
0
void ofDrawRectOutline(const ofRectangle & rect, int thickness, ofDrawRectOutlineMode mode) {
    
    float b0, b1;
    if(mode == ofDrawRectOutlineModeOuter) {
        b0 = thickness;
        b1 = 0;
    } else if(mode == ofDrawRectOutlineModeInner) {
        b0 = 0;
        b1 = thickness;
    } else if(mode == ofDrawRectOutlineModeMiddle) {
        b0 = thickness * 0.5;
        b1 = thickness * 0.5;
    }
    
    ofVec2f po0(rect.x - b0, rect.y - b0);
    ofVec2f po1(rect.x + rect.width + b0, rect.y - b0);
    ofVec2f po2(rect.x + rect.width + b0, rect.y + rect.height + b0);
    ofVec2f po3(rect.x - b0, rect.y + rect.height + b0);
    
    ofVec2f pi0(rect.x + b1, rect.y + b1);
    ofVec2f pi1(rect.x + rect.width - b1, rect.y + b1);
    ofVec2f pi2(rect.x + rect.width - b1, rect.y + rect.height - b1);
    ofVec2f pi3(rect.x + b1, rect.y + rect.height - b1);
    
    ofBeginShape();

    ofVertex(po0.x, po0.y);
    ofVertex(po1.x, po1.y);
    ofVertex(po2.x, po2.y);
    ofVertex(po3.x, po3.y);
    
    ofNextContour();
    
    ofVertex(pi0.x, pi0.y);
    ofVertex(pi1.x, pi1.y);
    ofVertex(pi2.x, pi2.y);
    ofVertex(pi3.x, pi3.y);
    
    ofEndShape(true);
}
Example #8
0
inline void KisStrokeBenchmark::benchmarkLine(QString presetFileName)
{
    KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName);
    preset->load();
    m_painter->setPaintOpPreset(preset, m_layer, m_image);

    QPointF startPoint(0.10 * TEST_IMAGE_WIDTH, 0.5 * TEST_IMAGE_HEIGHT);
    QPointF endPoint(0.90 * TEST_IMAGE_WIDTH, 0.5 * TEST_IMAGE_HEIGHT);

    KisDistanceInformation currentDistance;
    KisPaintInformation pi1(startPoint, 0.0);
    KisPaintInformation pi2(endPoint, 1.0);

    QBENCHMARK{
        m_painter->paintLine(pi1, pi2, &currentDistance);
    }

#ifdef SAVE_OUTPUT
    m_layer->paintDevice()->convertToQImage(0).save(m_outputPath + presetFileName + "_line" + OUTPUT_FORMAT);
#endif

}
/**
 * This benchmark runs a series of huge strokes on a canvas with a
 * particular configuration of the swapper/pooler and history
 * management. After the test is done you can visualize the results
 * with the GNU Octave. Please use kis_low_memory_show_report.m file
 * for that.
 */
void KisLowMemoryBenchmark::benchmarkWideArea(const QString presetFileName,
                                              const QRectF &rect, qreal vstep,
                                              int numCycles,
                                              bool createTransaction,
                                              int hardLimitMiB,
                                              int softLimitMiB,
                                              int poolLimitMiB,
                                              int index)
{
    KisPaintOpPresetSP preset = new KisPaintOpPreset(QString(FILES_DATA_DIR) + QDir::separator() + presetFileName);
    LOAD_PRESET_OR_RETURN(preset, presetFileName);


    /**
     * Initialize image and painter
     */
    const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, HUGE_IMAGE_SIZE, HUGE_IMAGE_SIZE, colorSpace, "stroke sample image", true);
    KisLayerSP layer = new KisPaintLayer(image, "temporary for stroke sample", OPACITY_OPAQUE_U8, colorSpace);
    KisLayerSP layerExtra = new KisPaintLayer(image, "temporary for threading", OPACITY_OPAQUE_U8, colorSpace);

    image->addNode(layer, image->root());
    image->addNode(layerExtra, image->root());

    KisPainter *painter = new KisPainter(layer->paintDevice());

    painter->setPaintColor(KoColor(Qt::black, colorSpace));
    painter->setPaintOpPreset(preset, layer, image);

    /**
     * A simple adapter that will store all the transactions for us
     */
    KisSurrogateUndoAdapter undoAdapter;

    /**
     * Reset configuration to the desired settings
     */
    KisImageConfig config;
    qreal oldHardLimit = config.memoryHardLimitPercent();
    qreal oldSoftLimit = config.memorySoftLimitPercent();
    qreal oldPoolLimit = config.memoryPoolLimitPercent();
    const qreal _MiB = 100.0 / KisImageConfig::totalRAM();

    config.setMemoryHardLimitPercent(hardLimitMiB * _MiB);
    config.setMemorySoftLimitPercent(softLimitMiB * _MiB);
    config.setMemoryPoolLimitPercent(poolLimitMiB * _MiB);

    KisTileDataStore::instance()->testingRereadConfig();

    /**
     * Create an empty the log file
     */
    QString fileName;
    fileName = QString("log_%1_%2_%3_%4_%5.txt")
        .arg(createTransaction)
        .arg(hardLimitMiB)
        .arg(softLimitMiB)
        .arg(poolLimitMiB)
        .arg(index);

    QFile logFile(fileName);
    logFile.open(QFile::WriteOnly | QFile::Truncate);
    QTextStream logStream(&logFile);
    logStream.setFieldWidth(10);
    logStream.setFieldAlignment(QTextStream::AlignRight);

    /**
     * Start painting on the image
     */

    QTime cycleTime;
    QTime lineTime;
    cycleTime.start();
    lineTime.start();

    qreal rectBottom = rect.y() + rect.height();

    for (int i = 0; i < numCycles; i++) {
        cycleTime.restart();

        QLineF line(rect.topLeft(), rect.topLeft() + QPointF(rect.width(), 0));
        if (createTransaction) {
            painter->beginTransaction();
        }

        KisDistanceInformation currentDistance;

        while(line.y1() < rectBottom) {
            lineTime.restart();

            KisPaintInformation pi1(line.p1(), 0.0);
            KisPaintInformation pi2(line.p2(), 1.0);
            painter->paintLine(pi1, pi2, &currentDistance);
            painter->device()->setDirty(painter->takeDirtyRegion());

            logStream << "L 1" << i << lineTime.elapsed()
                      << KisTileDataStore::instance()->numTilesInMemory() * 16
                      << KisTileDataStore::instance()->numTiles() * 16
                      << createTransaction << endl;

            line.translate(0, vstep);
        }

        painter->device()->setDirty(painter->takeDirtyRegion());

        if (createTransaction) {
            painter->endTransaction(&undoAdapter);
        }

        // comment/uncomment to emulate user waiting after the stroke
        QTest::qSleep(1000);

        logStream << "C 2" << i << cycleTime.elapsed()
                  << KisTileDataStore::instance()->numTilesInMemory() * 16
                  << KisTileDataStore::instance()->numTiles() * 16
                  << createTransaction
                  << config.memoryHardLimitPercent() / _MiB
                  << config.memorySoftLimitPercent() / _MiB
                  << config.memoryPoolLimitPercent() / _MiB  << endl;
    }

    config.setMemoryHardLimitPercent(oldHardLimit * _MiB);
    config.setMemorySoftLimitPercent(oldSoftLimit * _MiB);
    config.setMemoryPoolLimitPercent(oldPoolLimit * _MiB);

    delete painter;
}
Example #10
0
// Decryption and Verification procedure
int crypto_aead_decrypt(
	unsigned char *m, unsigned long long *mlen,
	unsigned char *nsec,
	const unsigned char *c, unsigned long long clen,
	const unsigned char *ad, unsigned long long adlen,
	const unsigned char *npub,
	const unsigned char *k
	)
{
	//...
	//... the code for the cipher implementation goes here,
	//... generating a plaintext m[0],m[1],...,m[*mlen-1]
	//... and secret message number nsec[0],nsec[1],...
	//... from a ciphertext c[0],c[1],...,c[clen-1]
	//... and associated data ad[0],ad[1],...,ad[adlen-1]
	//... and public message number npub[0],npub[1],...
	//... and secret key k[0],k[1],...
	//...

	// some 64-bit temp variables
	u_int64_t  t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13;
	// more 64-bit temp variables
	u_int64_t  x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3;
	// more 64-bit temp variables
	u_int64_t  pom1, pom2, pom3, pom4, nu1, nu2, nu3, nu4;
	// more 64-bit temp variables
	u_int64_t IS0, IS1, IS2, IS3, IS4, IS5, IS6, IS7, IS8, IS9, IS10, IS11, IS12, IS13, IS14, IS15;
	// more 64-bit temp variables
	u_int64_t preCompIS0, preCompIS1, preCompIS2, preCompIS3, preCompIS4, preCompIS5, preCompIS6, preCompIS7, preCompIS8, preCompIS9, preCompIS10, preCompIS11, preCompIS12, preCompIS13, preCompIS14, preCompIS15;
	// pointers to 64-bit variables
	u_int64_t  *c64, *m64, *ad64, *nsec64, *npub64, *k64;
	// an array for storing some temporal values for the Tag computation
	u_int64_t  tempTag[CRYPTO_ABYTES / W] = { 0 };
	// counter ctr is a 64-bit variable in all variants of PiCipher
	u_int64_t  ctr = 0x0000000000000000ull;
	// an array for the Common Internal State
	u_int64_t  CIS[IS_SIZE] = { 0 };
	u_int64_t  CIS1[IS_SIZE] = { 0 };
	// pointers that look at the used data arrays as arrays of bytes
	u_int8_t   *InternalState8, *CommonInternalState8, *tempTag8;
	// variables for dealing with various lengths of the plaintext and associated data
	int LastMessageChunkLength, LastADChunkLength;
	// different iterator variables
	unsigned long long i, j, jj, ii, b, i1, j1, a, cblocks, ii1, ii2, b1;

	c64 = (u_int64_t *)c;
	m64 = (u_int64_t *)m;
	ad64 = (u_int64_t *)ad;
	nsec64 = (u_int64_t *)nsec;
	npub64 = (u_int64_t *)npub;
	k64 = (u_int64_t *)k;
	InternalState8 = (u_int8_t *)IS;
	CommonInternalState8 = (u_int8_t *)CIS;
	tempTag8 = (u_int8_t *)tempTag;

	// phase 1: Initialization
	/* for (i = 0; i < IS_SIZE; i++) {
	IS[i] = 0;
	} */
	IS[0] = 0;
	IS[1] = 0;
	IS[2] = 0;
	IS[3] = 0;
	IS[4] = 0;
	IS[5] = 0;
	IS[6] = 0;
	IS[7] = 0;
	IS[8] = 0;
	IS[9] = 0;
	IS[10] = 0;
	IS[11] = 0;
	IS[12] = 0;
	IS[13] = 0;
	IS[14] = 0;
	IS[15] = 0;

	// injection of the key
	/*for (i = 0; i < CRYPTO_KEYBYTES; i++) {
	InternalState8[i] = k[i];
	}*/
	IS[0] = k64[0];
	IS[1] = k64[1];
	IS[2] = k64[2];
	IS[3] = k64[3];

	// injection of the nonce (public message number - PMN)
	/*for (j = 0; j < CRYPTO_NPUBBYTES; j++) {
	InternalState8[i++] = npub[j];
	}*/
	IS[4] = npub64[0];
	IS[5] = npub64[1];
	// appending a single 1 to the concatenated value of the key and PMN
	InternalState8[48] = 0x01;

	// applying the permutation function pi
	pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);

	// initialization of the Common Internal State (CIS), common for all parallel invocations of pi() with different ctrs
	/* for (i = 0; i < IS_SIZE; i++) {
	CIS[i] = IS[i];
	} */
	CIS[0] = IS[0];
	CIS[1] = IS[1];
	CIS[2] = IS[2];
	CIS[3] = IS[3];
	CIS[4] = IS[4];
	CIS[5] = IS[5];
	CIS[6] = IS[6];
	CIS[7] = IS[7];
	CIS[8] = IS[8];
	CIS[9] = IS[9];
	CIS[10] = IS[10];
	CIS[11] = IS[11];
	CIS[12] = IS[12];
	CIS[13] = IS[13];
	CIS[14] = IS[14];
	CIS[15] = IS[15];

	// initialization of the ctr obtained from the first 64 bits of the capacity of CIS
	ctr = CIS[4];

	// phase 2: Processing the associated data
	nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS1[4], CIS1[5], CIS1[6], CIS1[7]);
	nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS1[8], CIS1[9], CIS1[10], CIS1[11]);
	nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS1[12], CIS1[13], CIS1[14], CIS1[15]);
	nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3];
	nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3];
	nu2 = rotl64((nu2), 23);
	nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2];
	nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3];
	b = 0;
	a = adlen / RATE;
	for (j = 0; j < a; j++) {
		// IS for the triplex component is initialized by the CIS for every AD block
		/* for (i = 0; i < IS_SIZE; i++) {
		IS[i] = CIS[i];
		} */
		IS[0] =  CIS[0];
		IS[1] =  CIS[1];
		IS[2] =  CIS[2];
		IS[3] =  CIS[3];
		IS[4] =  CIS1[4];
		IS[5] =  CIS1[5];
		IS[6] =  CIS1[6];
		IS[7] =  CIS1[7];
		IS[8] =  CIS1[8];
		IS[9] =  CIS1[9];
		IS[10] = CIS1[10];
		IS[11] = CIS1[11];
		IS[12] = CIS1[12];
		IS[13] = CIS1[13];
		IS[14] = CIS1[14];
		IS[15] = CIS1[15];
		ctr++;
		// Inject ctr + j in IS
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		//pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// process the AD block
		// Inject the AD block
		/* for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		IS[ii1] = IS[ii1] ^ ad64[b];
		b++;
		ii1++;
		}
		} */
		IS[0] = IS[0] ^ ad64[b];
		b++;
		IS[1] = IS[1] ^ ad64[b];
		b++;
		IS[2] = IS[2] ^ ad64[b];
		b++;
		IS[3] = IS[3] ^ ad64[b];
		b++;
		IS[8] = IS[8] ^ ad64[b];
		b++;
		IS[9] = IS[9] ^ ad64[b];
		b++;
		IS[10] = IS[10] ^ ad64[b];
		b++;
		IS[11] = IS[11] ^ ad64[b];
		b++;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// Collect the tag for this block
		// Sum of the tags componentwise, where the length of one component is W
		/* jj = 0;
		for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		tempTag[jj] = tempTag[jj] + IS[ii1];
		jj++;
		ii1++;
		}
		} */
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}
	// if the last AD block is not the full block, we process it byte by byte
	LastADChunkLength = adlen % RATE;
	if (LastADChunkLength) {
		b = b * W;
		i1 = 0;
		/* for (i = 0; i < IS_SIZE; i++) {
		IS[i] = CIS[i];
		} */
		IS[0] =  CIS[0];
		IS[1] =  CIS[1];
		IS[2] =  CIS[2];
		IS[3] =  CIS[3];
		IS[4] =  CIS1[4];
		IS[5] =  CIS1[5];
		IS[6] =  CIS1[6];
		IS[7] =  CIS1[7];
		IS[8] =  CIS1[8];
		IS[9] =  CIS1[9];
		IS[10] = CIS1[10];
		IS[11] = CIS1[11];
		IS[12] = CIS1[12];
		IS[13] = CIS1[13];
		IS[14] = CIS1[14];
		IS[15] = CIS1[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		//pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		for (i = 0; i < LastADChunkLength; i++) {
			InternalState8[i1] = InternalState8[i1] ^ ad[b];
			i1++;
			if (i1 % (RATE_OUT) == 0) i1 += RATE_OUT;
			b++;
		}
		// padding with 10*
		InternalState8[i1] = InternalState8[i1] ^ 0x01;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		//updating the tag
		/* jj = 0;
		for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		tempTag[jj] = tempTag[jj] + IS[ii1];
		jj++;
		ii1++;
		}
		} */
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}
	// if the AD is full blocks we still need to append 10* and it is done in an additional block
	else {
		IS[0] =  CIS[0];
		IS[1] =  CIS[1];
		IS[2] =  CIS[2];
		IS[3] =  CIS[3];
		IS[4] =  CIS1[4];
		IS[5] =  CIS1[5];
		IS[6] =  CIS1[6];
		IS[7] =  CIS1[7];
		IS[8] =  CIS1[8];
		IS[9] =  CIS1[9];
		IS[10] = CIS1[10];
		IS[11] = CIS1[11];
		IS[12] = CIS1[12];
		IS[13] = CIS1[13];
		IS[14] = CIS1[14];
		IS[15] = CIS1[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		// padding with 10*
		InternalState8[0] = InternalState8[0] ^ 0x01;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		//updating the tag
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}

	// updating the Common Internal State by injection of the tag (tempTag) obtained from the associated data
	/* jj = 0;
	for (i = 0; i < N; i += 2) {
	ii1 = i * WORDS_CHUNK;
	ii2 = (i + 1) * WORDS_CHUNK;
	for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
	IS[ii1] = CIS[ii1] ^ tempTag[jj];
	IS[ii2] = CIS[ii2];
	jj++;
	ii1++;
	ii2++;
	}
	} */
	IS[0] = CIS[0] ^ tempTag[0];
	IS[1] = CIS[1] ^ tempTag[1];
	IS[2] = CIS[2] ^ tempTag[2];
	IS[3] = CIS[3] ^ tempTag[3];
	IS[4] = CIS[4];
	IS[5] = CIS[5];
	IS[6] = CIS[6];
	IS[7] = CIS[7];
	IS[8] = CIS[8] ^ tempTag[4];
	IS[9] = CIS[9] ^ tempTag[5];
	IS[10] = CIS[10] ^ tempTag[6];
	IS[11] = CIS[11] ^ tempTag[7];
	IS[12] = CIS[12];
	IS[13] = CIS[13];
	IS[14] = CIS[14];
	IS[15] = CIS[15];
	pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
	/* for (i = 0; i < IS_SIZE; i++) {
	CIS[i] = IS[i];
	} */
	CIS[0] = IS[0];
	CIS[1] = IS[1];
	CIS[2] = IS[2];
	CIS[3] = IS[3];
	CIS[4] = IS[4];
	CIS[5] = IS[5];
	CIS[6] = IS[6];
	CIS[7] = IS[7];
	CIS[8] = IS[8];
	CIS[9] = IS[9];
	CIS[10] = IS[10];
	CIS[11] = IS[11];
	CIS[12] = IS[12];
	CIS[13] = IS[13];
	CIS[14] = IS[14];
	CIS[15] = IS[15];

	// phase 3: Processing the secret message number
	if (CRYPTO_NSECBYTES > 0) {
		nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS[4], CIS[5], CIS[6], CIS[7]);
		nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS[8], CIS[9], CIS[10], CIS[11]);
		nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS[12], CIS[13], CIS[14], CIS[15]);
		nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3];
		nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3];
		nu2 = rotl64((nu2), 23);
		nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2];
		nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3];
		/* for (i = 0; i < IS_SIZE; i++) {
		IS[i] = CIS[i];
		} */
		IS[0] = CIS[0];
		IS[1] = CIS[1];
		IS[2] = CIS[2];
		IS[3] = CIS[3];
		IS[4] = CIS[4];
		IS[5] = CIS[5];
		IS[6] = CIS[6];
		IS[7] = CIS[7];
		IS[8] = CIS[8];
		IS[9] = CIS[9];
		IS[10] = CIS[10];
		IS[11] = CIS[11];
		IS[12] = CIS[12];
		IS[13] = CIS[13];
		IS[14] = CIS[14];
		IS[15] = CIS[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		//pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// decrypt the SMN
		// Inject the SMN
		b = 0;
		/* for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		nsec64[b] = IS[ii1] ^ c64[b];
		IS[ii1] = c64[b];
		b++;
		ii1++;
		}
		} */
		nsec64[b] = IS[0] ^ c64[b];
		IS[0] = c64[b];
		b++;
		nsec64[b] = IS[1] ^ c64[b];
		IS[1] = c64[b];
		b++;
		nsec64[b] = IS[2] ^ c64[b];
		IS[2] = c64[b];
		b++;
		nsec64[b] = IS[3] ^ c64[b];
		IS[3] = c64[b];
		b++;
		nsec64[b] = IS[8] ^ c64[b];
		IS[8] = c64[b];
		b++;
		nsec64[b] = IS[9] ^ c64[b];
		IS[9] = c64[b];
		b++;
		nsec64[b] = IS[10] ^ c64[b];
		IS[10] = c64[b];
		b++;
		nsec64[b] = IS[11] ^ c64[b];
		IS[11] = c64[b];
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);

		// updating the Common Internal State after decrypting the SMN
		/* for (i = 0; i < IS_SIZE; i++) {
		CIS[i] = IS[i];
		} */
		CIS[0] = IS[0];
		CIS[1] = IS[1];
		CIS[2] = IS[2];
		CIS[3] = IS[3];
		CIS[4] = IS[4];
		CIS[5] = IS[5];
		CIS[6] = IS[6];
		CIS[7] = IS[7];
		CIS[8] = IS[8];
		CIS[9] = IS[9];
		CIS[10] = IS[10];
		CIS[11] = IS[11];
		CIS[12] = IS[12];
		CIS[13] = IS[13];
		CIS[14] = IS[14];
		CIS[15] = IS[15];
		// Collect the tag from this encryption and update the tempTag
		/* jj = 0;
		for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		tempTag[jj] = tempTag[jj] + IS[ii1];
		jj++;
		ii1++;
		}
		} */
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}

	//phase 4: Processing the ciphertext
	nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS[4], CIS[5], CIS[6], CIS[7]);
	nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS[8], CIS[9], CIS[10], CIS[11]);
	nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS[12], CIS[13], CIS[14], CIS[15]);
	nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3];
	nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3];
	nu2 = rotl64((nu2), 23);
	nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2];
	nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3];
	cblocks = (clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES) / RATE;
	b = 0;
	b1 = bSMN;
	for (j = 0; j < cblocks; j++) {
		/* for (i = 0; i < IS_SIZE; i++) {
		IS[i] = CIS[i];
		} */
		IS[0] = CIS[0];
		IS[1] = CIS[1];
		IS[2] = CIS[2];
		IS[3] = CIS[3];
		IS[4] = CIS[4];
		IS[5] = CIS[5];
		IS[6] = CIS[6];
		IS[7] = CIS[7];
		IS[8] = CIS[8];
		IS[9] = CIS[9];
		IS[10] = CIS[10];
		IS[11] = CIS[11];
		IS[12] = CIS[12];
		IS[13] = CIS[13];
		IS[14] = CIS[14];
		IS[15] = CIS[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		//pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// decrypt the ciphertext c
		/* for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		// XOR the IS_bitrate (InternalState[0], InternalSate[2], ...) with the c to obtain m
		m64[b] = IS[ii1] ^ c64[b1];
		// in order to proceed for tag computation, put the ciphertext data in the InternalState
		IS[ii1] = c64[b1];
		b++;
		b1++;
		ii1++;
		}
		} */
		m64[b] = IS[0] ^ c64[b1];
		IS[0] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[1] ^ c64[b1];
		IS[1] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[2] ^ c64[b1];
		IS[2] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[3] ^ c64[b1];
		IS[3] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[8] ^ c64[b1];
		IS[8] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[9] ^ c64[b1];
		IS[9] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[10] ^ c64[b1];
		IS[10] = c64[b1];
		b++;
		b1++;
		m64[b] = IS[11] ^ c64[b1];
		IS[11] = c64[b1];
		b++;
		b1++;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// Collect the tag from this decryption and update the tempTag
		/* jj = 0;
		for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		tempTag[jj] = tempTag[jj] + IS[ii1];
		jj++;
		ii1++;
		}
		} */
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}
	// if the last ciphertext block is not the full block, we process it byte by byte
	LastMessageChunkLength = (clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES) % RATE;
	if (LastMessageChunkLength) {
		b = b * W;
		b1 = CRYPTO_NSECBYTES + b;
		i1 = 0;
		/* for (i = 0; i < IS_SIZE; i++) {
		IS[i] = CIS[i];
		} */
		IS[0] = CIS[0];
		IS[1] = CIS[1];
		IS[2] = CIS[2];
		IS[3] = CIS[3];
		IS[4] = CIS[4];
		IS[5] = CIS[5];
		IS[6] = CIS[6];
		IS[7] = CIS[7];
		IS[8] = CIS[8];
		IS[9] = CIS[9];
		IS[10] = CIS[10];
		IS[11] = CIS[11];
		IS[12] = CIS[12];
		IS[13] = CIS[13];
		IS[14] = CIS[14];
		IS[15] = CIS[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		//pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		for (i = 0; i < LastMessageChunkLength; i++) {
			m[b] = InternalState8[i1] ^ c[b1];
			InternalState8[i1] = c[b1];
			i1++;
			if (i1 % (RATE_OUT) == 0) i1 += RATE_OUT;
			b++;
			b1++;
		}
		// padding with 10*
		InternalState8[i1] = InternalState8[i1] ^ 0x01;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		// updating the tag
		/* jj = 0;
		for (i = 0; i < N; i += 2) {
		ii1 = i * WORDS_CHUNK;
		for (i1 = 0; i1 < WORDS_CHUNK; i1++) {
		tempTag[jj] = tempTag[jj] + IS[ii1];
		jj++;
		ii1++;
		}
		} */
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}
	// if the message is full blocks we still need to append 10* and it is done in an additional block
	else {
		IS[0] =  CIS[0];
		IS[1] =  CIS[1];
		IS[2] =  CIS[2];
		IS[3] =  CIS[3];
		IS[4] =  CIS1[4];
		IS[5] =  CIS1[5];
		IS[6] =  CIS1[6];
		IS[7] =  CIS1[7];
		IS[8] =  CIS1[8];
		IS[9] =  CIS1[9];
		IS[10] = CIS1[10];
		IS[11] = CIS1[11];
		IS[12] = CIS1[12];
		IS[13] = CIS1[13];
		IS[14] = CIS1[14];
		IS[15] = CIS1[15];
		ctr++;
		IS[0] = IS[0] ^ ctr;
		pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4);
		// padding with 10*
		InternalState8[0] = InternalState8[0] ^ 0x01;
		pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]);
		//updating the tag
		tempTag[0] = tempTag[0] + IS[0];
		tempTag[1] = tempTag[1] + IS[1];
		tempTag[2] = tempTag[2] + IS[2];
		tempTag[3] = tempTag[3] + IS[3];
		tempTag[4] = tempTag[4] + IS[8];
		tempTag[5] = tempTag[5] + IS[9];
		tempTag[6] = tempTag[6] + IS[10];
		tempTag[7] = tempTag[7] + IS[11];
	}

	//updating the length of the message
	*mlen = clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES;

	// tag verification
	b = (*mlen + CRYPTO_NSECBYTES);
	for (ii = b; ii < clen; ii++) {
		if (c[ii] != tempTag8[ii - b])
			return -1;
	}

	return 0;
}
Example #11
0
    void DrrnPsiClient::recv(Channel s0, Channel s1, span<block> inputs)
    {
        if (inputs.size() != mClientSetSize)
            throw std::runtime_error(LOCATION);

        Matrix<u64> bins(mNumSimpleBins, mBinSize);
        std::vector<u64> binSizes(mNumSimpleBins);
        u64 cuckooSlotsPerBin = (mCuckooParams.numBins() + mNumSimpleBins) / mNumSimpleBins;

        // Simple hashing with a PRP
        std::vector<block> hashs(inputs.size());
        AES hasher(mHashingSeed);
        u64 numCuckooBins = mCuckooParams.numBins();
        for (u64 i = 0; i < u64(inputs.size());)
        {
            auto min = std::min<u64>(inputs.size() - i, 8);
            auto end = i + min;
            hasher.ecbEncBlocks(inputs.data() + i, min, hashs.data() + i);
            for (; i < end; ++i)
            {
                hashs[i] = hashs[i] ^ inputs[i];
                for (u64 j = 0; j < mCuckooParams.mNumHashes; ++j)
                {
                    u64 idx = CuckooIndex<>::getHash(hashs[i], j, numCuckooBins) * mNumSimpleBins / mCuckooParams.numBins();

                    // insert this item in this bin. pack together the hash index and input index
                    bins(idx, binSizes[idx]++) = (j << 56) | i;
                }

                //if (!i)
                //{
                //    ostreamLock(std::cout) << "cinput[" << i << "] = " << inputs[i] << " -> " << hashs[i] << " ("
                //        << CuckooIndex<>::getHash(hashs[i], 0, numCuckooBins) << ", "
                //        << CuckooIndex<>::getHash(hashs[i], 1, numCuckooBins) << ", "
                //        << CuckooIndex<>::getHash(hashs[i], 2, numCuckooBins) << ")"
                //        << std::endl;
                //}
            }
        }



        // power of 2
        u64 numLeafBlocks = (cuckooSlotsPerBin + mBigBlockSize * 128 - 1) / (mBigBlockSize * 128);
        u64 gDepth = 2;
        u64 kDepth = std::max<u64>(gDepth, log2floor(numLeafBlocks)) - gDepth;
        u64 groupSize = (numLeafBlocks + (u64(1) << kDepth) - 1) / (u64(1) << kDepth);
        if (groupSize > 8) throw std::runtime_error(LOCATION);

        //std::cout << "kDepth:   " << kDepth << std::endl;
        //std::cout << "mBinSize: " << mBinSize << std::endl;

        u64 numQueries = mNumSimpleBins * mBinSize;
        auto permSize = numQueries * mBigBlockSize;

        // mask generation
        block rSeed = CCBlock;// mPrng.get<block>();
        AES rGen(rSeed);


        std::vector<block> shares(mClientSetSize * mCuckooParams.mNumHashes), r(permSize), piS1(permSize), s(permSize);
        //std::vector<u32> rIdxs(numQueries);
        //std::vector<u64> sharesIdx(shares.size());

        //TODO("use real masks");
        //memset(r.data(), 0, r.size() * sizeof(block));
        rGen.ecbEncCounterMode(r.size() * 0, r.size(), r.data());
        rGen.ecbEncCounterMode(r.size() * 1, r.size(), piS1.data());
        rGen.ecbEncCounterMode(r.size() * 2, r.size(), s.data());

        //auto encIter = enc.begin();
        auto shareIter = shares.begin();
        //auto shareIdxIter = sharesIdx.begin();
        u64 queryIdx = 0, dummyPermIdx = mClientSetSize * mCuckooParams.mNumHashes;

        std::unordered_map<u64, u64> inputMap;
        inputMap.reserve(mClientSetSize * mCuckooParams.mNumHashes);

        std::vector<u32> pi(permSize);
        auto piIter = pi.begin();


        u64 keySize = kDepth + 1 + groupSize;
        u64 mask = (u64(1) << 56) - 1;
        auto binIter = bins.begin();
        for (u64 bIdx = 0; bIdx < mNumSimpleBins; ++bIdx)
        {
            u64 i = 0;

            auto binOffset = (bIdx * numCuckooBins + mNumSimpleBins - 1) / mNumSimpleBins;

            std::vector<block> k0(keySize * mBinSize), k1(keySize * mBinSize);
            //std::vector<u64> idx0(mBinSize), idx1(mBinSize);
            auto k0Iter = k0.data(), k1Iter = k1.data();
            //auto idx0Iter = idx0.data(), idx1Iter = idx1.data();

            for (; i < binSizes[bIdx]; ++i)
            {
                span<block>
                    kk0(k0Iter, kDepth + 1),
                    g0(k0Iter + kDepth + 1, groupSize),
                    kk1(k1Iter, kDepth + 1),
                    g1(k1Iter + kDepth + 1, groupSize);

                k0Iter += keySize;
                k1Iter += keySize;

                u8 hashIdx = *binIter >> 56;
                u64 itemIdx = *binIter & mask;
                u64 cuckooIdx = CuckooIndex<>::getHash(hashs[itemIdx], hashIdx, numCuckooBins) - binOffset;
                ++binIter;

                auto bigBlockoffset = cuckooIdx % mBigBlockSize;
                auto bigBlockIdx = cuckooIdx / mBigBlockSize;

                BgiPirClient::keyGen(bigBlockIdx, mPrng.get<block>(), kk0, g0, kk1, g1);



                // the index of the mask that will mask this item
                auto rIdx = *piIter = itemIdx * mCuckooParams.mNumHashes + hashIdx * mBigBlockSize + bigBlockoffset;

                // the masked value that will be inputted into the PSI
                *shareIter = r[rIdx] ^ inputs[itemIdx];
                //*shareIter = inputs[itemIdx];

                //if (itemIdx == 0)
                //    ostreamLock(std::cout)
                //    << "item[" << i << "]    bin " << bIdx
                //    << " block " << bigBlockIdx 
                //    << " offset " << bigBlockoffset 
                //    << " psi " << *shareIter << std::endl;

                // This will be used to map itemed items in the intersection back to their input item
                inputMap.insert({ queryIdx, itemIdx });

                ++shareIter;
                ++piIter;
                ++queryIdx;
            }

            u64 rem = mBinSize - i;


            binIter += rem;
            for (u64 i = 0; i < rem; ++i)
            {
                *piIter++ = dummyPermIdx++;
            }

            //s0.asyncSendCopy(k0);
            //s0.asyncSendCopy(k1);
            //s1.asyncSendCopy(k1);
            //s1.asyncSendCopy(k0);

            s0.asyncSend(std::move(k0));
            s1.asyncSend(std::move(k1));

        }

        std::vector<u32> pi1(permSize), pi0(permSize), pi1Inv(permSize);
        for (u32 i = 0; i < pi1.size(); ++i) pi1[i] = i;
        PRNG prng(rSeed ^ OneBlock);
        std::random_shuffle(pi1.begin(), pi1.end(), prng);


        //std::vector<block> pi1RS(pi.size());
        for (u64 i = 0; i < permSize; ++i)
        {
            //auto pi1i = pi1[i];
            //pi1RS[i] = r[pi1i] ^ s[pi1i];

            pi1Inv[pi1[i]] = i;
            //std::cout << "pi1(r + s)[" << i << "] " << pi1RS[i] << std::endl;
        }
        std::vector<block> piS0(r.size());
        for (u64 i = 0; i < permSize; ++i)
        {
            //std::cout << "r[" << i << "] " << r[i] << std::endl;
            //std::cout << "pi(r + s)[" << i << "]=" << (r[pi[i]] ^ s[pi[i]]) << std::endl;


            pi0[i] = pi1Inv[pi[i]];
            piS0[i] = piS1[i] ^ s[pi[i]];
            //std::cout << "pi (r + s)[" << i << "] = " << (r[pi[i]] ^ s[pi[i]]) << " = " << r[pi[i]] << " ^ " << s[pi[i]] << " c " << pi[i] << std::endl;
            //std::cout << "pi`(r + s)[" << i << "] = " << pi1RS[pi0[i]]  <<" c " << pi0[pi1[i]] << std::endl;
        }

        s0.asyncSend(std::move(pi0));
        s0.asyncSend(std::move(piS0));
        //rGen.ecbEncBlocks(r.data(), r.size(), r.data());
        //for (u64 i = 0; i < shares.size(); ++i)
        //{
        //    std::cout << IoStream::lock << "cshares[" << i << "] " << shares[i] << " input[" << sharesIdx[i]<<"]" << std::endl << IoStream::unlock;
        //}
        mPsi.sendInput(shares, s0);

        mIntersection.reserve(mPsi.mIntersection.size());
        for (u64 i = 0; i < mPsi.mIntersection.size(); ++i) {
            // divide index by #hashes
            mIntersection.emplace(inputMap[mPsi.mIntersection[i]]);
        }

    }