int main() { static const uint8_t point1[32] = { 0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; static const uint8_t point2[32] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, }; static const uint8_t scalar[32] = { 1 }; uint8_t out1[32], out2[32]; curve25519_donna(out1, scalar, point1); curve25519_donna(out2, scalar, point2); if (0 == memcmp(out1, out2, sizeof(out1))) { fprintf(stderr, "Top bit not ignored.\n"); return 1; } fprintf(stderr, "Top bit correctly ignored.\n"); return 0; }
static void *run( void *state ) { thr_state *st = (thr_state*)state; unsigned char mypublic[32]; uint64_t start, end; unsigned i; const unsigned iterations = 100000; printf("Waiting in thread %d ...\n", st->i+1); while( *st->all_start==0 ) ; /* spin */ //printf("Proceed to testing in thread %d\n", st->i); // Load the caches for (i = 0; i < 1000; ++i) { curve25519_donna(mypublic, st->secret, basepoint); } start = time_now(); for (i = 0; i < iterations; ++i) { curve25519_donna(mypublic, st->secret, basepoint); } end = time_now(); st->op_sec = iterations*1000000. / (end - start); st->total_sec = (end - start)/1000000.; st->exited = 1; //printf("Exited thread %d\n", st->i); return NULL; }
void doit(unsigned char *ek,unsigned char *e,unsigned char *k) { int i; for (i = 0;i < 32;++i) printhex((unsigned int) e[i]); for (i = 0;i < 32;++i) printhex((unsigned int) k[i]); curve25519_donna(ek,e,k); for (i = 0;i < 32;++i) printhex((unsigned int) ek[i]); }
void CECPQ1_finish(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], const CECPQ1_key& offer_key, const uint8_t received[CECPQ1_ACCEPT_BYTES]) { curve25519_donna(shared_key, offer_key.m_x25519.data(), received); newhope_shareda(shared_key + 32, &offer_key.m_newhope, received + 32, Newhope_Mode::BoringSSL); }
int main() { static const uint8_t basepoint[32] = {9}; unsigned char publicKey[32] = {0}; curve25519_donna(publicKey, privateKey, basepoint); printf("done\n"); for (int i = 0; i < 32; ++i) { printf("%d ", publicKey[i]); } printf("\n"); }
uint8_t do_one_computation(uint8_t *data) { uint8_t out[32] = {0}; const uint8_t secret[32] = {1,2,3}; uint8_t ret = 0; const uint8_t basepoint[32] = {9}; curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); curve25519_donna(out, data, basepoint); memcpy(data, out, 32); ret ^= out[0]; return ret; }
static void curve25519_djb_doit(unsigned char *ek,unsigned char *e,unsigned char *k, int print) { int i; if (print) { for (i = 0;i < 32;++i) printf("%02x",(unsigned int) e[i]); printf(" "); for (i = 0;i < 32;++i) printf("%02x",(unsigned int) k[i]); printf(" "); } curve25519_donna(ek,e,k); if (print) { for (i = 0;i < 32;++i) printf("%02x",(unsigned int) ek[i]); printf("\n"); } }
int pairing_session_handshake(pairing_session_t *session, const unsigned char ecdh_key[32], const unsigned char ed_key[32]) { unsigned char ecdh_priv[32]; assert(session); if (session->status == STATUS_FINISHED) { return -1; } if (ed25519_create_seed(ecdh_priv)) { return -2; } memcpy(session->ecdh_theirs, ecdh_key, 32); memcpy(session->ed_theirs, ed_key, 32); curve25519_donna(session->ecdh_ours, ecdh_priv, kCurve25519BasePoint); curve25519_donna(session->ecdh_secret, ecdh_priv, session->ecdh_theirs); session->status = STATUS_HANDSHAKE; return 0; }
static void test_main(void) { int i; static const curve25519_key max = { 255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255 }; static const curve25519_key mid = { 127,127,127,127,127,127,127,127, 127,127,127,127,127,127,127,127, 127,127,127,127,127,127,127,127, 127,127,127,127,127,127,127,127 }; curve25519_key pk[2]; curve25519_key shared[2]; uint64_t ticks, curveticks = maxticks; curve25519_donna(pk[0], max, max); for (i = 0; i < 1023; i++) curve25519_donna(pk[(i & 1) ^ 1], pk[i & 1], max); curve25519_donna_basepoint(pk[0], pk[1]); curveassert_equal(curve25519_expected, pk[0], sizeof(curve25519_key), "curve25519 sanity test failed to generate correct value"); curve25519_donna_basepoint(pk[0], max); curve25519_donna_basepoint(pk[1], mid); curve25519_donna(shared[0], max, pk[1]); curve25519_donna(shared[1], mid, pk[0]); curveassert_equal(curve25519_shared, shared[0], sizeof(curve25519_key), "curve25519 failed to generate the same shared key (1)"); curveassert_equal(curve25519_shared, shared[1], sizeof(curve25519_key), "curve25519 failed to generate the same shared key (2)"); for (i = 0; i < 2048; i++) { timeit(curve25519_donna(pk[1], pk[0], max), curveticks); } printf("%.0f ticks/curve25519 scalarmult\n", (double)curveticks); }
void CECPQ1_accept(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], uint8_t send[CECPQ1_ACCEPT_BYTES], const uint8_t received[CECPQ1_OFFER_BYTES], RandomNumberGenerator& rng) { secure_vector<byte> x25519_key = rng.random_vec(32); curve25519_basepoint(send, x25519_key.data()); curve25519_donna(shared_key, x25519_key.data(), received); newhope_sharedb(shared_key + 32, send + 32, received + 32, rng, Newhope_Mode::BoringSSL); }
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_textsecure_crypto_ecc_Curve25519_calculateAgreement (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey) { jbyteArray sharedKey = (*env)->NewByteArray(env, 32); uint8_t* sharedKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, sharedKey, 0); uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); curve25519_donna(sharedKeyBytes, privateKeyBytes, publicKeyBytes); (*env)->ReleaseByteArrayElements(env, sharedKey, sharedKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); return sharedKey; }
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_textsecure_crypto_ecc_Curve25519_generatePublicKey (JNIEnv *env, jclass clazz, jbyteArray privateKey) { static const uint8_t basepoint[32] = {9}; jbyteArray publicKey = (*env)->NewByteArray(env, 32); uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); curve25519_donna(publicKeyBytes, privateKeyBytes, basepoint); (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); return publicKey; }
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_calculateAgreement (JNIEnv *env, jobject obj, jbyteArray privateKey, jbyteArray publicKey) { jbyteArray sharedKey = (*env)->NewByteArray(env, 32); uint8_t* sharedKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, sharedKey, 0); uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); curve25519_donna(sharedKeyBytes, privateKeyBytes, publicKeyBytes); (*env)->ReleaseByteArrayElements(env, sharedKey, sharedKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); return sharedKey; }
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_generatePublicKey (JNIEnv *env, jobject obj, jbyteArray privateKey) { static const uint8_t basepoint[32] = {9}; jbyteArray publicKey = (*env)->NewByteArray(env, 32); uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); curve25519_donna(publicKeyBytes, privateKeyBytes, basepoint); (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); return publicKey; }
OSStatus curve25519_test( int print ) { OSStatus err; uint8_t e[ 32 ], k[ 32 ], ek[ 32 ], ek2[ 32 ]; size_t i, j, len; CFAbsoluteTime t = 0; for( i = 0; i < countof( kCurve25519TestVectors ); ++i ) { const curve25519_test_vector * const tv = &kCurve25519TestVectors[ i ]; err = HexToData( tv->e, kSizeCString, kHexToData_NoFlags, e, sizeof( e ), &len, NULL, NULL ); require_noerr( err, exit ); require_action( len == 32, exit, err = kSizeErr ); err = HexToData( tv->k, kSizeCString, kHexToData_NoFlags, k, sizeof( k ), &len, NULL, NULL ); require_noerr( err, exit ); require_action( len == 32, exit, err = kSizeErr ); err = HexToData( tv->ek, kSizeCString, kHexToData_NoFlags, ek, sizeof( ek ), &len, NULL, NULL ); require_noerr( err, exit ); require_action( len == 32, exit, err = kSizeErr ); memset( ek2, 0, sizeof( ek2 ) ); curve25519_donna( ek2, e, k ); require_action( memcmp( ek, ek2, 32 ) == 0, exit, err = kMismatchErr ); if( print ) { for( j = 0; j < 32; ++j ) printf( "%02x", e[ j ] ); printf( " " ); for( j = 0; j < 32; ++j ) printf( "%02x", k[ j ] ); printf( " " ); for( j = 0; j < 32; ++j ) printf( "%02x", ek[ j ] ); printf( "\n" ); } } t = CFAbsoluteTimeGetCurrent(); err = curve25519_djb_test( print ); require_noerr( err, exit ); t = CFAbsoluteTimeGetCurrent() - t; exit: FPrintF( stdout, "%###s: %s (%f seconds)\n", __ROUTINE__, !err ? "PASSED" : "FAILED", t ); return( err ); }
STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret, const uint8_t *basepoint) { uint8_t bp[CURVE25519_PUBKEY_LEN]; int r; memcpy(bp, basepoint, CURVE25519_PUBKEY_LEN); /* Clear the high bit, in case our backend foolishly looks at it. */ bp[31] &= 0x7f; #ifdef USE_CURVE25519_DONNA r = curve25519_donna(output, secret, bp); #elif defined(USE_CURVE25519_NACL) r = crypto_scalarmult_curve25519(output, secret, bp); #else #error "No implementation of curve25519 is available." #endif memwipe(bp, 0, sizeof(bp)); return r; }
static OSStatus __MFiSAP_Exchange_ServerM1( MFiSAPRef inRef, const uint8_t * inInputPtr, size_t inInputLen, uint8_t ** outOutputPtr, size_t * outOutputLen ) { OSStatus err; const uint8_t * inputEnd; const uint8_t * clientECDHPublicKey; uint8_t ourPrivateKey[ kMFiSAP_ECDHKeyLen ]; uint8_t ourPublicKey[ kMFiSAP_ECDHKeyLen ]; SHA_CTX sha1Context; uint8_t digest[ 20 ]; uint8_t * signaturePtr = NULL; size_t signatureLen; uint8_t * certificatePtr = NULL; size_t certificateLen; uint8_t aesMasterKey[ kMFiSAP_AESKeyLen ]; uint8_t aesMasterIV[ kMFiSAP_AESKeyLen ]; uint8_t * buf; uint8_t * dst; size_t len; if( ( UpTicks() - gMFiSAP_LastTicks ) < UpTicksPerSecond() ) { if( gMFiSAP_ThrottleCounter < 4 ) ++gMFiSAP_ThrottleCounter; SleepForUpTicks( gMFiSAP_ThrottleCounter * UpTicksPerSecond() ); } else { gMFiSAP_ThrottleCounter = 0; } gMFiSAP_LastTicks = UpTicks(); // Validate inputs. Input data must be: <1:version> <32:client's ECDH public key>. inputEnd = inInputPtr + inInputLen; require_action( inputEnd > inInputPtr, exit, err = kSizeErr ); // Detect bad length causing ptr wrap. require_action( ( inputEnd - inInputPtr ) >= kMFiSAP_VersionLen, exit, err = kSizeErr ); inRef->version = *inInputPtr++; require_action( inRef->version == kMFiSAPVersion1, exit, err = kVersionErr ); require_action( ( inputEnd - inInputPtr ) >= kMFiSAP_ECDHKeyLen, exit, err = kSizeErr ); clientECDHPublicKey = inInputPtr; inInputPtr += kMFiSAP_ECDHKeyLen; require_action( inInputPtr == inputEnd, exit, err = kSizeErr ); // Generate a random ECDH key pair. err = PlatformRandomBytes( ourPrivateKey, sizeof( ourPrivateKey ) ); require_noerr( err, exit ); curve25519_donna( ourPublicKey, ourPrivateKey, NULL ); // Use our private key and the client's public key to generate the shared secret. // Hash the shared secret and truncate it to form the AES master key. // Hash the shared secret with salt to derive the AES master IV. curve25519_donna( inRef->sharedSecret, ourPrivateKey, clientECDHPublicKey ); SHA1_Init( &sha1Context ); SHA1_Update( &sha1Context, kMFiSAP_AES_KEY_SaltPtr, kMFiSAP_AES_KEY_SaltLen ); SHA1_Update( &sha1Context, inRef->sharedSecret, sizeof( inRef->sharedSecret ) ); SHA1_Final( digest, &sha1Context ); memcpy( aesMasterKey, digest, sizeof( aesMasterKey ) ); SHA1_Init( &sha1Context ); SHA1_Update( &sha1Context, kMFiSAP_AES_IV_SaltPtr, kMFiSAP_AES_IV_SaltLen ); SHA1_Update( &sha1Context, inRef->sharedSecret, sizeof( inRef->sharedSecret ) ); SHA1_Final( digest, &sha1Context ); memcpy( aesMasterIV, digest, sizeof( aesMasterIV ) ); // Use the auth chip to sign a hash of <32:our ECDH public key> <32:client's ECDH public key>. // And copy the auth chip's certificate so the client can verify the signature. SHA1_Init( &sha1Context ); SHA1_Update( &sha1Context, ourPublicKey, sizeof( ourPublicKey ) ); SHA1_Update( &sha1Context, clientECDHPublicKey, kMFiSAP_ECDHKeyLen ); SHA1_Final( digest, &sha1Context ); err = PlatformMFiAuthCreateSignature( digest, sizeof( digest ), &signaturePtr, &signatureLen ); require_noerr( err, exit ); err = PlatformMFiAuthCopyCertificate( &certificatePtr, &certificateLen ); require_noerr( err, exit ); // Encrypt the signature with the AES master key and master IV. err = AES_CTR_Init( &inRef->aesMasterContext, aesMasterKey, aesMasterIV ); require_noerr( err, exit ); err = AES_CTR_Update( &inRef->aesMasterContext, signaturePtr, signatureLen, signaturePtr ); if( err ) AES_CTR_Final( &inRef->aesMasterContext ); require_noerr( err, exit ); inRef->aesMasterValid = true; // Return the response: // // <32:our ECDH public key> // <4:big endian certificate length> // <N:certificate data> // <4:big endian signature length> // <N:encrypted signature data> len = kMFiSAP_ECDHKeyLen + 4 + certificateLen + 4 + signatureLen; buf = (uint8_t *) malloc( len ); require_action( buf, exit, err = kNoMemoryErr ); dst = buf; memcpy( dst, ourPublicKey, sizeof( ourPublicKey ) ); dst += sizeof( ourPublicKey ); *dst++ = (uint8_t)( ( certificateLen >> 24 ) & 0xFF ); *dst++ = (uint8_t)( ( certificateLen >> 16 ) & 0xFF ); *dst++ = (uint8_t)( ( certificateLen >> 8 ) & 0xFF ); *dst++ = (uint8_t)( certificateLen & 0xFF ); memcpy( dst, certificatePtr, certificateLen ); dst += certificateLen; *dst++ = (uint8_t)( ( signatureLen >> 24 ) & 0xFF ); *dst++ = (uint8_t)( ( signatureLen >> 16 ) & 0xFF ); *dst++ = (uint8_t)( ( signatureLen >> 8 ) & 0xFF ); *dst++ = (uint8_t)( signatureLen & 0xFF ); memcpy( dst, signaturePtr, signatureLen ); dst += signatureLen; check( dst == ( buf + len ) ); *outOutputPtr = buf; *outOutputLen = (size_t)( dst - buf ); exit: if( certificatePtr ) free( certificatePtr ); if( signaturePtr ) free( signaturePtr ); return( err ); }
void operator()(std::map<uint64_t, uint64_t> &accounts, std::string thread_seed) { // Our approach is to pick a random point and repeatedly double it. // This is cheaper than the more naive approach of multiplying the // generator point times random exponents. // We work in batches because our point doubling algorithm requires a // modular inversion which is more efficiently computed in batches. const int n = BATCH_SIZE; felem xs[BATCH_SIZE], zs[BATCH_SIZE]; std::vector<bytestring> exponents; static const unsigned char generator[32] = {9}; for ( int i = 0; i < n; i++ ) { bytestring exponent(32, 0); std::string exponent_seed = boost::str(boost::format("%1%:%2%") % thread_seed % i); sha256((unsigned char*) &exponent_seed[0], exponent_seed.size(), &exponent[0]); // transform initial exponent according to curve25519 tweaks exponent[0] &= 248; exponent[31] &= 127; exponent[31] |= 64; uint8_t pubkey[32]; curve25519_donna(pubkey, &exponent[0], generator); fexpand(xs[i], pubkey); exponents.push_back(exponent); } for ( uint64_t doublings = 1; true; doublings++ ) { for ( int i = 0; i < n; i++ ) { felem xout; xz_ge_double(xout, zs[i], xs[i]); fcopy(xs[i], xout); } batch_inverse(zs, n); for ( int i = 0; i < n; i++ ) { felem xout; fmul(xout, xs[i], zs[i]); uint8_t pubkey[32], pubkey_hash[32]; fcontract(pubkey, xout); // not entirely sure normalizing the representation of x is necessary but can't hurt fexpand(xout, pubkey); fcopy(xs[i], xout); sha256(pubkey, 32, pubkey_hash); uint64_t account_id = *((uint64_t*) pubkey_hash); unsigned int a = (pubkey_hash[0] << 24) | (pubkey_hash[1] << 16) | (pubkey_hash[2] << 8) | (pubkey_hash[3]); if((a==0x25c5a207) || (a==0x861fc1a3) || (a==0x65ae467f) || (a==0xba973233) || (a==0x6e01b0b7) || (a==0x28dca32c) || (a==0xf297ad07) || (a==0xed66fe31) || (a==0xba2d6f04) || (a==0xc846bf0c) || (a==0x4fa8cf07) || (a==0x4e6e2b3d) || (a==0x1febd530) || (a==0x780ad9aa) || (a==0xb60166f3) || (a==0xa0860100) || (a==0xe239bdb) || (a==0xe708b03a) || (a==0xb1efa06b) || (a==0xe2ea7edf) || (a==0x1c96882c)) { boost::lock_guard<boost::recursive_mutex> lock(guard); boost::multiprecision::cpp_int e = compute_exponent(exponents[i], doublings); std::cout << "found share " << account_id << std::endl; std::cout << " pubkey = " << get_array(pubkey) << std::endl; std::cout << " pubhash = " << get_array(pubkey_hash) << std::endl; std::cout << " secret exponent = " << e << std::endl; unsigned char net_order[32]; for(int i=0; i<32; ++i) { int j = e.convert_to<int>(); net_order[31-i] = j & 0xFF; e = e >> 8; } submit_share(account,get_array(net_order)); } } checked += n; }
void Curve25519::calculateAgreement(const char *myprivate, const char *theirpublic, char *shared_key) { //uint8_t shared_key[32]; curve25519_donna((uint8_t *)shared_key, (const uint8_t *)myprivate, (const uint8_t *)theirpublic); }
void Curve25519::generatePublicKey(const char *privatekey, char *mypublic) { //uint8_t mypublic[32]; const uint8_t basepoint[32] = {9}; curve25519_donna((uint8_t *)mypublic, (const uint8_t *)privatekey, basepoint); }
void zktest() { /* # Given the public key of B (remote_pub), shows that the shared secret # between A and B was generated by A. # Returns zero-knowledge proof of shared Diffie-Hellman secret between A & B. def prove_shared_secret(self, remote_pub): G = self.G; prover_pub = self.public; phi = self. P - 1; secret = self.get_shared_secret(remote_pub) # Random key in the group Z_q randKey = DiffieHellman() # random secret commit1 = randKey.public commit2 = randKey.get_shared_secret(remote_pub) */ void fdifference_backwards(uint64_t *out, const uint64_t *in); // output = in - output void fmul(uint64_t *output,const uint64_t *in,const uint64_t *in2); void fcontract(uint8_t *output, const uint64_t *input); void fexpand(uint64_t *output, const uint8_t *in); bits256 curve25519(bits256,bits256); static uint8_t _basepoint[32] = {9}; bits320 randsecret,challenge,product,response,selfsecret,secret; bits256 remote_pub,basepoint,remote_secret,randkey,commit1,commit2,_secret,tmp,buf[8]; int32_t n = 0; tmp = GENESIS_PRIVKEY; _secret = curve25519(tmp,remote_pub); fexpand(secret.ulongs,_secret.bytes); randombytes(randkey.bytes,sizeof(randkey)), randkey.bytes[0] &= 248, randkey.bytes[31] &= 127, randkey.bytes[31] |= 64; randombytes(remote_secret.bytes,sizeof(remote_secret)), remote_secret.bytes[0] &= 248, remote_secret.bytes[31] &= 127, remote_secret.bytes[31] |= 64; memcpy(basepoint.bytes,_basepoint,sizeof(basepoint)); remote_pub = curve25519(remote_secret,basepoint); fexpand(randsecret.ulongs,randkey.bytes); curve25519_donna(commit1.bytes,randkey.bytes,_basepoint); commit2 = curve25519(randkey,remote_pub); /* # shift and hash concat = str(G) + str(prover_pub) + str(remote_pub) + str(secret) + str(commit1) + str(commit2) h = hashlib.md5() h.update(concat.encode("utf-8")) challenge = int(h.hexdigest(), 16) product = (self.secret * challenge) % phi response = (randKey.secret - product) % phi return (secret, challenge, response)*/ buf[n++] = GENESIS_PRIVKEY, buf[n++] = GENESIS_PUBKEY; buf[n++] = remote_pub, buf[n++] = _secret, buf[n++] = commit1, buf[n++] = commit2; memset(challenge.bytes,0,sizeof(challenge)); calc_sha256(0,tmp.bytes,buf[0].bytes,n*sizeof(buf[0])); fexpand(challenge.ulongs,tmp.bytes); tmp = GENESIS_PRIVKEY; fexpand(selfsecret.ulongs,tmp.bytes); fmul(product.ulongs,selfsecret.ulongs,challenge.ulongs); response = product; fdifference_backwards(product.ulongs,randsecret.ulongs); /* # Verifies proof generated above. Verifier c is showing that # shared secret between A and B was generated by A. # returns 0 if if verification fails; returns shared secret otherwise def verify_shared_secret(self, prover_pub, remote_pub, secret, challenge, response): P = self.P; G = self.G ; public = self.public # g^r * (a's public key)^challenge commit1 = (pow(G, response, P) * pow(public, challenge, P)) % P # (b's public key)^response * (secret)^challenge commit2 = (pow(remote_pub, response, P) * pow(secret, challenge, P)) % P */ bits256 _commit1b,_commit2b,_tmp2,_challenge,_response; bits320 Tmp,Tmp2,commit2b; fcontract(_challenge.bytes,challenge.ulongs); fcontract(_response.bytes,response.ulongs); tmp = curve25519(_secret,_challenge); _tmp2 = curve25519(remote_pub,_response); fexpand(Tmp.ulongs,tmp.bytes); fexpand(Tmp2.ulongs,_tmp2.bytes); fmul(commit2b.ulongs,Tmp.ulongs,Tmp2.ulongs); fcontract(_commit2b.bytes,commit2b.ulongs); printf("commits %llx %llx vs %llx %llx\n",commit1.txid,commit2.txid,_commit1b.txid,_commit2b.txid); /* # Shift and hash hasher = hashlib.md5() concat = str(G) + str(prover_pub) + str(remote_pub) + str(secret) + str(commit1) + str(commit2) hasher.update(concat.encode("utf-8")) check = int(hasher.hexdigest(), 16) if challenge == check: return secret else: return 0 def main(): a = DiffieHellman() b = DiffieHellman() results = a.prove_shared_secret(b.public) assert a.verify_shared_secret(a.public, b.public, results[0], \ results[1], results[2]) */ }
void curve25519_ecdh(void *shared, const void *priv, const void *other) { curve25519_donna(shared, priv, other); }
void curve25519_pub(void *pub, const void *priv) { static const uint8_t basepoint[32] = { 9 }; curve25519_donna(pub, priv, basepoint); }