fc::sha512 private_key::get_shared_secret( const public_key& other )const { FC_ASSERT( my->_key != empty_priv ); FC_ASSERT( other.my->_key != nullptr ); public_key_data pub(other.serialize()); FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); return fc::sha512::hash( pub.begin() + 1, pub.size() - 1 ); }
bool ec_multiply(const secp256k1_context* context, byte_array<Size>& in_out, const ec_secret& secret) { secp256k1_pubkey pubkey; return parse(context, pubkey, in_out) && secp256k1_ec_pubkey_tweak_mul(context, &pubkey, secret.data()) == 1 && serialize(context, in_out, pubkey); }
SECP256K1_API jobjectArray JNICALL Java_org_commercium_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) { secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); const unsigned char* tweak = (unsigned char*) (pkey + publen); jobjectArray retArray; jbyteArray pubArray, intsByteArray; unsigned char intsarray[2]; unsigned char outputSer[65]; size_t outputLen = 65; secp256k1_pubkey pubkey; int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); if ( ret ) { ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); } if( ret ) { int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; } intsarray[0] = outputLen; intsarray[1] = ret; retArray = (*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "[B"), (*env)->NewByteArray(env, 1)); pubArray = (*env)->NewByteArray(env, outputLen); (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); intsByteArray = (*env)->NewByteArray(env, 2); (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); (void)classObject; return retArray; }
/* BOLT #3: * * The `revocationpubkey` is a blinded key: when the local node wishes to * create a new commitment for the remote node, it uses its own * `revocation_basepoint` and the remote node's `per_commitment_point` to * derive a new `revocationpubkey` for the commitment. After the remote node * reveals the `per_commitment_secret` used (thereby revoking that * commitment), the local node can then derive the `revocationprivkey`, as it * now knows the two secrets necessary to derive the key * (`revocation_basepoint_secret` and `per_commitment_secret`). * * The `per_commitment_point` is generated using elliptic-curve multiplication: * * per_commitment_point = per_commitment_secret * G * * And this is used to derive the revocation pubkey from the remote node's * `revocation_basepoint`: * * revocationpubkey = revocation_basepoint * SHA256(revocation_basepoint || per_commitment_point) + per_commitment_point * SHA256(per_commitment_point || revocation_basepoint) */ bool derive_revocation_key(const struct pubkey *basepoint, const struct pubkey *per_commitment_point, struct pubkey *key) { struct sha256 sha; unsigned char der_keys[PUBKEY_CMPR_LEN * 2]; secp256k1_pubkey add[2]; const secp256k1_pubkey *args[2]; pubkey_to_der(der_keys, basepoint); pubkey_to_der(der_keys + PUBKEY_CMPR_LEN, per_commitment_point); sha256(&sha, der_keys, sizeof(der_keys)); #ifdef SUPERVERBOSE printf("# SHA256(revocation_basepoint || per_commitment_point)\n"); printf("# => SHA256(0x%s || 0x%s)\n", tal_hexstr(tmpctx, der_keys, PUBKEY_CMPR_LEN), tal_hexstr(tmpctx, der_keys + PUBKEY_CMPR_LEN, PUBKEY_CMPR_LEN)); printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))), #endif add[0] = basepoint->pubkey; if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &add[0], sha.u.u8) != 1) return false; #ifdef SUPERVERBOSE printf("# x revocation_basepoint = 0x%s\n", type_to_string(tmpctx, secp256k1_pubkey, &add[0])); #endif pubkey_to_der(der_keys, per_commitment_point); pubkey_to_der(der_keys + PUBKEY_CMPR_LEN, basepoint); sha256(&sha, der_keys, sizeof(der_keys)); #ifdef SUPERVERBOSE printf("# SHA256(per_commitment_point || revocation_basepoint)\n"); printf("# => SHA256(0x%s || 0x%s)\n", tal_hexstr(tmpctx, der_keys, PUBKEY_CMPR_LEN), tal_hexstr(tmpctx, der_keys + PUBKEY_CMPR_LEN, PUBKEY_CMPR_LEN)); printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))), #endif add[1] = per_commitment_point->pubkey; if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &add[1], sha.u.u8) != 1) return false; #ifdef SUPERVERBOSE printf("# x per_commitment_point = 0x%s\n", type_to_string(tmpctx, secp256k1_pubkey, &add[1])); #endif args[0] = &add[0]; args[1] = &add[1]; if (secp256k1_ec_pubkey_combine(secp256k1_ctx, &key->pubkey, args, 2) != 1) return false; #ifdef SUPERVERBOSE printf("# 0x%s + 0x%s => 0x%s\n", type_to_string(tmpctx, secp256k1_pubkey, args[0]), type_to_string(tmpctx, secp256k1_pubkey, args[1]), type_to_string(tmpctx, struct pubkey, key)); #endif return true; }
void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; /* Generate a random key and message. */ { secp256k1_scalar_t msg, key; random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_scalar_get_b32(message, &msg); } /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(privkey) == 1); unsigned char pubkey[65]; int pubkeylen = 65; CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1); CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen)); /* Verify private key import and export. */ unsigned char seckey[300]; int seckeylen = 300; CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); unsigned char privkey2[32]; CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1); CHECK(memcmp(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ if (secp256k1_rand32() % 3 == 0) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); int ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd); int ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd); CHECK(ret1 == ret2); if (ret1 == 0) return; unsigned char pubkey2[65]; int pubkeylen2 = 65; CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } /* Optionally tweak the keys using multiplication. */ if (secp256k1_rand32() % 3 == 0) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); int ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd); int ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd); CHECK(ret1 == ret2); if (ret1 == 0) return; unsigned char pubkey2[65]; int pubkeylen2 = 65; CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); } /* Sign. */ unsigned char signature[72]; int signaturelen = 72; while(1) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); if (secp256k1_ecdsa_sign(message, 32, signature, &signaturelen, privkey, rnd) == 1) { break; } } /* Verify. */ CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) == 1); /* Destroy signature and verify again. */ signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) != 1); /* Compact sign. */ unsigned char csignature[64]; int recid = 0; while(1) { unsigned char rnd[32]; secp256k1_rand256_test(rnd); if (secp256k1_ecdsa_sign_compact(message, 32, csignature, privkey, rnd, &recid) == 1) { break; } } /* Recover. */ unsigned char recpubkey[65]; int recpubkeylen = 0; CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); CHECK(recpubkeylen == pubkeylen); CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0); /* Destroy signature and verify again. */ csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 || memcmp(pubkey, recpubkey, pubkeylen) != 0); CHECK(recpubkeylen == pubkeylen); }
bool ec_multiply(ec_point& a, const ec_secret& b) { init.init(); return secp256k1_ec_pubkey_tweak_mul(a.data(), a.size(), b.data()) == 1; }