void create_file(char* filename) { unsigned int j; FILE *urandom = fopen("/dev/urandom", "r"); crypto_sign_keypair(pk, sk); for(j=0;j<MLEN;j++) mi[j] = fgetc(urandom); crypto_sign(sm, &smlen, mi, MLEN, sk); FILE *file; file=fopen(filename,"wb"); if(file == NULL) printf("Unable to open file!\n"); fwrite(pk, 1, CRYPTO_PUBLICKEYBYTES, file); fwrite(sm, 1, MLEN+CRYPTO_BYTES, file); fwrite(&smlen, sizeof(unsigned long long), 1, file); fclose(file); for(j=0;j<CRYPTO_PUBLICKEYBYTES;j++) pk[j] = fgetc(urandom); for(j=0;j<MLEN+CRYPTO_BYTES;j++) sm[j] = fgetc(urandom); smlen = fgetc(urandom); fclose(urandom); }
void speed_ed25519() { unsigned long long t[NTIMINGS]; int i; unsigned char pk[32]; unsigned char sk[64]; // Benchmarking keypair for(i=0;i<NTIMINGS;i++) { t[i] = cpucycles(); crypto_sign_keypair(pk, sk); } print_bench("sign_keypair",t,NTIMINGS); // Benchmarking sign for(i=0;i<NTIMINGS;i++) { t[i] = cpucycles(); crypto_sign(sm, &smlen, msg, MLEN, sk); } print_bench("sign (59 bytes)",t,NTIMINGS); // Benchmarking sign_open for(i=0;i<NTIMINGS;i++) { t[i] = cpucycles(); crypto_sign_open(mo, &mlen, sm, smlen, pk); } print_bench("sign_open (59 bytes)",t,NTIMINGS); }
PyObject *pycrypto_sign_keypair(PyObject *self){ PyObject *pypk, *pysk, *pyret; unsigned char pk[crypto_sign_PUBLICKEYBYTES]; unsigned char sk[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(pk, sk); pypk = PyBytes_FromStringAndSize((char *)pk, crypto_sign_PUBLICKEYBYTES); if (!pypk) return (PyObject *)0; pysk = PyBytes_FromStringAndSize((char *)sk, crypto_sign_SECRETKEYBYTES); if (!pysk){ Py_DECREF(pypk); return (PyObject *)0;} pyret = PyTuple_New(2); if (!pyret){ Py_DECREF(pypk); Py_DECREF(pysk); return (PyObject *)0;} PyTuple_SET_ITEM(pyret, 0, pypk); PyTuple_SET_ITEM(pyret, 1, pysk); return pyret;}
static char * createGUID() { sodium_init(); unsigned char out[crypto_hash_sha512_BYTES]; unsigned char sk[crypto_sign_SECRETKEYBYTES]; int valid_pow = 0; while (valid_pow == 0){ //Generate a key pair unsigned char pk[crypto_sign_PUBLICKEYBYTES]; unsigned char sk[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(pk, sk); //Sign the public key const unsigned char * message = pk; int message_len = crypto_sign_PUBLICKEYBYTES; unsigned char signed_message[crypto_sign_BYTES + message_len]; unsigned long long signed_message_len; crypto_sign(signed_message, &signed_message_len, message, message_len, sk); //Hash the signed key with sha512 crypto_hash_sha512(out, signed_message, signed_message_len); char proof_of_work[32]; memcpy(proof_of_work, &out[32], 32); char * pow = to_hex(proof_of_work, 3); valid_pow = test_pow(pow); } to_hex(sk, 32); return to_hex(sk, 32); }
bool unit_test_crypto_sign(){ uint64_t len = HACL_UNIT_TESTS_SIZE * sizeof(uint8_t); uint8_t *plaintext = malloc(HACL_UNIT_TESTS_SIZE * sizeof (uint8_t)); uint8_t *expected_signed_msg = malloc((HACL_UNIT_TESTS_SIZE+64) * sizeof (uint8_t)); uint8_t *hacl_signed_msg = malloc((HACL_UNIT_TESTS_SIZE+64) * sizeof (uint8_t)); uint8_t sk[64], pk[32]; crypto_sign_keypair(pk, sk); READ_RANDOM_BYTES(len, plaintext); int a, res; bool pass = true; long long unsigned int smlen; for (int i = 0; i < 256; i++){ tweet_crypto_sign(expected_signed_msg, &smlen, plaintext, i, sk); crypto_sign(hacl_signed_msg, &smlen, plaintext, i, sk); a = memcmp(hacl_signed_msg, expected_signed_msg, (i+64) * sizeof(uint8_t)); if (a != 0){ pass = false; printf("crypto_sign failed on input of size %d\n", i); break; } res = crypto_sign_open(hacl_signed_msg, &smlen, expected_signed_msg, i + 64, pk); if (res != 0) { pass = false; printf("crypto_sign_open returned value failed on input of size %d\n", i); break; } a = memcmp(hacl_signed_msg, plaintext, i * sizeof(uint8_t)); if (a != 0){ pass = false; printf("crypto_sign_open failed on input of size %d\n", i); break; } } if (!pass) return pass; tweet_crypto_sign(expected_signed_msg, &smlen, plaintext, HACL_UNIT_TESTS_SIZE, sk); crypto_sign(hacl_signed_msg, &smlen, plaintext, HACL_UNIT_TESTS_SIZE, sk); a = memcmp(hacl_signed_msg, expected_signed_msg, (HACL_UNIT_TESTS_SIZE+64) * sizeof (uint8_t)); if (a != 0){ pass = false; printf("crypto_sign failed on input of size %d\n.", HACL_UNIT_TESTS_SIZE); } res = crypto_sign_open(hacl_signed_msg, &smlen, expected_signed_msg, HACL_UNIT_TESTS_SIZE + 64, pk); if (res != 0) { pass = false; printf("crypto_sign_open returned value failed on input of size %d\n", HACL_UNIT_TESTS_SIZE); } a = memcmp(hacl_signed_msg, plaintext, HACL_UNIT_TESTS_SIZE * sizeof(uint8_t)); if (a != 0){ pass = false; printf("crypto_sign_open failed on input of size %d\n", HACL_UNIT_TESTS_SIZE); } free(plaintext); free(hacl_signed_msg); free(expected_signed_msg); return pass; }
CWalletTx GetValidReceive(ZCJoinSplit& params, const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) { CMutableTransaction mtx; mtx.nVersion = 2; // Enable JoinSplits mtx.vin.resize(2); if (randomInputs) { mtx.vin[0].prevout.hash = GetRandHash(); mtx.vin[1].prevout.hash = GetRandHash(); } else { mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); } mtx.vin[0].prevout.n = 0; mtx.vin[1].prevout.n = 0; // Generate an ephemeral keypair. uint256 joinSplitPubKey; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); mtx.joinSplitPubKey = joinSplitPubKey; boost::array<libzcash::JSInput, 2> inputs = { libzcash::JSInput(), // dummy input libzcash::JSInput() // dummy input }; boost::array<libzcash::JSOutput, 2> outputs = { libzcash::JSOutput(sk.address(), value), libzcash::JSOutput(sk.address(), value) }; boost::array<libzcash::Note, 2> output_notes; // Prepare JoinSplits uint256 rt; JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 2*value, 0, false}; mtx.vjoinsplit.push_back(jsdesc); // Empty output script. CScript scriptCode; CTransaction signTx(mtx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); // Add the signature assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; return wtx; }
static int sign_keypair(lua_State *L) { unsigned char sk[crypto_sign_SECRETKEYBYTES]; unsigned char pk[crypto_sign_PUBLICKEYBYTES]; if (crypto_sign_keypair(pk, sk)) { lua_pushnil(L); lua_pushstring(L, "Failed to create keys."); return 2; } lua_pushlstring(L, (char*)sk, crypto_sign_SECRETKEYBYTES); lua_pushlstring(L, (char*)pk, crypto_sign_PUBLICKEYBYTES); return 2; }
void measure(void) { int i; int loop; for (loop = 0;loop < LOOPS;++loop) { for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); crypto_sign_keypair(pk,sk); } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(-1,"keypair_cycles",cycles,TIMINGS); for (mlen = 0;mlen <= MAXTEST_BYTES;mlen += 1 + mlen / 4) { randombytes(m,mlen); for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); bytes[i] = crypto_sign(sm,&smlen,m,mlen,sk); if (bytes[i] == 0) bytes[i] = smlen; } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(mlen,"cycles",cycles,TIMINGS); printentry(mlen,"bytes",bytes,TIMINGS); for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); bytes[i] = crypto_sign_open(t,&tlen,sm,smlen,pk); if (bytes[i] == 0) bytes[i] = tlen; } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(mlen,"open_cycles",cycles,TIMINGS); printentry(mlen,"open_bytes",bytes,TIMINGS); } } }
CWalletTx GetValidSpend(ZCJoinSplit& params, const libzcash::SpendingKey& sk, const libzcash::Note& note, CAmount value) { CMutableTransaction mtx; mtx.vout.resize(2); mtx.vout[0].nValue = value; mtx.vout[1].nValue = 0; // Generate an ephemeral keypair. uint256 joinSplitPubKey; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); mtx.joinSplitPubKey = joinSplitPubKey; // Fake tree for the unused witness ZCIncrementalMerkleTree tree; libzcash::JSOutput dummyout; libzcash::JSInput dummyin; { if (note.value > value) { libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); libzcash::PaymentAddress dummyaddr = dummykey.address(); dummyout = libzcash::JSOutput(dummyaddr, note.value - value); } else if (note.value < value) { libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); libzcash::PaymentAddress dummyaddr = dummykey.address(); libzcash::Note dummynote(dummyaddr.a_pk, (value - note.value), uint256(), uint256()); tree.append(dummynote.cm()); dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey); } } tree.append(note.cm()); boost::array<libzcash::JSInput, 2> inputs = { libzcash::JSInput(tree.witness(), note, sk), dummyin }; boost::array<libzcash::JSOutput, 2> outputs = { dummyout, // dummy output libzcash::JSOutput() // dummy output }; boost::array<libzcash::Note, 2> output_notes; // Prepare JoinSplits uint256 rt = tree.root(); JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 0, value, false}; mtx.vjoinsplit.push_back(jsdesc); // Empty output script. CScript scriptCode; CTransaction signTx(mtx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); // Add the signature assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; return wtx; }
static void salt_handle_req(struct salt_pcb *sc, struct salt_msg *sm) { const char *err; nif_bin_t pk; nif_bin_t sk; nif_bin_t rb; /* Preemptive termination check via dirty read. */ if (sc->sc_exit_flag) { err = "exiting"; goto fail_0; } /* Perform know request or reject unknown (forwards compatibility). */ switch (sm->msg_type) { case SALT_MSG_BOXKEYPAIR_REQ: if (! enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) { err = "enomem"; goto fail_0; } if (! enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) { err = "enomem"; goto fail_1; } crypto_box_keypair(pk.data, sk.data); salt_reply_keypair(sm, &pk, &sk); break; case SALT_MSG_SIGNKEYPAIR_REQ: if (! enif_alloc_binary(crypto_sign_PUBLICKEYBYTES, &pk)) { err = "enomem"; goto fail_0; } if (! enif_alloc_binary(crypto_sign_SECRETKEYBYTES, &sk)) { err = "enomem"; goto fail_1; } crypto_sign_keypair(pk.data, sk.data); salt_reply_keypair(sm, &pk, &sk); break; case SALT_MSG_RANDOMBYTES_REQ: if (! enif_alloc_binary(sm->msg_aux, &rb)) { err = "enomem"; goto fail_0; } /* XXX not sure I want to rely on native RNG, but not sure either if salsa20 randombytes is kosher */ /* XXX probably best to write one that uses dev random but also encrypts output with stream cipher? */ randombytes_buf(rb.data, rb.size); salt_reply_bytes(sm, &rb); break; default: err = "unsupported"; goto fail_0; } return ; /* Failure treatment. */ fail_1: enif_release_binary(&pk); fail_0: salt_reply_error(sm, err); return ; }
static int generate(const char *pk_file, const char *sk_file, const char *comment) { char *pwd = xsodium_malloc(PASSWORDMAXBYTES); char *pwd2 = xsodium_malloc(PASSWORDMAXBYTES); SeckeyStruct *seckey_struct = xsodium_malloc(sizeof(SeckeyStruct)); PubkeyStruct *pubkey_struct = xsodium_malloc(sizeof(PubkeyStruct)); unsigned char *stream ; FILE *fp; randombytes_buf(seckey_struct->keynum_sk.keynum, sizeof seckey_struct->keynum_sk.keynum); crypto_sign_keypair(pubkey_struct->keynum_pk.pk, seckey_struct->keynum_sk.sk); memcpy(seckey_struct->sig_alg, SIGALG, sizeof seckey_struct->sig_alg); memcpy(seckey_struct->kdf_alg, KDFALG, sizeof seckey_struct->kdf_alg); memcpy(seckey_struct->chk_alg, CHKALG, sizeof seckey_struct->chk_alg); randombytes_buf(seckey_struct->kdf_salt, sizeof seckey_struct->kdf_salt); le64_store(seckey_struct->kdf_opslimit_le, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE); le64_store(seckey_struct->kdf_memlimit_le, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE); seckey_chk(seckey_struct->keynum_sk.chk, seckey_struct); memcpy(pubkey_struct->keynum_pk.keynum, seckey_struct->keynum_sk.keynum, sizeof pubkey_struct->keynum_pk.keynum); memcpy(pubkey_struct->sig_alg, SIGALG, sizeof pubkey_struct->sig_alg); puts("Please enter a password to protect the secret key.\n"); if (get_password(pwd, PASSWORDMAXBYTES, "Password: "******"Password (one more time): ") != 0) { exit_msg("get_password()"); } if (strcmp(pwd, pwd2) != 0) { exit_msg("Passwords don't match"); } printf("Deriving a key from the password in order to encrypt the secret key... "); fflush(stdout); stream = xsodium_malloc(sizeof seckey_struct->keynum_sk); if (crypto_pwhash_scryptsalsa208sha256 (stream, sizeof seckey_struct->keynum_sk, pwd, strlen(pwd), seckey_struct->kdf_salt, le64_load(seckey_struct->kdf_opslimit_le), le64_load(seckey_struct->kdf_memlimit_le)) != 0) { abort(); } sodium_free(pwd); sodium_free(pwd2); xor_buf((unsigned char *) (void *) &seckey_struct->keynum_sk, stream, sizeof seckey_struct->keynum_sk); sodium_free(stream); puts("done\n"); if ((fp = fopen_create_useronly(sk_file)) == NULL) { exit_err(sk_file); } xfprintf(fp, "%s%s\n", COMMENT_PREFIX, comment); xfput_b64(fp, (unsigned char *) (void *) seckey_struct, sizeof *seckey_struct); xfclose(fp); sodium_free(seckey_struct); if ((fp = fopen(pk_file, "w")) == NULL) { exit_err(pk_file); } xfprintf(fp, COMMENT_PREFIX "minisign public key %" PRIX64 "\n", le64_load(pubkey_struct->keynum_pk.keynum)); xfput_b64(fp, (unsigned char *) (void *) pubkey_struct, sizeof *pubkey_struct); xfclose(fp); printf("The secret key was saved as %s - Keep it secret!\n", sk_file); printf("The public key was saved as %s - That one can be public.\n\n", pk_file); puts("Files signed using this key pair can be verified with the following command:\n"); printf("minisign -Vm <file> -P "); xfput_b64(stdout, (unsigned char *) (void *) pubkey_struct, sizeof *pubkey_struct); puts(""); sodium_free(pubkey_struct); return 0; }
int main(void) { volatile unsigned char a; /* Mark the beginning of the stack */ for(i=0;i<5;i++) { canary = random(); WRITE_CANARY(&a); crypto_sign_keypair(pk,sk); newctr =(unsigned int)&a - (unsigned int)&_end - stack_count(canary); ctr = (newctr>ctr)?newctr:ctr; } print_stack(XSTR(crypto_sign_keypair),-1,ctr); for(i=0;i<5;i++) { canary = random(); WRITE_CANARY(&a); crypto_sign(sm,&smlen,sm,0,sk); newctr =(unsigned int)&a - (unsigned int)&_end - stack_count(canary); ctr = (newctr>ctr)?newctr:ctr; } print_stack(XSTR(crypto_sign),0,ctr); for(i=0;i<5;i++) { canary = random(); WRITE_CANARY(&a); crypto_sign_open(sm,&mlen,sm,smlen,pk); newctr =(unsigned int)&a - (unsigned int)&_end - stack_count(canary); ctr = (newctr>ctr)?newctr:ctr; } print_stack(XSTR(crypto_sign_open),smlen,ctr); for(j=1;j<=MAXTEST_BYTES;j<<=1) { mlen = j; for(i=0;i<5;i++) { canary = random(); WRITE_CANARY(&a); crypto_sign(sm,&smlen,sm,mlen,sk); newctr =(unsigned int)&a - (unsigned int)&_end - stack_count(canary); ctr = (newctr>ctr)?newctr:ctr; } print_stack(XSTR(crypto_sign),mlen,ctr); for(i=0;i<5;i++) { canary = random(); WRITE_CANARY(&a); crypto_sign_open(sm,&mlen,sm,smlen,pk); newctr =(unsigned int)&a - (unsigned int)&_end - stack_count(canary); ctr = (newctr>ctr)?newctr:ctr; } print_stack(XSTR(crypto_sign_open),smlen,ctr); } avr_end(); return 0; }
/* * Create a new set of master keys. * * Seed is optional, can be NULL. It can be of any length and doesn't * require to have high entropy. It will be used as entropy source * in addition to the OSs CPRNG. * * WARNING: Don't use Entropy from the OSs CPRNG as seed! */ return_status master_keys_create( master_keys ** const keys, //output const buffer_t * const seed, buffer_t * const public_signing_key, //output, optional, can be NULL buffer_t * const public_identity_key //output, optional, can be NULL ) { return_status status = return_status_init(); //seeds buffer_t *crypto_seeds = NULL; if (keys == NULL) { throw(INVALID_INPUT, "Invalid input for master_keys_create."); } *keys = sodium_malloc(sizeof(master_keys)); throw_on_failed_alloc(*keys); //initialize the buffers buffer_init_with_pointer((*keys)->public_signing_key, (*keys)->public_signing_key_storage, PUBLIC_MASTER_KEY_SIZE, PUBLIC_MASTER_KEY_SIZE); buffer_init_with_pointer((*keys)->private_signing_key, (*keys)->private_signing_key_storage, PRIVATE_MASTER_KEY_SIZE, PRIVATE_MASTER_KEY_SIZE); buffer_init_with_pointer((*keys)->public_identity_key, (*keys)->public_identity_key_storage, PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_init_with_pointer((*keys)->private_identity_key, (*keys)->private_identity_key_storage, PRIVATE_KEY_SIZE, PRIVATE_KEY_SIZE); if (seed != NULL) { //use external seed //create the seed buffer crypto_seeds = buffer_create_with_custom_allocator( crypto_sign_SEEDBYTES + crypto_box_SEEDBYTES, crypto_sign_SEEDBYTES + crypto_box_SEEDBYTES, sodium_malloc, sodium_free); throw_on_failed_alloc(crypto_seeds); status = spiced_random(crypto_seeds, seed, crypto_seeds->buffer_length); throw_on_error(GENERIC_ERROR, "Failed to create spiced random data."); //generate the signing keypair int status_int = 0; status_int = crypto_sign_seed_keypair( (*keys)->public_signing_key->content, (*keys)->private_signing_key_storage, crypto_seeds->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate signing keypair."); } //generate the identity keypair status_int = crypto_box_seed_keypair( (*keys)->public_identity_key->content, (*keys)->private_identity_key->content, crypto_seeds->content + crypto_sign_SEEDBYTES); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate encryption keypair."); } } else { //don't use external seed //generate the signing keypair int status_int = 0; status_int = crypto_sign_keypair( (*keys)->public_signing_key->content, (*keys)->private_signing_key->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate signing keypair."); } //generate the identity keypair status_int = crypto_box_keypair( (*keys)->public_identity_key->content, (*keys)->private_identity_key->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate encryption keypair."); } } //copy the public keys if requested if (public_signing_key != NULL) { if (public_signing_key->buffer_length < PUBLIC_MASTER_KEY_SIZE) { public_signing_key->content_length = 0; throw(INCORRECT_BUFFER_SIZE, "Public master key buffer is too short."); } if (buffer_clone(public_signing_key, (*keys)->public_signing_key) != 0) { throw(BUFFER_ERROR, "Failed to copy public signing key."); } } if (public_identity_key != NULL) { if (public_identity_key->buffer_length < PUBLIC_KEY_SIZE) { public_identity_key->content_length = 0; throw(INCORRECT_BUFFER_SIZE, "Public encryption key buffer is too short."); } if (buffer_clone(public_identity_key, (*keys)->public_identity_key) != 0) { throw(BUFFER_ERROR, "Failed to copy public encryption key."); } } cleanup: buffer_destroy_with_custom_deallocator_and_null_if_valid(crypto_seeds, sodium_free); on_error { if (keys != NULL) { sodium_free_and_null_if_valid(*keys); } return status; } if ((keys != NULL) && (*keys != NULL)) { sodium_mprotect_noaccess(*keys); } return status; }
void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t consensusBranchId) { tx.fOverwintered = insecure_rand() % 2; if (tx.fOverwintered) { if (insecure_rand() % 2) { tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; tx.nVersion = sapling_version_dist(rng); } else { tx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; tx.nVersion = overwinter_version_dist(rng); } tx.nExpiryHeight = (insecure_rand() % 2) ? insecure_rand() : 0; } else { tx.nVersion = insecure_rand() & 0x7FFFFFFF; } tx.vin.clear(); tx.vout.clear(); tx.vShieldedSpend.clear(); tx.vShieldedOutput.clear(); tx.vjoinsplit.clear(); tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; int ins = (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1; int shielded_spends = (insecure_rand() % 4) + 1; int shielded_outs = (insecure_rand() % 4) + 1; int joinsplits = (insecure_rand() % 4); for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = GetRandHash(); txin.prevout.n = insecure_rand() % 4; RandomScript(txin.scriptSig); txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); txout.nValue = insecure_rand() % 100000000; RandomScript(txout.scriptPubKey); } if (tx.nVersionGroupId == SAPLING_VERSION_GROUP_ID) { tx.valueBalance = insecure_rand() % 100000000; for (int spend = 0; spend < shielded_spends; spend++) { SpendDescription sdesc; sdesc.cv = GetRandHash(); sdesc.anchor = GetRandHash(); sdesc.nullifier = GetRandHash(); sdesc.rk = GetRandHash(); randombytes_buf(sdesc.zkproof.begin(), sdesc.zkproof.size()); tx.vShieldedSpend.push_back(sdesc); } for (int out = 0; out < shielded_outs; out++) { OutputDescription odesc; odesc.cv = GetRandHash(); odesc.cm = GetRandHash(); odesc.ephemeralKey = GetRandHash(); randombytes_buf(odesc.encCiphertext.begin(), odesc.encCiphertext.size()); randombytes_buf(odesc.outCiphertext.begin(), odesc.outCiphertext.size()); randombytes_buf(odesc.zkproof.begin(), odesc.zkproof.size()); tx.vShieldedOutput.push_back(odesc); } } if (tx.nVersion >= 2) { for (int js = 0; js < joinsplits; js++) { JSDescription jsdesc; if (insecure_rand() % 2 == 0) { jsdesc.vpub_old = insecure_rand() % 100000000; } else { jsdesc.vpub_new = insecure_rand() % 100000000; } jsdesc.anchor = GetRandHash(); jsdesc.nullifiers[0] = GetRandHash(); jsdesc.nullifiers[1] = GetRandHash(); jsdesc.ephemeralKey = GetRandHash(); jsdesc.randomSeed = GetRandHash(); randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size()); randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size()); if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { libzcash::GrothProof zkproof; randombytes_buf(zkproof.begin(), zkproof.size()); jsdesc.proof = zkproof; } else { jsdesc.proof = libzcash::PHGRProof::random_invalid(); } jsdesc.macs[0] = GetRandHash(); jsdesc.macs[1] = GetRandHash(); tx.vjoinsplit.push_back(jsdesc); } unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(tx.joinSplitPubKey.begin(), joinSplitPrivKey); // Empty output script. CScript scriptCode; CTransaction signTx(tx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); } }
// CryptoEngine constructor CryptoEngine::CryptoEngine(const std::string &context):context_(context), file_utils_(context), hkdf_(context){ try { if(context.empty()) { std::cout << "Cannot initialize the crypto engine with an empty context." << std::endl; throw g_crypto_engine_initialization_failure; } // Create the standard keys folder // IMPORTANT DO NOT REMOVE !!!!! // THE FOLDER CREATION CAN FAIL !!!! if(!file_utils_.CreateKeysFolder()) { std::cout << "Could not create the folder where to store the keys." << std::endl; throw g_crypto_engine_initialization_failure; } // **************************************************** // ######## HKDF MASTER KEY // Always generate a new HKDF master key when the crypto engine is initialized // create the nonce master key // init a uint8_t buffer uint8_t buffer_hkdf_master_key[KEY_SIZE]; // read KEY_SIZE bytes into the buffer int hkdf_random_result = RAND_bytes(buffer_hkdf_master_key, KEY_SIZE); if (1 != hkdf_random_result) { std::cout << "Could not generate the HKDF master key. Not enough entropy" << std::endl; throw g_crypto_engine_initialization_failure; } nonce_master_key_ = std::string(reinterpret_cast<const char *>(buffer_hkdf_master_key), KEY_SIZE); if (nonce_master_key_.size() != KEY_SIZE) { std::cout << "The loaded HKDF master key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } // **************************************************** // ######## SALT KEY // Always generate a new SALT key when the crypto engine is initialized // create the nonce master key // init a uint8_t buffer uint8_t buffer_salt_key[KEY_SIZE]; // read KEY_SIZE bytes into the buffer int salt_random_result = RAND_bytes(buffer_salt_key, KEY_SIZE); if (1 != salt_random_result) { std::cout << "Could not generate the salt key. Not enough entropy" << std::endl; throw g_crypto_engine_initialization_failure; } salt_ = std::string(reinterpret_cast<const char *>(buffer_salt_key), KEY_SIZE); if (salt_.size() != KEY_SIZE) { std::cout << "The loaded salt key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } // **************************************************** // ######## SECRET KEY // if the key already exists then load it if(file_utils_.KeyExists(kSecret)) { // read the key back secret_key_ = file_utils_.ReadKey(kSecret); // check the size of the key which should match the predefined one if (secret_key_.size() != KEY_SIZE) { std::cout << "The loaded secret key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } } else { // otherwise generate one // create the nonce master key // init a uint8_t buffer uint8_t buffer_secret_key[KEY_SIZE]; // read KEY_SIZE bytes into the buffer int secret_random_result = RAND_bytes(buffer_secret_key, KEY_SIZE); if (1 != secret_random_result) { std::cout << "Could not generate the secret key. Not enough entropy" << std::endl; throw g_crypto_engine_initialization_failure; } secret_key_ = std::string(reinterpret_cast<const char *>(buffer_secret_key), KEY_SIZE); if (secret_key_.size() != KEY_SIZE) { std::cout << "The loaded secret key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } if (!file_utils_.WriteKey(secret_key_,kSecret)) { std::cout << "Could not store the secret key." << std::endl; throw g_crypto_engine_initialization_failure; } } // **************************************************** // ######## PUBLIC/PRIVATE KEY if(file_utils_.KeyExists(kPrivate) && file_utils_.KeyExists(kPublic)) { // read the keys back private_key_ = file_utils_.ReadKey(kPrivate); // check the size of the key which should match the predefined one if (private_key_.size() != KEY_SIZE) { std::cout << "The loaded private key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } public_key_ = file_utils_.ReadKey(kPublic); // check the size of the key which should match the predefined one if (public_key_.size() != KEY_SIZE) { std::cout << "The loaded public key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } } else { // otherwise generate them // generate the private/public key public_key_ = crypto_box_keypair(&private_key_); if (private_key_.size() != KEY_SIZE) { std::cout << "The loaded private key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } if (public_key_.size() != KEY_SIZE) { std::cout << "The loaded public key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } if (!file_utils_.WriteKey(private_key_,kPrivate)) { std::cout << "Could not store the private key." << std::endl; throw g_crypto_engine_initialization_failure; } if (!file_utils_.WriteKey(public_key_, kPublic)) { std::cout << "Could not store the public key." << std::endl; throw g_crypto_engine_initialization_failure; } } // **************************************************** // ######## PUBLIC/PRIVATE SIGNING KEY if(file_utils_.KeyExists(kPrivateSign) && file_utils_.KeyExists(kPublicSign)) { // read the keys back sign_private_key_ = file_utils_.ReadKey(kPrivateSign); // check the size of the key which should match the predefined one if (sign_private_key_.size() != SIGNING_KEY_SIZE) { std::cout << "The loaded private signing key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } sign_public_key_ = file_utils_.ReadKey(kPublicSign); // check the size of the key which should match the predefined one if (sign_public_key_.size() != KEY_SIZE) { std::cout << "The loaded public signing key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } } else { // otherwise generate them // generate the private/public signing key sign_public_key_ = crypto_sign_keypair(&sign_private_key_); if (sign_private_key_.size() != SIGNING_KEY_SIZE) { std::cout << "The loaded private signing key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } if (sign_public_key_.size() != KEY_SIZE) { std::cout << "The loaded public signing key is empty or too short." << std::endl; throw g_crypto_engine_initialization_failure; } if (!file_utils_.WriteKey(sign_private_key_,kPrivateSign)) { std::cout << "Could not store the private signing key." << std::endl; throw g_crypto_engine_initialization_failure; } if (!file_utils_.WriteKey(sign_public_key_, kPublicSign)) { std::cout << "Could not store the publicsigning key." << std::endl; throw g_crypto_engine_initialization_failure; } } } catch (std::exception &e) { std::cout << e.what() << std::endl; throw g_crypto_engine_initialization_failure; } }
int proc_sign(const ts::wstrings_c & pars) { if (pars.size() < 3) return 0; ts::wstr_c arch = pars.get(1); ts::fix_path( arch, FNO_SIMPLIFY ); ts::wstr_c proc = pars.get(2); ts::fix_path( proc, FNO_SIMPLIFY ); if (!is_file_exists(arch.as_sptr())) { Print(FOREGROUND_RED, "arch file not found: %s\n", to_str(arch).cstr()); return 0; } if (!is_file_exists(proc.as_sptr())) { Print(FOREGROUND_RED, "proc file not found: %s\n", to_str(proc).cstr()); return 0; } ts::buf_c b; b.load_from_disk_file(arch); int archlen = b.size(); ts::md5_c md5; md5.update(b.data(), b.size()); md5.done(); ts::abp_c bp; b.load_from_disk_file(proc); bp.load(b.cstr()); ts::wstr_c procpath = ts::fn_get_path(proc); auto pa = [&]( ts::asptr p ) ->ts::wstr_c { return ts::fn_join(procpath, to_wstr(bp.get_string(p))); }; b.load_from_disk_file( pa(CONSTASTR("ver")) ); ts::str_c ver = b.cstr(); ver.replace_all('/','.').trim(); ts::str_c ss(CONSTASTR("ver=")); ss.append( ver ); ss.append(CONSTASTR("\r\nurl=")); ts::str_c path = bp.get_string(CONSTASTR("path")); path.replace_all(CONSTASTR("%ver%"), ver); path.replace_all(CONSTASTR("%https%"), CONSTASTR("https://")); path.replace_all(CONSTASTR("%http%"), CONSTASTR("http://")); path.appendcvt(ts::fn_get_name_with_ext(arch)); ss.append(path); ss.append(CONSTASTR("\r\nsize=")); ss.append_as_uint(archlen); ss.append(CONSTASTR("\r\nmd5=")); ss.append_as_hex(md5.result(), 16); unsigned char pk[crypto_sign_PUBLICKEYBYTES]; unsigned char sk[crypto_sign_SECRETKEYBYTES]; b.clear(); b.load_from_disk_file( pa(CONSTASTR("sk")) ); if (b.size() != crypto_sign_SECRETKEYBYTES) { rebuild: crypto_sign_keypair(pk, sk); FILE *f = _wfopen(pa(CONSTASTR("sk")), L"wb"); fwrite(sk, 1, sizeof(sk), f); fclose(f); ts::str_c spk; for(int i=0;i<crypto_sign_PUBLICKEYBYTES;++i) spk.append(CONSTASTR("0x")).append_as_hex(pk[i]).append(CONSTASTR(", ")); spk.trunc_length(2); f = _wfopen(pa(CONSTASTR("pk")), L"wb"); fwrite(spk.cstr(), 1, spk.get_length(), f); fclose(f); } else { memcpy(sk, b.data(), crypto_sign_SECRETKEYBYTES); crypto_sign_ed25519_sk_to_pk(pk, sk); b.load_from_disk_file( pa(CONSTASTR("pk")) ); ts::token<char> t(b.cstr(), ','); int n = 0; for(;t; ++t, ++n) { if (n >= sizeof(pk)) goto rebuild; ts::str_c nx(*t); nx.trim(); if (pk[n] != (byte)nx.as_uint()) goto rebuild; } if (n < sizeof(pk)) goto rebuild; } unsigned char sig[crypto_sign_BYTES]; unsigned long long siglen; crypto_sign_detached(sig,&siglen, (const byte *)ss.cstr(), ss.get_length(), sk); ss.append(CONSTASTR("\r\nsign=")); ss.append_as_hex(sig, (int)siglen); if (CONSTASTR("github") == bp.get_string(CONSTASTR("wiki"))) { ss.insert(0,CONSTASTR("[begin]\r\n")); ss.replace_all(CONSTASTR("\r\n"), CONSTASTR("`<br>\r\n`")); ss.replace_all(CONSTASTR("[begin]`"), CONSTASTR("[begin]")); ss.append(CONSTASTR("`<br>\r\n[end]<br>\r\n")); } FILE *f = _wfopen(pa(CONSTASTR("result")), L"wb"); fwrite(ss.cstr(), 1, ss.get_length(), f); fclose(f); return 0; }