SECP256K1_API jobjectArray JNICALL Java_org_commercium_NativeSecp256k1_secp256k1_1privkey_1tweak_1add (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) { secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); const unsigned char* tweak = (unsigned char*) (privkey + 32); jobjectArray retArray; jbyteArray privArray, intsByteArray; unsigned char intsarray[2]; int privkeylen = 32; int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); intsarray[0] = privkeylen; intsarray[1] = ret; retArray = (*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "[B"), (*env)->NewByteArray(env, 1)); privArray = (*env)->NewByteArray(env, privkeylen); (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); (*env)->SetObjectArrayElement(env, retArray, 0, privArray); 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 corresponding private keys can be similarly derived, if the basepoint * secrets are known (i.e. the private keys corresponding to `localpubkey`, * `local_htlcpubkey`, and `local_delayedpubkey` only): * * privkey = basepoint_secret + SHA256(per_commitment_point || basepoint) */ bool derive_simple_privkey(const struct secret *base_secret, const struct pubkey *basepoint, const struct pubkey *per_commitment_point, struct privkey *key) { struct sha256 sha; unsigned char der_keys[PUBKEY_CMPR_LEN * 2]; 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 || 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, sizeof(sha))); #endif key->secret = *base_secret; if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data, sha.u.u8) != 1) return false; #ifdef SUPERVERBOSE printf("# + basepoint_secret (0x%s)\n", tal_hexstr(tmpctx, base_secret, sizeof(*base_secret))); printf("# = 0x%s\n", tal_hexstr(tmpctx, key, sizeof(*key))); #endif return true; }
bool bp_key_add_secret(struct bp_key *out, const struct bp_key *key, const uint8_t *tweak32) { secp256k1_context *ctx = get_secp256k1_context(); if (!ctx) { return false; } // If the secret is valid, tweak it and calculate the // resulting public key. Otherwise tweak the public key (and // ensure the output private key is invalid). if (secp256k1_ec_seckey_verify(ctx, key->secret)) { memcpy(out->secret, key->secret, sizeof(key->secret)); if (secp256k1_ec_privkey_tweak_add(ctx, out->secret, tweak32)) { return secp256k1_ec_pubkey_create( ctx, &out->pubkey, out->secret); } return false; } memset(out->secret, 0, sizeof(out->secret)); memcpy(&out->pubkey, &key->pubkey, sizeof(secp256k1_pubkey)); return secp256k1_ec_pubkey_tweak_add(ctx, &out->pubkey, tweak32); }
PrivateKey & PrivateKey::operator += (const PrivateKey &privateKey) { if(!secp256k1_ec_privkey_tweak_add(getContext().get(), data(), privateKey.data())) { throw std::runtime_error("private key operation failed"); } return *this; }
/* BOLT #3: * * The corresponding private key can be derived once the `per_commitment_secret` * is known: * * revocationprivkey = revocation_basepoint_secret * SHA256(revocation_basepoint || per_commitment_point) + per_commitment_secret * SHA256(per_commitment_point || revocation_basepoint) */ bool derive_revocation_privkey(const struct secret *base_secret, const struct secret *per_commitment_secret, const struct pubkey *basepoint, const struct pubkey *per_commitment_point, struct privkey *key) { struct sha256 sha; unsigned char der_keys[PUBKEY_CMPR_LEN * 2]; struct secret part2; 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 key->secret = *base_secret; if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, key->secret.data, sha.u.u8) != 1) return false; #ifdef SUPERVERBOSE printf("# * revocation_basepoint_secret (0x%s)", tal_hexstr(tmpctx, base_secret, sizeof(*base_secret))), printf("# = 0x%s\n", tal_hexstr(tmpctx, key, sizeof(*key))), #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 part2 = *per_commitment_secret; if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, part2.data, sha.u.u8) != 1) return false; #ifdef SUPERVERBOSE printf("# * per_commitment_secret (0x%s)", tal_hexstr(tmpctx, per_commitment_secret, sizeof(*per_commitment_secret))), printf("# = 0x%s\n", tal_hexstr(tmpctx, &part2, sizeof(part2))); #endif if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data, part2.data) != 1) return false; #ifdef SUPERVERBOSE printf("# => 0x%s\n", tal_hexstr(tmpctx, key, sizeof(*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_add(ec_secret& a, const ec_secret& b) { init.init(); return secp256k1_ec_privkey_tweak_add(a.data(), b.data()) == 1; }
bool ecc_private_key_tweak_add(uint8_t *private_key, const uint8_t *tweak) { assert(secp256k1_ctx); return secp256k1_ec_privkey_tweak_add(secp256k1_ctx, (unsigned char *)private_key, (const unsigned char *)tweak); }
bool ec_add(ec_secret& left, const ec_secret& right) { const auto context = verification.context(); return secp256k1_ec_privkey_tweak_add(context, left.data(), right.data()) == 1; }