int main(void) { int i; secp256k1_pubkey_t pubkey; secp256k1_ecdsa_signature_t sig; benchmark_verify_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); for (i = 0; i < 32; i++) { data.msg[i] = 1 + i; } for (i = 0; i < 32; i++) { data.key[i] = 33 + i; } data.siglen = 72; CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); secp256k1_context_destroy(data.ctx); return 0; }
int main(void) { int i; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature sig; benchmark_verify_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); for (i = 0; i < 32; i++) { data.msg[i] = 1 + i; } for (i = 0; i < 32; i++) { data.key[i] = 33 + i; } data.siglen = 72; CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); data.pubkeylen = 33; CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); #ifdef ENABLE_OPENSSL_TESTS data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); EC_GROUP_free(data.ec_group); #endif secp256k1_context_destroy(data.ctx); return 0; }
bool sign(ec_signature& out, const ec_secret& secret, const hash_digest& hash) { secp256k1_ecdsa_signature signature; const auto context = signing.context(); if (secp256k1_ecdsa_sign(context, &signature, hash.data(), secret.data(), secp256k1_nonce_function_rfc6979, nullptr) != 1) return false; std::copy_n(std::begin(signature.data), out.size(), out.begin()); return true; }
bool ecc_sign(const uint8_t *private_key, const uint8_t *hash, unsigned char *sigder, size_t *outlen) { assert(secp256k1_ctx); secp256k1_ecdsa_signature sig; if (!secp256k1_ecdsa_sign(secp256k1_ctx, &sig, hash, private_key, secp256k1_nonce_function_rfc6979, NULL)) return false; if (secp256k1_ecdsa_signature_serialize_der(secp256k1_ctx, sigder, outlen, &sig)) return false; return true; }
endorsement sign(ec_secret secret, hash_digest hash, ec_secret nonce) { init.init(); int out_size = max_endorsement_size; endorsement signature(out_size); if (0 < secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(), &out_size, secret.data(), nonce.data())) { signature.resize(out_size); return signature; } // Error case: return endorsement(); }
data_chunk sign(ec_secret secret, hash_digest hash, ec_secret nonce) { std::reverse(hash.begin(), hash.end()); init.init(); int out_size = 72; data_chunk signature(out_size); if (!verify_private_key(nonce)) // Needed because of upstream bug return data_chunk(); bool valid = secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(), &out_size, secret.data(), nonce.data()) == 1; if (!valid) return data_chunk(); signature.resize(out_size); return signature; }
endorsement sign(ec_secret secret, hash_digest hash) { init.init(); int out_size = max_endorsement_size; endorsement signature(out_size); ec_secret nonce; unsigned index = 0; do { nonce = create_nonce(secret, hash, index++); } while (secp256k1_ecdsa_sign(hash.data(), hash.size(), signature.data(), &out_size, secret.data(), nonce.data()) <= 0); signature.resize(out_size); return signature; }
void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { int i, j, k; /* Loop */ for (i = 1; i < order; i++) { /* message */ for (j = 1; j < order; j++) { /* key */ for (k = 1; k < order; k++) { /* nonce */ const int starting_k = k; secp256k1_ecdsa_signature sig; secp256k1_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; secp256k1_scalar_set_int(&msg, i); secp256k1_scalar_set_int(&sk, j); secp256k1_scalar_get_b32(sk32, &sk); secp256k1_scalar_get_b32(msg32, &msg); secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); /* Note that we compute expected_r *after* signing -- this is important * because our nonce-computing function function might change k during * signing. */ r_from_k(&expected_r, group, k); CHECK(r == expected_r); CHECK((k * s) % order == (i + r * j) % order || (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); /* Overflow means we've tried every possible nonce */ if (k < starting_k) { break; } } } } /* We would like to verify zero-knowledge here by counting how often every * possible (s, r) tuple appears, but because the group order is larger * than the field order, when coercing the x-values to scalar values, some * appear more often than others, so we are actually not zero-knowledge. * (This effect also appears in the real code, but the difference is on the * order of 1/2^128th the field order, so the deviation is not useful to a * computationally bounded attacker.) */ }
void sign_hash(secp256k1_context *secpctx, const struct privkey *privkey, const struct sha256_double *h, struct signature *s) { bool ok; #ifdef USE_SCHNORR ok = secp256k1_schnorr_sign(secpctx, s->schnorr, h->sha.u.u8, privkey->secret, NULL, NULL); #else ok = secp256k1_ecdsa_sign(secpctx, &s->sig, h->sha.u.u8, privkey->secret, NULL, NULL); #endif assert(ok); }
SECP256K1_API jobjectArray JNICALL Java_org_commercium_NativeSecp256k1_secp256k1_1ecdsa_1sign (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) { secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); unsigned char* secKey = (unsigned char*) (data + 32); jobjectArray retArray; jbyteArray sigArray, intsByteArray; unsigned char intsarray[2]; secp256k1_ecdsa_signature sig[72]; int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); unsigned char outputSer[72]; size_t outputLen = 72; if( ret ) { int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; } intsarray[0] = outputLen; intsarray[1] = ret; retArray = (*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "[B"), (*env)->NewByteArray(env, 1)); sigArray = (*env)->NewByteArray(env, outputLen); (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); intsByteArray = (*env)->NewByteArray(env, 2); (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); (void)classObject; return retArray; }
bool bp_sign(const struct bp_key *key, const void *data, size_t data_len, void **sig_, size_t *sig_len_) { secp256k1_ecdsa_signature sig; if (32 != data_len) { return false; } secp256k1_context *ctx = get_secp256k1_context(); if (!ctx) { return false; } if (!secp256k1_ec_seckey_verify(ctx, key->secret)) { return false; } if (!secp256k1_ecdsa_sign(ctx, &sig, data, key->secret, secp256k1_nonce_function_rfc6979, NULL)) { return false; } *sig_ = malloc(72); *sig_len_ = 72; if (!secp256k1_ecdsa_signature_serialize_der(ctx, *sig_, sig_len_, &sig)) { free(sig_); *sig_ = NULL; return false; } 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 serialize(const int devfd, struct bitcoin_storage *const st, bool serial_pad) { static struct encoder_state s; static bool first_run = true; static int buf_left = 0; // Bytes left to send static int buf_i = 0; // Bytes position of next unsent byte if (first_run) { encoder_state_init(&s); first_run = false; } gint queued = heap_size(&st->send_queue); if (!buf_left && queued) { // Try to fill send buffer struct msg *m = bitcoin_dequeue(st); // Should not happen if (m == NULL) errx(6,"Send queue handling error"); // Do not retransmit if it is already sent. if (m->sent) { printf("Already sent %s %s, skipping\n", bitcoin_type_str(m), hex256(bitcoin_inv_hash(m))); return true; } // Mark message as sent m->sent = true; // Calculate signature. FIXME: Include type in calculation! // Bitcoin message header in unidirectional // transfer. The signature is used to verify the // transmitter. Transactions have their own signature // inside message body, too. unsigned char sig[72]; int siglen; secp256k1_ecdsa_sign(m->payload,m->length,sig,&siglen,NULL,NULL); encode_start(&s); encode(&s,&siglen,1); // FIXME doesn't work on big endian archs encode(&s,&sig,siglen); encode(&s,&m->type,1); // FIXME doesn't work on big endian archs encode(&s,m->payload,m->length); // Finishing encoding and updating send buffer buf_left = encode_end(&s); buf_i = 0; // Debugging char height_buf[20] = ""; if (m->height != UNCONFIRMED) { snprintf(height_buf,sizeof(height_buf), " @ %d",m->height); } printf("Sending %s %s%s, %d bytes, %d items left\n", bitcoin_type_str(m), hex256(bitcoin_inv_hash(m)), height_buf, m->length, queued); } if (buf_left) { // Consume buffer as much as possible const int wrote = write(devfd, s.buf+buf_i, buf_left); if (wrote == 0) { errx(3,"Weird behaviour on serial port"); } else if (wrote == -1) { err(4,"Unable to write to serial port"); } buf_i += wrote; buf_left -= wrote; } else { if (!serial_pad) { // All is sent, do not come back until there // is more data availableq printf("Serial device idle\n"); return false; } // Send padding and go back to waiting loop. guint8 buf[PAD_COUNT*5]; int i = 0; while (i < sizeof(buf)) { // Z_SYNC_FLUSH is 5 bytes long: buf[i++] = 0x00; buf[i++] = 0x00; buf[i++] = 0x00; buf[i++] = 0xFF; buf[i++] = 0xFF; } const int ret = write(devfd,buf,sizeof(buf)); if (ret < 1) err(4,"Unable to write to serial port"); if (ret != sizeof(buf)) err(10,"Too large padding buffer or non-linuxy system"); printf("Sending %d bytes of padding\n",ret); } return true; }