int main(void) { unsigned char k[crypto_box_BEFORENMBYTES]; int i; int ret; if (crypto_box_open(m, c, 163, nonce, alicepk, bobsk) == 0) { for (i = 32; i < 163; ++i) { printf(",0x%02x", (unsigned int)m[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); } ret = crypto_box_open(m, c, 163, nonce, small_order_p, bobsk); assert(ret == -1); memset(m, 0, sizeof m); ret = crypto_box_beforenm(k, alicepk, bobsk); assert(ret == 0); if (crypto_box_open_afternm(m, c, 163, nonce, k) == 0) { for (i = 32; i < 163; ++i) { printf(",0x%02x", (unsigned int)m[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); } return 0; }
int zmq::curve_server_t::process_hello (msg_t *msg_) { puts("zmq::curve_server_t::process_hello start"); if (msg_->size() != 200) { // Temporary support for security debugging puts ("CURVE I: client HELLO is not correct size"); errno = EPROTO; return -1; } const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ()); if (memcmp (hello, "\x05HELLO", 6)) { // Temporary support for security debugging puts ("CURVE I: client HELLO has invalid command name"); errno = EPROTO; return -1; } const uint8_t major = hello [6]; const uint8_t minor = hello [7]; if (major != 1 || minor != 0) { // Temporary support for security debugging puts ("CURVE I: client HELLO has unknown version number"); errno = EPROTO; return -1; } // Save client's short-term public key (C') memcpy (cn_client, hello + 80, 32); uint8_t hello_nonce [crypto_box_NONCEBYTES]; uint8_t hello_plaintext [crypto_box_ZEROBYTES + 64]; uint8_t hello_box [crypto_box_BOXZEROBYTES + 80]; memcpy (hello_nonce, "CurveZMQHELLO---", 16); memcpy (hello_nonce + 16, hello + 112, 8); cn_peer_nonce = get_uint64(hello + 112); memset (hello_box, 0, crypto_box_BOXZEROBYTES); memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80); // Open Box [64 * %x0](C'->S) int rc = crypto_box_open (hello_plaintext, hello_box, sizeof hello_box, hello_nonce, cn_client, secret_key); if (rc != 0) { // Temporary support for security debugging puts ("CURVE I: cannot open client HELLO -- wrong server key?"); errno = EPROTO; return -1; } state = send_welcome; puts("zmq::curve_server_t::process_hello end"); return rc; }
/* decrypts encrypted of length length to plain of length length - 16 using the public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce return -1 if there was a problem(decryption failed) return length of plain data if everything was fine. */ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, uint8_t * encrypted, uint32_t length, uint8_t * plain) { if(length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) { return -1; } uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; uint8_t zeroes[crypto_box_ZEROBYTES] = {0}; memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ if(crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, public_key, secret_key) == -1) { return -1; } /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ if(memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0) { return -1; } /* unpad the plain message */ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; }
int main() { unsigned char n[crypto_box_NONCEBYTES]; unsigned char m[32+crypto_box_ZEROBYTES]; unsigned char c[32+crypto_box_ZEROBYTES]; unsigned char pk[crypto_box_PUBLICKEYBYTES]; unsigned char sk[crypto_box_SECRETKEYBYTES]; //crypto_box_keypair(pk, sk); //randombytes(sk,32); sk[0]=1; crypto_scalarmult_curve25519_base(pk,sk); int r; unsigned char* buffer1offset = m + crypto_box_ZEROBYTES; strcpy(buffer1offset, "hello world"); printf("in=$s\n", buffer1offset); memset(m, 0, crypto_box_ZEROBYTES); r=crypto_box(c, m, 32+crypto_box_ZEROBYTES, n, pk, sk); printf("ret=%d\n", r); memset(c, 0, crypto_box_BOXZEROBYTES); r=crypto_box_open(m, c, 32+crypto_box_ZEROBYTES, n, pk, sk); printf("ret=%d\n", r); printf("out=$s\n", buffer1offset); }
int main(void) { size_t mlen; size_t i; int caught; for (mlen = 0;mlen < 1000 && mlen + crypto_box_ZEROBYTES < sizeof m;++mlen) { crypto_box_keypair(alicepk,alicesk); crypto_box_keypair(bobpk,bobsk); randombytes(n,crypto_box_NONCEBYTES); randombytes(m + crypto_box_ZEROBYTES,mlen); crypto_box(c,m,mlen + crypto_box_ZEROBYTES,n,bobpk,alicesk); caught = 0; while (caught < 10) { c[rand() % (mlen + crypto_box_ZEROBYTES)] = rand(); if (crypto_box_open(m2,c,mlen + crypto_box_ZEROBYTES,n,alicepk,bobsk) == 0) { for (i = 0;i < mlen + crypto_box_ZEROBYTES;++i) if (m2[i] != m[i]) { printf("forgery\n"); return 100; } } else { ++caught; } } } return 0; }
static void test_hacl_01(void) { int res; /* Creating keypair ALICE... */ crypto_box_keypair(alice_pk, alice_sk); /* Creating keypair BOB... */ crypto_box_keypair(bob_pk, bob_sk); memset(m, 0, crypto_box_ZEROBYTES); memcpy(m + crypto_box_ZEROBYTES, message, MLEN - crypto_box_ZEROBYTES); /* Encrypting using pk_bob... */ crypto_box(c, m, MLEN, n, bob_pk, alice_sk); memset(result, '\0', sizeof(result)); /* Decrypting... */ res = crypto_box_open(result, c, MLEN, n, alice_pk, bob_sk); TEST_ASSERT_EQUAL_INT(0, res); memset(r, 0, sizeof(r)); memcpy(r, result + crypto_box_ZEROBYTES, MLEN - crypto_box_ZEROBYTES); TEST_ASSERT_EQUAL_STRING((const char*)message, (const char*)r); }
/* decrypts encrypted of length length to plain of length length - 16 using the public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce return -1 if there was a problem(decryption failed) return length of plain data if everything was fine. */ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) { if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) return -1; uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ if (crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, public_key, secret_key) == -1) return -1; /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero apparently memcmp should not be used so we do this instead:*/ uint32_t i; uint32_t check = 0; for(i = 0; i < crypto_box_ZEROBYTES; ++i) { check |= temp_plain[i] ^ 0; } if(check != 0) return -1; /* unpad the plain message */ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; }
void main(int argc, char **argv) { char *pubkey_filename, *seckey_filename, *message_plain_filename, *message_enc_filename; unsigned char pk[crypto_box_PUBLICKEYBYTES]; unsigned char sk[crypto_box_SECRETKEYBYTES]; unsigned char *pubkey_data; size_t pubkey_data_size; unsigned char *seckey_data; size_t seckey_data_size; if(argc != 1 + 4) return; seckey_filename = argv[1]; pubkey_filename = argv[2]; message_enc_filename = argv[3]; message_plain_filename = argv[4]; printf("seckey:%s pubkey:%s ciphertext:%s -> decrypted:%s\n", seckey_filename, pubkey_filename, message_enc_filename, message_plain_filename); // read public key from a file if(read_from_file(seckey_filename, &seckey_data, &seckey_data_size)) return; if(read_from_file(pubkey_filename, &pubkey_data, &pubkey_data_size)) return; // check that it is the right size if(pubkey_data_size != crypto_box_PUBLICKEYBYTES) { puts("Public key is wrong size!"); return; } // check that it is the right size if(seckey_data_size != crypto_box_SECRETKEYBYTES) { puts("Public key is wrong size!"); return; } unsigned char n[crypto_box_NONCEBYTES] = { 0 }; unsigned char *ciphertext; size_t ciphertext_size; unsigned char *ciphertext_padded; if(read_from_file(message_enc_filename, &ciphertext, &ciphertext_size)) return; unsigned char *m; m = calloc(ciphertext_size, sizeof(char)); // decrypt if(crypto_box_open(m, ciphertext, ciphertext_size, n, pubkey_data, seckey_data)) puts("NO1"); // write to message.enc if(write_to_file(message_plain_filename, m + crypto_box_BOXZEROBYTES, ciphertext_size)) puts("NO2"); }
// Decrypt with the same key but from the message bytes (from bytes) Message CryptoEngine::DecryptWithPublicKeyAndVerify(const std::vector<unsigned char> message_bytes, const VerificationEngine &ver_engine) { // check the public key if (ver_engine.public_key().empty()) { std::cout << "The recipient public key is empty. Cannot encrypt here." << std::endl; throw g_crypto_engine_encryption_failure; } if (ver_engine.signing_public_key().empty()) { std::cout << "The recipient signing public key is empty. Cannot encrypt here." << std::endl; throw g_crypto_engine_encryption_failure; } if (private_key_.empty()) { std::cout << "The secret key is empty. Cannot encrypt here." << std::endl; throw g_crypto_engine_encryption_failure; } if (nonce_master_key_.empty()) { std::cout << "The master key for deriving the nonce is not valid" << std::endl; throw g_crypto_engine_encryption_failure; } if (context_.empty()) { std::cout << "The context identifier for deriving the nonce is not valid" << std::endl; throw g_crypto_engine_encryption_failure; } if (salt_.empty()) { std::cout << "The salt for deriving the nonce is not valid" << std::endl; throw g_crypto_engine_encryption_failure; } // Convert bytes to encrypted message EncryptedMessage encrypted_msg = EncryptedMessage::FromBytes(message_bytes); // decrypt std::string clear_text_signed_message = crypto_box_open(encrypted_msg.message(), encrypted_msg.nonce(), ver_engine.public_key(), private_key_); // take the signature out std::string signature = clear_text_signed_message.substr(0,128); // verify the signature - if it fails it throws an exception std::string signed_message = crypto_sign_open(signature,ver_engine.signing_public_key()); // remove the signing part and the hash std::string message_with_data = clear_text_signed_message.substr(128,clear_text_signed_message.size()); // Convert to message Message message = Message::FromBytesString(message_with_data); return message; }
int main() { char * padded_message; int padded_mlen; u8 sk[PRIV_KEY_LEN] = {0}; u8 pk[PUB_KEY_LEN] = {0}; u8 sk2[PRIV_KEY_LEN] = {0}; u8 pk2[PUB_KEY_LEN] = {0}; u8 nonce[NONCE_LEN] = {0}; char* message = "This is a cross-platform test of crypto_box/crypto_box_open in TweetNaCl."; u8 * ciphertext; char *decryptedmessage; // randomize nonce randombytes(nonce, NONCE_LEN); printf("Nonce: \n"); hexdump((char*)nonce, NONCE_LEN); crypto_box_keypair(pk, sk); crypto_box_keypair(pk2, sk2); printf("Public key: \n"); hexdump((char*)pk, PUB_KEY_LEN); printf("\nSecret key: \n"); hexdump((char*)sk, PRIV_KEY_LEN); printf("Public key2: \n"); hexdump((char*)pk2, PUB_KEY_LEN); printf("\nSecret key2: \n"); hexdump((char*)sk2, PRIV_KEY_LEN); padded_mlen = strlen(message) + PADDING_LEN; padded_message = (char*) malloc(padded_mlen); memset(padded_message, 0, PADDING_LEN); memcpy(padded_message + PADDING_LEN, message, strlen(message)); ciphertext = (u8*) malloc(padded_mlen); // we have a string so add 1 byte and NUL it so we can print it decryptedmessage = (char*) malloc(padded_mlen+1); decryptedmessage[padded_mlen] = '\0'; printf("crypto_box returned: %d\n",crypto_box(ciphertext, (u8*)padded_message, padded_mlen, nonce, pk2, sk)); free(padded_message); printf("\nCipher text: \n"); hexdump((char*)ciphertext, padded_mlen); printf("crypto_box_open returned: %d\n", crypto_box_open((u8*)decryptedmessage, ciphertext, padded_mlen, nonce, pk, sk2)); free(ciphertext); printf("\nDecrypted text: \n"); hexdump((char*)decryptedmessage, padded_mlen); printf("%s\n", decryptedmessage+32); free(decryptedmessage); return 0; }
int main(int argc, char** argv) { if (argc != 2) {fprintf(stderr, "%s our_sk", argv[0]); return 1;} unsigned char sk[crypto_box_SECRETKEYBYTES]; { FILE* f = fopen(argv[1], "r"); if (f == NULL) {fprintf(stderr, "Cannot open our secret key file"); return 1;} int len = fread(sk, 1, crypto_box_SECRETKEYBYTES, f); fclose(f); if (len != crypto_box_SECRETKEYBYTES) {fprintf(stderr, "Bad secret key file"); return 1;} } uint8_t buf[1<<16]; int len = fread(buf, 1, 1<<16, stdin); pb_istream_t stream = pb_istream_from_buffer(buf, len); Box box; if (!pb_decode(&stream, Box_fields, &box)) return 1; if (box.enc_algo != 1) return 1; uint8_t n[crypto_box_NONCEBYTES]; for (int i=0; i<crypto_box_NONCEBYTES; ++i) n[i] = box.data.bytes[i]; for (int i=0; i<crypto_box_BOXZEROBYTES; ++i) box.data.bytes[i] = 0; stream = pb_istream_from_buffer(box.sender.bytes, box.sender.size); PublicKey pk; if (!pb_decode(&stream, PublicKey_fields, &pk)) return 1; PublicKeyData pkd; stream = pb_istream_from_buffer(pk.publickey_msg.bytes, pk.publickey_msg.size); if (!pb_decode(&stream, PublicKeyData_fields, &pkd)) return 1; int decrypted = 0; for (int i=0; i<min(pkd.enc_keys_count,pkd.enc_algos_count); i++) { if (pkd.enc_keys[i].size == crypto_box_PUBLICKEYBYTES && pkd.sig_algos[i] == 1) { uint8_t* encpk = &pkd.enc_keys[i].bytes[0]; if (crypto_box_open(buf,box.data.bytes+8,box.data.size-8,n,encpk,sk) == 0) { decrypted = 1; break; } } } for (int i=0; i<crypto_box_SECRETKEYBYTES; i++) sk[i] = 0; if (decrypted) { int got = fwrite(buf+crypto_box_ZEROBYTES, 1, box.data.size-8-crypto_box_ZEROBYTES, stdout); assert(got == box.data.size-8-crypto_box_ZEROBYTES); got = fwrite(box.sender.bytes, 1, box.sender.size, stderr); assert(got == box.sender.size); } return !decrypted; }
// decrypted_bytes = crypto_box_open(enc_bytes, nonce, pk_other, sk_self); static int tweetnacl_crypto_box_open( lua_State* L ) { unsigned int emsg_len; const char* emsg = luaL_checklstring(L,1,&emsg_len); if(emsg_len < crypto_box_BOXZEROBYTES) return luaL_error( L, "len(emessage)=%d, too short", emsg_len); unsigned int nonce_len; const char* nonce = luaL_checklstring(L,2,&nonce_len); if(nonce_len != crypto_box_NONCEBYTES) return luaL_error( L, "len(nonce)=%d, should be %d", nonce_len, crypto_box_NONCEBYTES); unsigned int pk_len; const char* pk_other = luaL_checklstring(L,3,&pk_len); if(pk_len != crypto_box_PUBLICKEYBYTES) return luaL_error( L, "len(pk)=%d, should be %d", pk_len, crypto_box_PUBLICKEYBYTES); unsigned int sk_len; const char* sk_self = luaL_checklstring(L,4,&sk_len); if(sk_len != crypto_box_SECRETKEYBYTES) return luaL_error( L, "len(sk)=%d, should be %d", sk_len, crypto_box_SECRETKEYBYTES); unsigned int pmsg_len = emsg_len + crypto_box_BOXZEROBYTES; char *pmsg = (char *)c_malloc(pmsg_len); if(!pmsg) return luaL_error( L, "malloc failed, %d bytes", pmsg_len); int i; for(i=0;i<crypto_box_BOXZEROBYTES;i++) pmsg[i] = 0; for(;i<pmsg_len;i++) pmsg[i] = emsg[i-crypto_box_BOXZEROBYTES]; unsigned int cmsg_len = pmsg_len; char *cmsg = (char *)c_malloc(cmsg_len); if(!cmsg) { c_free(pmsg); return luaL_error( L, "malloc failed, %d bytes", cmsg_len); } int r; r = crypto_box_open(cmsg, pmsg, pmsg_len, nonce, pk_other, sk_self); if(r!=0) { c_free(cmsg); c_free(pmsg); return luaL_error( L, "decryption failed"); } lua_pushlstring(L, cmsg+crypto_box_ZEROBYTES, cmsg_len-crypto_box_ZEROBYTES); c_free(cmsg); c_free(pmsg); return 1; }
String NaCl::public_decrypt(String enc_msg) { try { std::string encrypted_message = from_ruby<std::string>(enc_msg); std::string message = crypto_box_open(encrypted_message, my_nonce, remote_pk, my_sk); return to_ruby<std::string>(message); } catch (int e) { return to_ruby<std::string>(""); } }
/** * Deciphered data without making it a packet. * @src: source of the data * @len: length of the entire src array * @pk: public key to decrypt the data from * @sk: secret key to decrypt the data with * @dest: destination for plaintext, must be as big as len - PREFIX */ int crypto_decipher_data (const void *src, int len, const unsigned char *pek, const unsigned char *sek, void *dest) { int report = 0; unsigned char buf[len - crypto_box_NONCEBYTES]; memset(buf, 0, len - crypto_box_NONCEBYTES); report = crypto_box_open(buf, (const unsigned char *)src + crypto_box_NONCEBYTES, len - crypto_box_NONCEBYTES, src, pek, sek); memcpy(dest, buf + crypto_box_ZEROBYTES, len - PREFIX); return report; }
int main(int argc, char **argv) { int rc; uint8_t client_pub[32], client_sec[32]; uint8_t server_pub[32], server_sec[32]; uint8_t cipher[512], plain[512]; uint8_t nonce[24]; /* initialize memory */ memset(cipher, 0, 512); memset(plain, 0, 512); /* "generate" nonce */ memset(nonce, 0, 24); /* "generate" keys */ memcpy(client_pub, CLIENT_PUB, 32); memcpy(client_sec, CLIENT_SEC, 32); memcpy(server_pub, SERVER_PUB, 32); memcpy(server_sec, SERVER_SEC, 32); /* assemble plaintext */ memset(plain, 0, 32); /* first 32 octest are ZERO */ memcpy(plain+32, MESSAGE, MESSAGE_LEN); /* then comes the real data */ dump("plaintext, before encryption", plain, MESSAGE_LEN+32); /* encipher message from client to server */ rc = crypto_box(cipher, plain, MESSAGE_LEN+32, nonce, server_pub, client_sec); dump("ciphertext", cipher, MESSAGE_LEN); assert(rc == 0); /* erase all trace of plaintext */ memset(plain, 0, 512); /* decipher message as server, using client's public key */ rc = crypto_box_open(plain, cipher, MESSAGE_LEN+32, nonce, client_pub, server_sec); dump("plaintext, after decryption", plain, MESSAGE_LEN+32); assert(rc == 0); assert(memcmp(MESSAGE, plain, MESSAGE_LEN) == 0); plain[MESSAGE_LEN+1] = '\0'; printf("%s\n", plain); return 0; }
error tunnel_openPacket(struct tunnel *t, uint8_t *packet, uint8_t *message, size_t packetSize, size_t *messageSize) { if (packetSize < sizeof t->tid) { return "Invalid packet"; } uint64_t tidWithFlags = readUint64LE(packet), tid = tidWithFlags & ~TID_FLAGS; bool hasPublickey = tidWithFlags & PUBLICKEY_FLAG, hasPuzzle = tidWithFlags & PUZZLE_FLAG, expectingPublickey = t->state == TUNNEL_STATE_SERVER_PRE_HANDSHAKE; size_t headerSize = sizeof tid + sizeof t->nonce + (hasPublickey ? sizeof t->remotePublickey : 0), contentSize = packetSize - headerSize; if (headerSize > packetSize) { return "Invalid packet (1)"; } if (hasPuzzle) { return "Puzzles not supported"; } if (hasPublickey && !expectingPublickey) { return "Unexpected public key"; } else if (!hasPublickey && expectingPublickey) { return "Expected public key"; } else if (hasPublickey && expectingPublickey) { t->state = TUNNEL_STATE_NORMAL; memcpy(t->remotePublickey, &packet[sizeof tid + sizeof t->nonce], sizeof t->remotePublickey); } uint8_t crypted[crypto_box_BOXZEROBYTES + contentSize]; memset(crypted, 0, crypto_box_BOXZEROBYTES); memcpy(&crypted[crypto_box_BOXZEROBYTES], &packet[headerSize], contentSize); if (crypto_box_open(crypted, crypted, sizeof crypted, &packet[sizeof tid], t->remotePublickey, t->localSecretkey) == -1) { return "Invalid packet (2)"; } *messageSize = sizeof crypted - crypto_box_ZEROBYTES; memcpy(message, &crypted[crypto_box_ZEROBYTES], *messageSize); return NULL; }
PyObject *pycrypto_box_open(PyObject *self, PyObject *args, PyObject *kw){ char *c, *n, *pk, *sk; Py_ssize_t csize=0, nsize=0, pksize=0, sksize=0; static const char *kwlist[] = {"c", "n", "pk", "sk", 0}; unsigned int i; PyObject *ret; size_t clen; unsigned char *mpad; unsigned char *cpad; if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#s#:crypto_box_open", (char **) kwlist, &c, &csize, &n, &nsize, &pk, &pksize, &sk, &sksize)){ return (PyObject *)0;} if (nsize != crypto_box_NONCEBYTES) return Py_BuildValue("i", 0); if (pksize != crypto_box_PUBLICKEYBYTES) return Py_BuildValue("i", 0); if (sksize != crypto_box_SECRETKEYBYTES) return Py_BuildValue("i", 0); clen = csize + crypto_box_BOXZEROBYTES; mpad = PyMem_Malloc(clen); if (!mpad) return PyErr_NoMemory(); cpad = PyMem_Malloc(clen); if (!cpad){ PyMem_Free(mpad); return PyErr_NoMemory();} for (i = 0;i < crypto_box_BOXZEROBYTES;++i) cpad[i] = 0; for (i = crypto_box_BOXZEROBYTES;i < clen;++i) cpad[i] = c[i - crypto_box_BOXZEROBYTES]; if (crypto_box_open(mpad, cpad, clen, (const unsigned char *) n, (const unsigned char *) pk, (const unsigned char *) sk) != 0){ PyMem_Free(mpad); PyMem_Free(cpad); return Py_BuildValue("i", 0);} if (clen < crypto_box_ZEROBYTES){ PyMem_Free(mpad); PyMem_Free(cpad); return Py_BuildValue("i", 0);} ret = PyBytes_FromStringAndSize((char *)mpad + crypto_box_ZEROBYTES, clen - crypto_box_ZEROBYTES); PyMem_Free(mpad); PyMem_Free(cpad); return ret;}
int zmq::curve_server_t::process_hello (msg_t *msg_) { if (msg_->size () != 200) { errno = EPROTO; return -1; } const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ()); if (memcmp (hello, "HELLO\0", 6)) { errno = EPROTO; return -1; } const uint8_t major = hello [6]; const uint8_t minor = hello [7]; if (major != 1 || minor != 0) { errno = EPROTO; return -1; } // Save client's short-term public key (C') memcpy (cn_client, hello + 80, 32); uint8_t hello_nonce [crypto_box_NONCEBYTES]; uint8_t hello_plaintext [crypto_box_ZEROBYTES + 64]; uint8_t hello_box [crypto_box_BOXZEROBYTES + 80]; memcpy (hello_nonce, "CurveZMQHELLO---", 16); memcpy (hello_nonce + 16, hello + 112, 8); memset (hello_box, 0, crypto_box_BOXZEROBYTES); memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80); // Open Box [64 * %x0](C'->S) int rc = crypto_box_open (hello_plaintext, hello_box, sizeof hello_box, hello_nonce, cn_client, secret_key); if (rc != 0) { errno = EPROTO; return -1; } return rc; }
int decrypt(UCHAR plain[], const UCHAR pk[], const UCHAR sk[], const UCHAR nonce[], const UCHAR encrypted[], int length) { UCHAR temp_encrypted[BLEN + crypto_box_BOXZEROBYTES]; UCHAR temp_plain[BLEN + crypto_box_BOXZEROBYTES]; int rc; if (length + crypto_box_BOXZEROBYTES >= BLEN) { puts("fail greater max"); return -2; } /* * http://mob5.host.cs.st-andrews.ac.uk/html/d7/d46/a00002.html#gad0201c5b5acc5e1ad6bf23fb6cb82a1d * * Precondition: * first crypto_box_BOXZEROBYTES of ctxt be all 0. * the nonce must have size crypto_box_NONCEBYTES. */ memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES); memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); rc = crypto_box_open(temp_plain, temp_encrypted, crypto_box_BOXZEROBYTES + length, nonce, pk, sk); if( rc != 0 ) { puts("crypto_box_open fails"); return -1; } /* * Postcondition: * first clen bytes of msg will contain the plaintext. * first crypto_box_ZEROBYTES of msg will be all 0. */ if( is_zero(temp_plain, crypto_box_ZEROBYTES) != 0 ) { puts("is_zero fails"); return -3; } memcpy(plain, temp_plain + crypto_box_ZEROBYTES, crypto_box_BOXZEROBYTES + length); return crypto_box_BOXZEROBYTES + length - crypto_box_ZEROBYTES; }
static int process_welcome (const uint8_t *msg_data_, size_t msg_size_, const uint8_t *server_key_, const uint8_t *cn_secret_, uint8_t *cn_server_, uint8_t *cn_cookie_, uint8_t *cn_precom_) { if (msg_size_ != 168) { errno = EPROTO; return -1; } uint8_t welcome_nonce[crypto_box_NONCEBYTES]; uint8_t welcome_plaintext[crypto_box_ZEROBYTES + 128]; uint8_t welcome_box[crypto_box_BOXZEROBYTES + 144]; // Open Box [S' + cookie](C'->S) memset (welcome_box, 0, crypto_box_BOXZEROBYTES); memcpy (welcome_box + crypto_box_BOXZEROBYTES, msg_data_ + 24, 144); memcpy (welcome_nonce, "WELCOME-", 8); memcpy (welcome_nonce + 8, msg_data_ + 8, 16); int rc = crypto_box_open (welcome_plaintext, welcome_box, sizeof welcome_box, welcome_nonce, server_key_, cn_secret_); if (rc != 0) { errno = EPROTO; return -1; } memcpy (cn_server_, welcome_plaintext + crypto_box_ZEROBYTES, 32); memcpy (cn_cookie_, welcome_plaintext + crypto_box_ZEROBYTES + 32, 16 + 80); // Message independent precomputation rc = crypto_box_beforenm (cn_precom_, cn_server_, cn_secret_); zmq_assert (rc == 0); return 0; }
// Decrypt from the message bytes Message CryptoEngine::DecryptWithPublicKey(const std::vector<unsigned char> message_bytes, const VerificationEngine &ver_engine) { // check the public key if (ver_engine.public_key().empty()) { std::cout << "The recipient public key is empty. Cannot encrypt here." << std::endl; throw g_crypto_engine_encryption_failure; } // from bytes to encrypted message EncryptedMessage encrypted_msg = EncryptedMessage::FromBytes(message_bytes); // get the clear text, with the additional data prepended std::string clear_text_with_data(crypto_box_open(encrypted_msg.message(), encrypted_msg.nonce(), ver_engine.public_key(), private_key_)); // extract the additional data and build the message Message message = Message::FromBytesString(clear_text_with_data); return message; }
int zmq::curve_client_t::process_welcome (msg_t *msg_) { if (msg_->size () != 168) { errno = EPROTO; return -1; } const uint8_t * welcome = static_cast <uint8_t *> (msg_->data ()); if (memcmp (welcome, "\x07WELCOME", 8)) { errno = EPROTO; return -1; } uint8_t welcome_nonce [crypto_box_NONCEBYTES]; uint8_t welcome_plaintext [crypto_box_ZEROBYTES + 128]; uint8_t welcome_box [crypto_box_BOXZEROBYTES + 144]; // Open Box [S' + cookie](C'->S) memset (welcome_box, 0, crypto_box_BOXZEROBYTES); memcpy (welcome_box + crypto_box_BOXZEROBYTES, welcome + 24, 144); memcpy (welcome_nonce, "WELCOME-", 8); memcpy (welcome_nonce + 8, welcome + 8, 16); int rc = crypto_box_open (welcome_plaintext, welcome_box, sizeof welcome_box, welcome_nonce, server_key, cn_secret); if (rc != 0) { errno = EPROTO; return -1; } memcpy (cn_server, welcome_plaintext + crypto_box_ZEROBYTES, 32); memcpy (cn_cookie, welcome_plaintext + crypto_box_ZEROBYTES + 32, 16 + 80); // Message independent precomputation rc = crypto_box_beforenm (cn_precom, cn_server, cn_secret); zmq_assert (rc == 0); return 0; }
int zmq::curve_client_t::process_welcome ( const uint8_t *msg_data, size_t msg_size) { if (msg_size != 168) { errno = EPROTO; return -1; } uint8_t welcome_nonce [crypto_box_NONCEBYTES]; uint8_t welcome_plaintext [crypto_box_ZEROBYTES + 128]; uint8_t welcome_box [crypto_box_BOXZEROBYTES + 144]; // Open Box [S' + cookie](C'->S) memset (welcome_box, 0, crypto_box_BOXZEROBYTES); memcpy (welcome_box + crypto_box_BOXZEROBYTES, msg_data + 24, 144); memcpy (welcome_nonce, "WELCOME-", 8); memcpy (welcome_nonce + 8, msg_data + 8, 16); int rc = crypto_box_open (welcome_plaintext, welcome_box, sizeof welcome_box, welcome_nonce, server_key, cn_secret); if (rc != 0) { errno = EPROTO; return -1; } memcpy (cn_server, welcome_plaintext + crypto_box_ZEROBYTES, 32); memcpy (cn_cookie, welcome_plaintext + crypto_box_ZEROBYTES + 32, 16 + 80); // Message independent precomputation rc = crypto_box_beforenm (cn_precom, cn_server, cn_secret); zmq_assert (rc == 0); state = send_initiate; return 0; }
static ERL_NIF_TERM nacl_box_open_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary padded_ciphertext; ErlNifBinary nonce; ErlNifBinary pk; ErlNifBinary sk; ErlNifBinary result; if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[2], &pk)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[3], &sk)) return enif_make_badarg(env); if (nonce.size != crypto_box_NONCEBYTES) return enif_make_badarg(env); if (pk.size != crypto_box_PUBLICKEYBYTES) return enif_make_badarg(env); if (sk.size != crypto_box_SECRETKEYBYTES) return enif_make_badarg(env); if (padded_ciphertext.size < crypto_box_BOXZEROBYTES) return enif_make_badarg(env); if (!enif_alloc_binary(padded_ciphertext.size, &result)) return nacl_error_tuple(env, "alloc_failed"); if (crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { return nacl_error_tuple(env, "crypto_failed"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), crypto_box_ZEROBYTES, padded_ciphertext.size - crypto_box_ZEROBYTES); }
int validate_crypto_cookie_packet(unsigned char *buffer, UNUSED(uint64_t length)) { unsigned char *block; unsigned char *ciphertextpadded; unsigned char nonce[crypto_box_NONCEBYTES]; uint64_t ciphertextlen; uint64_t blocklen; memcpy(nonce, "splonePK", 8); memcpy(nonce + 8, buffer + 8, 16); ciphertextlen = 160; blocklen = 144; block = MALLOC_ARRAY(ciphertextlen, unsigned char); ciphertextpadded = CALLOC(ciphertextlen, unsigned char); if (block == NULL || ciphertextpadded == NULL) return (-1); memcpy(ciphertextpadded + 16, buffer + 24, blocklen); if (crypto_box_open(block, ciphertextpadded, ciphertextlen, nonce, serverlongtermpk, clientshorttermsk)) { FREE(block); FREE(ciphertextpadded); return (-1); } memcpy(servershorttermpk, block + 32, 32); memcpy(cookie, block + 64, 96); FREE(block); FREE(ciphertextpadded); return (0); }
int main(void) { size_t mlen; size_t i; for (mlen = 0;mlen < 1000 && mlen + crypto_box_ZEROBYTES < sizeof m;++mlen) { crypto_box_keypair(alicepk,alicesk); crypto_box_keypair(bobpk,bobsk); randombytes(n,crypto_box_NONCEBYTES); randombytes(m + crypto_box_ZEROBYTES,mlen); crypto_box(c,m,mlen + crypto_box_ZEROBYTES,n,bobpk,alicesk); if (crypto_box_open(m2,c,mlen + crypto_box_ZEROBYTES,n,alicepk,bobsk) == 0) { for (i = 0;i < mlen + crypto_box_ZEROBYTES;++i) if (m2[i] != m[i]) { printf("bad decryption\n"); break; } } else { printf("ciphertext fails verification\n"); } } return 0; }
int zmq::curve_server_t::process_initiate (msg_t *msg_) { if (msg_->size () < 257) { // Temporary support for security debugging puts ("CURVE I: client INITIATE is not correct size"); errno = EPROTO; return -1; } const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); if (memcmp (initiate, "\x08INITIATE", 9)) { // Temporary support for security debugging puts ("CURVE I: client INITIATE has invalid command name"); errno = EPROTO; return -1; } uint8_t cookie_nonce [crypto_secretbox_NONCEBYTES]; uint8_t cookie_plaintext [crypto_secretbox_ZEROBYTES + 64]; uint8_t cookie_box [crypto_secretbox_BOXZEROBYTES + 80]; // Open Box [C' + s'](t) memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES); memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80); memcpy (cookie_nonce, "COOKIE--", 8); memcpy (cookie_nonce + 8, initiate + 9, 16); int rc = crypto_secretbox_open (cookie_plaintext, cookie_box, sizeof cookie_box, cookie_nonce, cookie_key); if (rc != 0) { // Temporary support for security debugging puts ("CURVE I: cannot open client INITIATE cookie"); errno = EPROTO; return -1; } // Check cookie plain text is as expected [C' + s'] if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32) || memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) { // Temporary support for security debugging puts ("CURVE I: client INITIATE cookie is not valid"); errno = EPROTO; return -1; } const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES; uint8_t initiate_nonce [crypto_box_NONCEBYTES]; uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256]; uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256]; // Open Box [C + vouch + metadata](C'->S') memset (initiate_box, 0, crypto_box_BOXZEROBYTES); memcpy (initiate_box + crypto_box_BOXZEROBYTES, initiate + 113, clen - crypto_box_BOXZEROBYTES); memcpy (initiate_nonce, "CurveZMQINITIATE", 16); memcpy (initiate_nonce + 16, initiate + 105, 8); cn_peer_nonce = get_uint64(initiate + 105); rc = crypto_box_open (initiate_plaintext, initiate_box, clen, initiate_nonce, cn_client, cn_secret); if (rc != 0) { // Temporary support for security debugging puts ("CURVE I: cannot open client INITIATE"); errno = EPROTO; return -1; } const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES; uint8_t vouch_nonce [crypto_box_NONCEBYTES]; uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64]; uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80]; // Open Box Box [C',S](C->S') and check contents memset (vouch_box, 0, crypto_box_BOXZEROBYTES); memcpy (vouch_box + crypto_box_BOXZEROBYTES, initiate_plaintext + crypto_box_ZEROBYTES + 48, 80); memcpy (vouch_nonce, "VOUCH---", 8); memcpy (vouch_nonce + 8, initiate_plaintext + crypto_box_ZEROBYTES + 32, 16); rc = crypto_box_open (vouch_plaintext, vouch_box, sizeof vouch_box, vouch_nonce, client_key, cn_secret); if (rc != 0) { // Temporary support for security debugging puts ("CURVE I: cannot open client INITIATE vouch"); errno = EPROTO; return -1; } // What we decrypted must be the client's short-term public key if (memcmp (vouch_plaintext + crypto_box_ZEROBYTES, cn_client, 32)) { // Temporary support for security debugging puts ("CURVE I: invalid handshake from client (public key)"); errno = EPROTO; return -1; } // Precompute connection secret from client key rc = crypto_box_beforenm (cn_precom, cn_client, cn_secret); zmq_assert (rc == 0); // Use ZAP protocol (RFC 27) to authenticate the user. rc = session->zap_connect (); if (rc == 0) { send_zap_request (client_key); rc = receive_and_process_zap_reply (); if (rc == 0) state = status_code == "200" ? send_ready : send_error; else if (errno == EAGAIN) state = expect_zap_reply; else return -1; } else state = send_ready; return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128, clen - crypto_box_ZEROBYTES - 128); }
static nif_term_t salt_box_open(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_box_open(Cipher_text, Nonce, Public_key, Secret_key) -> {ok, Plain_text} | forged_or_garbled. */ nif_bin_t pt; nif_bin_t nc; nif_bin_t pk; nif_bin_t sk; nif_bin_t ct; nif_term_t raw; nif_term_t sub; nif_term_t tag; if (argc != 4) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &ct)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &nc)) return (BADARG); if (! enif_inspect_binary(hp, argv[2], &pk)) return (BADARG); if (! enif_inspect_binary(hp, argv[3], &sk)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (ct.size < crypto_box_BOXZEROBYTES || ct.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)ct.data, &salt_box_boxzerobytes[0], crypto_box_BOXZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_box_NONCEBYTES) return (BADARG); if (pk.size != crypto_box_PUBLICKEYBYTES) return (BADARG); if (sk.size != crypto_box_SECRETKEYBYTES) return (BADARG); /* Allocate space for plain text. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(ct.size, &pt)) return (BADARG); /* Perform the crypto, strip leading zeros and return rest if authentic. */ if (crypto_box_open(pt.data, ct.data, ct.size, nc.data, pk.data, sk.data) != 0) { enif_release_binary(&pt); return (enif_make_atom(hp, "forged_or_garbled")); } raw = enif_make_binary(hp, &pt); sub = enif_make_sub_binary(hp, raw, crypto_box_ZEROBYTES, pt.size - crypto_box_ZEROBYTES); tag = enif_make_atom(hp, "ok"); return (enif_make_tuple2(hp, tag, sub)); }
bool unit_test_crypto_box(){ // Global length uint64_t len = HACL_UNIT_TESTS_SIZE * sizeof(uint8_t); // Scratch buffers uint8_t hacl_cipher[HACL_UNIT_TESTS_SIZE + 32], expected_cipher[HACL_UNIT_TESTS_SIZE + 32]; // Generation of the public/secret key couple uint8_t sk1[32], pk1[32]; uint8_t sk2[32], pk2[32]; tweet_crypto_box_keypair(pk1, sk1); tweet_crypto_box_keypair(pk2, sk2); // Random plaintext uint8_t *plaintext = malloc((HACL_UNIT_TESTS_SIZE + crypto_box_ZEROBYTES) * sizeof (uint8_t)); READ_RANDOM_BYTES(len, plaintext + crypto_box_ZEROBYTES); for (int i = 0; i < crypto_box_ZEROBYTES; i++) plaintext[i] = 0; // Random plaintext uint8_t nonce[24]; READ_RANDOM_BYTES(24, nonce); // Test 1 int a; bool pass = true; for (int i = 0; i < 3 * CHACHA_BLOCKSIZE; i++){ tweet_crypto_box(expected_cipher, plaintext, crypto_box_ZEROBYTES + i, nonce, pk1, sk2); crypto_box(hacl_cipher, plaintext, crypto_box_ZEROBYTES + i, nonce, pk1, sk2); a = memcmp(hacl_cipher, expected_cipher, (crypto_box_ZEROBYTES + i) * sizeof (uint8_t)); if (a != 0){ pass = false; printf("BOX failed on input of size %d\n.", i); break; } a = crypto_box_open(hacl_cipher, expected_cipher, i + crypto_box_ZEROBYTES, nonce, pk2, sk1); if (a != 0) { pass = false; printf("BOX OPEN failed to verify on input of size %d\n", i); break; } a = memcmp(hacl_cipher, plaintext, (crypto_box_ZEROBYTES + i) * sizeof (uint8_t)); if (a != 0) { pass = false; printf("BOX OPEN failed on input of size %d\n", i); break; } } if (!pass) return pass; // Test 2 tweet_crypto_box(expected_cipher, plaintext, crypto_box_ZEROBYTES + HACL_UNIT_TESTS_SIZE, nonce, pk1, sk2); crypto_box(hacl_cipher, plaintext, crypto_box_ZEROBYTES + HACL_UNIT_TESTS_SIZE, nonce, pk1, sk2); a = memcmp(hacl_cipher, expected_cipher, (crypto_box_ZEROBYTES + HACL_UNIT_TESTS_SIZE) * sizeof (uint8_t)); if (a != 0){ pass = false; printf("BOX failed on input of size %d\n.", HACL_UNIT_TESTS_SIZE); } a = crypto_box_open(hacl_cipher, expected_cipher, HACL_UNIT_TESTS_SIZE + crypto_box_ZEROBYTES, nonce, pk2, sk1); if (a != 0) { pass = false; printf("BOX OPEN failed to verify on input of size %d\n", HACL_UNIT_TESTS_SIZE); } a = memcmp(hacl_cipher, plaintext, (crypto_box_ZEROBYTES + HACL_UNIT_TESTS_SIZE) * sizeof (uint8_t)); if (a != 0) { pass = false; printf("BOX OPEN failed on input of size %d\n", HACL_UNIT_TESTS_SIZE); } free(plaintext); return pass; }
int zmq::curve_server_t::process_initiate (msg_t *msg_) { int rc = check_basic_command_structure (msg_); if (rc == -1) return -1; const size_t size = msg_->size (); const uint8_t *initiate = static_cast<uint8_t *> (msg_->data ()); if (size < 9 || memcmp (initiate, "\x08INITIATE", 9)) { session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND); errno = EPROTO; return -1; } if (size < 257) { session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE); errno = EPROTO; return -1; } uint8_t cookie_nonce[crypto_secretbox_NONCEBYTES]; uint8_t cookie_plaintext[crypto_secretbox_ZEROBYTES + 64]; uint8_t cookie_box[crypto_secretbox_BOXZEROBYTES + 80]; // Open Box [C' + s'](t) memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES); memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80); memcpy (cookie_nonce, "COOKIE--", 8); memcpy (cookie_nonce + 8, initiate + 9, 16); rc = crypto_secretbox_open (cookie_plaintext, cookie_box, sizeof cookie_box, cookie_nonce, _cookie_key); if (rc != 0) { // CURVE I: cannot open client INITIATE cookie session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); errno = EPROTO; return -1; } // Check cookie plain text is as expected [C' + s'] if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, _cn_client, 32) || memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, _cn_secret, 32)) { // TODO this case is very hard to test, as it would require a modified // client that knows the server's secret temporary cookie key // CURVE I: client INITIATE cookie is not valid session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); errno = EPROTO; return -1; } const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES; uint8_t initiate_nonce[crypto_box_NONCEBYTES]; uint8_t initiate_plaintext[crypto_box_ZEROBYTES + 128 + 256]; uint8_t initiate_box[crypto_box_BOXZEROBYTES + 144 + 256]; // Open Box [C + vouch + metadata](C'->S') memset (initiate_box, 0, crypto_box_BOXZEROBYTES); memcpy (initiate_box + crypto_box_BOXZEROBYTES, initiate + 113, clen - crypto_box_BOXZEROBYTES); memcpy (initiate_nonce, "CurveZMQINITIATE", 16); memcpy (initiate_nonce + 16, initiate + 105, 8); cn_peer_nonce = get_uint64 (initiate + 105); rc = crypto_box_open (initiate_plaintext, initiate_box, clen, initiate_nonce, _cn_client, _cn_secret); if (rc != 0) { // CURVE I: cannot open client INITIATE session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); errno = EPROTO; return -1; } const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES; uint8_t vouch_nonce[crypto_box_NONCEBYTES]; uint8_t vouch_plaintext[crypto_box_ZEROBYTES + 64]; uint8_t vouch_box[crypto_box_BOXZEROBYTES + 80]; // Open Box Box [C',S](C->S') and check contents memset (vouch_box, 0, crypto_box_BOXZEROBYTES); memcpy (vouch_box + crypto_box_BOXZEROBYTES, initiate_plaintext + crypto_box_ZEROBYTES + 48, 80); memcpy (vouch_nonce, "VOUCH---", 8); memcpy (vouch_nonce + 8, initiate_plaintext + crypto_box_ZEROBYTES + 32, 16); rc = crypto_box_open (vouch_plaintext, vouch_box, sizeof vouch_box, vouch_nonce, client_key, _cn_secret); if (rc != 0) { // CURVE I: cannot open client INITIATE vouch session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); errno = EPROTO; return -1; } // What we decrypted must be the client's short-term public key if (memcmp (vouch_plaintext + crypto_box_ZEROBYTES, _cn_client, 32)) { // TODO this case is very hard to test, as it would require a modified // client that knows the server's secret short-term key // CURVE I: invalid handshake from client (public key) session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE); errno = EPROTO; return -1; } // Precompute connection secret from client key rc = crypto_box_beforenm (cn_precom, _cn_client, _cn_secret); zmq_assert (rc == 0); // Given this is a backward-incompatible change, it's behind a socket // option disabled by default. if (zap_required () || !options.zap_enforce_domain) { // Use ZAP protocol (RFC 27) to authenticate the user. rc = session->zap_connect (); if (rc == 0) { send_zap_request (client_key); state = waiting_for_zap_reply; // TODO actually, it is quite unlikely that we can read the ZAP // reply already, but removing this has some strange side-effect // (probably because the pipe's in_active flag is true until a read // is attempted) rc = receive_and_process_zap_reply (); if (rc == -1) return -1; } else if (!options.zap_enforce_domain) { // This supports the Stonehouse pattern (encryption without // authentication) in legacy mode (domain set but no handler). state = sending_ready; } else { session->get_socket ()->event_handshake_failed_no_detail ( session->get_endpoint (), EFAULT); return -1; } } else { // This supports the Stonehouse pattern (encryption without authentication). state = sending_ready; } return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128, clen - crypto_box_ZEROBYTES - 128); }