void measure(void) { int i; int loop; int mlen; for (loop = 0;loop < LOOPS;++loop) { for (mlen = 0;mlen <= MAXTEST_BYTES;mlen += 1 + mlen / 8) { randombytes(k,crypto_secretbox_KEYBYTES); randombytes(n,crypto_secretbox_NONCEBYTES); randombytes(m + crypto_secretbox_ZEROBYTES,mlen); randombytes(c,mlen + crypto_secretbox_ZEROBYTES); for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); crypto_secretbox(c,m,mlen + crypto_secretbox_ZEROBYTES,n,k); } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(mlen,"cycles",cycles,TIMINGS); for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); crypto_secretbox_open(m,c,mlen + crypto_secretbox_ZEROBYTES,n,k); } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(mlen,"open_cycles",cycles,TIMINGS); ++c[crypto_secretbox_ZEROBYTES]; for (i = 0;i <= TIMINGS;++i) { cycles[i] = cpucycles(); crypto_secretbox_open(m,c,mlen + crypto_secretbox_ZEROBYTES,n,k); } for (i = 0;i < TIMINGS;++i) cycles[i] = cycles[i + 1] - cycles[i]; printentry(mlen,"forgery_open_cycles",cycles,TIMINGS); } } }
static ERL_NIF_TERM nacl_secretbox_open_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary key; ErlNifBinary nonce; ErlNifBinary padded_ciphertext; ErlNifBinary padded_message; 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], &key)) return enif_make_badarg(env); if (key.size != crypto_secretbox_KEYBYTES) return enif_make_badarg(env); if (nonce.size != crypto_secretbox_NONCEBYTES) return enif_make_badarg(env); if (padded_ciphertext.size < crypto_secretbox_BOXZEROBYTES) return enif_make_badarg(env); if (!enif_alloc_binary(padded_ciphertext.size, &padded_message)) return nacl_error_tuple(env, "alloc_failed"); if (crypto_secretbox_open(padded_message.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, key.data)) { return nacl_error_tuple(env, "crypto_failed"); } return enif_make_sub_binary(env, enif_make_binary(env, &padded_message), crypto_secretbox_ZEROBYTES, padded_ciphertext.size - crypto_secretbox_ZEROBYTES); }
main() { int mlen; int i; int caught; for (mlen = 0;mlen < 1000 && mlen + crypto_secretbox_ZEROBYTES < sizeof m;++mlen) { randombytes(k,crypto_secretbox_KEYBYTES); randombytes(n,crypto_secretbox_NONCEBYTES); randombytes(m + crypto_secretbox_ZEROBYTES,mlen); crypto_secretbox(c,m,mlen + crypto_secretbox_ZEROBYTES,n,k); caught = 0; while (caught < 10) { c[random() % (mlen + crypto_secretbox_ZEROBYTES)] = random(); if (crypto_secretbox_open(m2,c,mlen + crypto_secretbox_ZEROBYTES,n,k) == 0) { for (i = 0;i < mlen + crypto_secretbox_ZEROBYTES;++i) if (m2[i] != m[i]) { printf("forgery\n"); return 100; } } else { ++caught; } } } return 0; }
static nif_term_t salt_secretbox_open(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_secretbox_open(Cipher_text, Nonce, Secret_key) -> {ok, Plain_text} | forged_or_garbled. */ nif_bin_t ct; nif_bin_t nc; nif_bin_t sk; nif_bin_t pt; nif_term_t raw; nif_term_t sub; nif_term_t tag; if (argc != 3) 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], &sk)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (ct.size < crypto_secretbox_BOXZEROBYTES || ct.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)ct.data, &salt_secretbox_boxzerobytes[0], crypto_secretbox_BOXZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_secretbox_NONCEBYTES) return (BADARG); if (sk.size != crypto_secretbox_KEYBYTES) 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. */ if (crypto_secretbox_open(pt.data, ct.data, ct.size, nc.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_secretbox_ZEROBYTES, ct.size - crypto_secretbox_ZEROBYTES); tag = enif_make_atom(hp, "ok"); return (enif_make_tuple2(hp, tag, sub)); }
String NaCl::secret_decrypt(String enc_msg) { try { std::string encrypted_message = from_ruby<std::string>(enc_msg); std::string message = crypto_secretbox_open(encrypted_message, my_nonce, my_secret); return to_ruby<std::string>(message); } catch (int e) { return to_ruby<std::string>(""); } }
Message CryptoEngine::Decrypt(const std::vector<unsigned char> message_bytes) { // Parse from bytes to EcnryptedMessage object EncryptedMessage encrypted_msg = EncryptedMessage::FromBytes(message_bytes); // get the clear text, with the additional data prepended std::string clear_text_with_data(crypto_secretbox_open(encrypted_msg.message(), encrypted_msg.nonce(), secret_key_)); // convert the string data to a real message: (version, type, clear_text) Message message = Message::FromBytesString(clear_text_with_data); return message; }
bool decrypt_box(uint8_t *keys, box *outer, size_t len) { box *inner = (box *) outer->data; uint8_t *outer_key = keys; uint8_t *inner_key = keys + BOX_KEY_LEN; bool ok = false; if (decrypt_gcm(outer_key, outer->iv, outer->data, sizeof(box) + len, outer->tag)) { uint8_t *data = inner->tag; size_t inner_len = len + crypto_secretbox_ZEROBYTES; memset(data, 0, crypto_secretbox_BOXZEROBYTES); ok = crypto_secretbox_open(data, data, inner_len, inner->iv, inner_key) == 0; } return ok; }
int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) { if (length <= crypto_secretbox_BOXZEROBYTES) return -1; uint8_t temp_plain[length + crypto_secretbox_ZEROBYTES]; uint8_t temp_encrypted[length + crypto_secretbox_BOXZEROBYTES]; memset(temp_plain, 0, crypto_secretbox_BOXZEROBYTES); memcpy(temp_encrypted + crypto_secretbox_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. if (crypto_secretbox_open(temp_plain, temp_encrypted, length + crypto_secretbox_BOXZEROBYTES, nonce, secret_key) == -1) return -1; memcpy(plain, temp_plain + crypto_secretbox_ZEROBYTES, length - crypto_secretbox_MACBYTES); return length - crypto_secretbox_MACBYTES; }
PyObject *pycrypto_secretbox_open(PyObject *self, PyObject *args, PyObject *kw){ char *c, *n, *k; Py_ssize_t csize=0, nsize=0, ksize=0; static const char *kwlist[] = {"c", "n", "k", 0}; unsigned int i; PyObject *ret; size_t clen; unsigned char *mpad; unsigned char *cpad; if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#:crypto_secretbox_open", (char **) kwlist, &c, &csize, &n, &nsize, &k, &ksize)){ return (PyObject *)0;} if (nsize != crypto_secretbox_NONCEBYTES) return Py_BuildValue("i", 0); if (ksize != crypto_secretbox_KEYBYTES) return Py_BuildValue("i", 0); clen = csize + crypto_secretbox_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_secretbox_BOXZEROBYTES;++i) cpad[i] = 0; for (i = crypto_secretbox_BOXZEROBYTES;i < clen;++i) cpad[i] = c[i - crypto_secretbox_BOXZEROBYTES]; if (crypto_secretbox_open(mpad, cpad, clen, (const unsigned char *) n, (const unsigned char *) k) != 0){ PyMem_Free(mpad); PyMem_Free(cpad); return Py_BuildValue("i", 0);} if (clen < crypto_secretbox_ZEROBYTES){ PyMem_Free(mpad); PyMem_Free(cpad); return Py_BuildValue("i", 0);} ret = PyBytes_FromStringAndSize((char *)mpad + crypto_secretbox_ZEROBYTES, clen - crypto_secretbox_ZEROBYTES); PyMem_Free(mpad); PyMem_Free(cpad); return ret;}
int main(void) { int mlen; int i; for (mlen = 0;mlen < 1000 && mlen + crypto_secretbox_ZEROBYTES < sizeof m;++mlen) { randombytes(k,crypto_secretbox_KEYBYTES); randombytes(n,crypto_secretbox_NONCEBYTES); randombytes(m + crypto_secretbox_ZEROBYTES,mlen); crypto_secretbox(c,m,mlen + crypto_secretbox_ZEROBYTES,n,k); if (crypto_secretbox_open(m2,c,mlen + crypto_secretbox_ZEROBYTES,n,k) == 0) { for (i = 0;i < mlen + crypto_secretbox_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 () < 225) { errno = EPROTO; return -1; } const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); if (memcmp (initiate, "INITIATE\0", 9)) { 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) { 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)) { errno = EAGAIN; 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 + 96 + 256]; uint8_t initiate_box [crypto_box_BOXZEROBYTES + 112 + 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); rc = crypto_box_open (initiate_plaintext, initiate_box, clen, initiate_nonce, cn_client, cn_secret); if (rc != 0) { 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 + 32]; uint8_t vouch_box [crypto_box_BOXZEROBYTES + 48]; // Open Box [C'](C->S) and check contents memset (vouch_box, 0, crypto_box_BOXZEROBYTES); memcpy (vouch_box + crypto_box_BOXZEROBYTES, initiate_plaintext + crypto_box_ZEROBYTES + 48, 48); 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, secret_key); if (rc != 0) { 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)) { 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) { if (errno != EAGAIN) return -1; expecting_zap_reply = true; } } return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 96, clen - crypto_box_ZEROBYTES - 96); }
bool unit_test_crypto_secretbox(){ // 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]; // Shared key uint8_t key[32]; // Random plaintext uint8_t *plaintext = malloc((HACL_UNIT_TESTS_SIZE + crypto_secretbox_ZEROBYTES) * sizeof (uint8_t)); READ_RANDOM_BYTES(len, plaintext + crypto_secretbox_ZEROBYTES); for (int i = 0; i < crypto_secretbox_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 < 256; i++){ tweet_crypto_secretbox(expected_cipher, plaintext, crypto_secretbox_ZEROBYTES + i, nonce, key); crypto_secretbox(hacl_cipher, plaintext, crypto_secretbox_ZEROBYTES + i, nonce, key); a = memcmp(hacl_cipher, expected_cipher, (crypto_secretbox_ZEROBYTES + i) * sizeof (uint8_t)); if (a != 0){ pass = false; break; } /* a = crypto_secretbox_open_detached(hacl_cipher/\* +32 *\/, expected_cipher/\* +32 *\/, expected_cipher + 16, i, nonce, key); */ a = crypto_secretbox_open(hacl_cipher, expected_cipher, crypto_secretbox_ZEROBYTES + i, nonce, key); if (a != 0) { pass = false; printf("SECRETBOX OPEN ******* failed to verify on input of size %d\n", i); break; } a = memcmp(hacl_cipher, plaintext, (crypto_secretbox_ZEROBYTES + i) * sizeof (uint8_t)); if (a != 0) { pass = false; printf("SECRETBOX OPEN failed on input of size %d\n", i); break; } } if (!pass) return pass; // Test 2 tweet_crypto_secretbox(expected_cipher, plaintext, crypto_secretbox_ZEROBYTES + HACL_UNIT_TESTS_SIZE, nonce, key); crypto_secretbox(hacl_cipher, plaintext, crypto_secretbox_ZEROBYTES + HACL_UNIT_TESTS_SIZE, nonce, key); a = memcmp(hacl_cipher, expected_cipher, (crypto_secretbox_ZEROBYTES + HACL_UNIT_TESTS_SIZE) * sizeof (uint8_t)); if (a != 0){ pass = false; printf("SECRETBOX failed on input of size %d\n.", HACL_UNIT_TESTS_SIZE); } a = crypto_secretbox_open(hacl_cipher, expected_cipher, HACL_UNIT_TESTS_SIZE + crypto_secretbox_ZEROBYTES, nonce, key); if (a != 0) { pass = false; printf("SECRETBOX OPEN failed to verify on input of size %d\n", HACL_UNIT_TESTS_SIZE); } a = memcmp(hacl_cipher, plaintext, (crypto_secretbox_ZEROBYTES + HACL_UNIT_TESTS_SIZE) * sizeof (uint8_t)); if (a != 0) { pass = false; printf("SECRETBOX OPEN failed on input of size %d\n", HACL_UNIT_TESTS_SIZE); } free(plaintext); return pass; }
const char *checksum_compute(void) { long long i; long long j; for (j = 0;j < crypto_secretbox_ZEROBYTES;++j) m[j] = 0; for (i = 0;i < CHECKSUM_BYTES;++i) { long long mlen = i + crypto_secretbox_ZEROBYTES; long long tlen = i + crypto_secretbox_ZEROBYTES; long long clen = i + crypto_secretbox_ZEROBYTES; for (j = -16;j < 0;++j) k[j] = rand(); for (j = -16;j < 0;++j) n[j] = rand(); for (j = -16;j < 0;++j) m[j] = rand(); for (j = klen;j < klen + 16;++j) k[j] = rand(); for (j = nlen;j < nlen + 16;++j) n[j] = rand(); for (j = mlen;j < mlen + 16;++j) m[j] = rand(); for (j = -16;j < klen + 16;++j) k2[j] = k[j]; for (j = -16;j < nlen + 16;++j) n2[j] = n[j]; for (j = -16;j < mlen + 16;++j) m2[j] = m[j]; for (j = -16;j < clen + 16;++j) c2[j] = c[j] = rand(); if (crypto_secretbox(c,m,mlen,n,k) != 0) return "crypto_secretbox returns nonzero"; for (j = -16;j < mlen + 16;++j) if (m2[j] != m[j]) return "crypto_secretbox overwrites m"; for (j = -16;j < nlen + 16;++j) if (n2[j] != n[j]) return "crypto_secretbox overwrites n"; for (j = -16;j < klen + 16;++j) if (k2[j] != k[j]) return "crypto_secretbox overwrites k"; for (j = -16;j < 0;++j) if (c2[j] != c[j]) return "crypto_secretbox writes before output"; for (j = clen;j < clen + 16;++j) if (c2[j] != c[j]) return "crypto_secretbox writes after output"; for (j = 0;j < crypto_secretbox_BOXZEROBYTES;++j) if (c[j] != 0) return "crypto_secretbox does not clear extra bytes"; for (j = -16;j < 0;++j) c[j] = rand(); for (j = clen;j < clen + 16;++j) c[j] = rand(); for (j = -16;j < clen + 16;++j) c2[j] = c[j]; for (j = -16;j < tlen + 16;++j) t2[j] = t[j] = rand(); if (crypto_secretbox_open(t,c,clen,n,k) != 0) return "crypto_secretbox_open returns nonzero"; for (j = -16;j < clen + 16;++j) if (c2[j] != c[j]) return "crypto_secretbox_open overwrites c"; for (j = -16;j < nlen + 16;++j) if (n2[j] != n[j]) return "crypto_secretbox_open overwrites n"; for (j = -16;j < klen + 16;++j) if (k2[j] != k[j]) return "crypto_secretbox_open overwrites k"; for (j = -16;j < 0;++j) if (t2[j] != t[j]) return "crypto_secretbox_open writes before output"; for (j = tlen;j < tlen + 16;++j) if (t2[j] != t[j]) return "crypto_secretbox_open writes after output"; for (j = 0;j < crypto_secretbox_ZEROBYTES;++j) if (t[j] != 0) return "crypto_secretbox_open does not clear extra bytes"; for (j = 0;j < i;++j) if (t[j] != m[j]) return "plaintext does not match"; for (j = 0;j < i;++j) k[j % klen] ^= c[j + crypto_secretbox_BOXZEROBYTES]; crypto_secretbox(c,m,mlen,n,k); for (j = 0;j < i;++j) n[j % nlen] ^= c[j + crypto_secretbox_BOXZEROBYTES]; crypto_secretbox(c,m,mlen,n,k); if (i == 0) m[crypto_secretbox_ZEROBYTES + 0] = 0; m[crypto_secretbox_ZEROBYTES + i] = m[crypto_secretbox_ZEROBYTES + 0]; for (j = 0;j < i;++j) m[j + crypto_secretbox_ZEROBYTES] ^= c[j + crypto_secretbox_BOXZEROBYTES]; } sodium_bin2hex(checksum, sizeof checksum, k, klen); return 0; }
void doit(void) { crypto_secretbox(c,m,TUNE_BYTES + crypto_secretbox_ZEROBYTES,n,k); crypto_secretbox_open(t,c,TUNE_BYTES + crypto_secretbox_ZEROBYTES,n,k); }
static int _handle_initiate (struct curvecpr_server *server, struct curvecpr_session *s, void *priv, const struct curvecpr_packet_initiate *p, const unsigned char *buf, size_t num) { const struct curvecpr_server_cf *cf = &server->cf; unsigned char nonce[24]; unsigned char data[sizeof(struct curvecpr_packet_initiate_box) + 640]; if (s != NULL) { /* Update existing client. */ crypto_uint64 unpacked_nonce = curvecpr_bytes_unpack_uint64(p->nonce); if (unpacked_nonce <= s->their_session_nonce) return -EINVAL; curvecpr_bytes_copy(nonce, "CurveCP-client-I", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, buf, num); if (crypto_box_open_afternm(data, data, num + 16, nonce, s->my_session_their_session_key)) return -EINVAL; s->their_session_nonce = unpacked_nonce; curvecpr_session_set_priv(s, priv); if (cf->ops.recv(server, s, data + sizeof(struct curvecpr_packet_initiate_box), num + 16 - sizeof(struct curvecpr_packet_initiate_box))) return -EINVAL; return 0; } else { struct curvecpr_session s_new, *s_new_stored; const struct curvecpr_packet_initiate_box *p_box; /* Register new client. */ curvecpr_bytes_copy(nonce, "minute-k", 8); curvecpr_bytes_copy(nonce + 8, p->cookie, 16); /* We can reuse data; the cookie will fit into it. */ curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, p->cookie + 16, 80); /* Validate cookie. */ if (crypto_secretbox_open(data, data, 96, nonce, server->my_temporal_key)) { curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, p->cookie + 16, 80); if (crypto_secretbox_open(data, data, 96, nonce, server->my_last_temporal_key)) return -EINVAL; } if (!curvecpr_bytes_equal(p->client_session_pk, data + 32, 32)) return -EINVAL; /* Cookie is valid; set up keys. */ curvecpr_session_new(&s_new); curvecpr_bytes_copy(s_new.their_session_pk, data + 32, 32); curvecpr_bytes_copy(s_new.my_session_sk, data + 64, 32); crypto_box_beforenm(s_new.my_session_their_session_key, s_new.their_session_pk, s_new.my_session_sk); curvecpr_bytes_copy(nonce, "CurveCP-client-I", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, buf, num); if (crypto_box_open_afternm(data, data, num + 16, nonce, s_new.my_session_their_session_key)) return -EINVAL; p_box = (struct curvecpr_packet_initiate_box *)data; /* Attempt to validate this client. */ { unsigned char vouch[64]; curvecpr_bytes_copy(s_new.their_global_pk, p_box->client_global_pk, 32); crypto_box_beforenm(s_new.my_global_their_global_key, s_new.their_global_pk, cf->my_global_sk); curvecpr_bytes_copy(nonce, "CurveCPV", 8); curvecpr_bytes_copy(nonce + 8, p_box->nonce, 16); curvecpr_bytes_zero(vouch, 16); curvecpr_bytes_copy(vouch + 16, p_box->vouch, 48); if (crypto_box_afternm(vouch, vouch, 64, nonce, s_new.my_global_their_global_key)) return -EINVAL; if (!curvecpr_bytes_equal(vouch + 32, s_new.their_session_pk, 32)) return -EINVAL; } /* All good, we can go ahead and submit the client for registration. */ s_new.their_session_nonce = curvecpr_bytes_unpack_uint64(p->nonce); curvecpr_bytes_copy(s_new.my_domain_name, p_box->server_domain_name, 256); curvecpr_session_set_priv(&s_new, priv); if (cf->ops.put_session(server, &s_new, &s_new_stored)) return -EINVAL; /* This can fail for a variety of reasons that are up to the delegate to determine, but two typical ones will be too many connections or an invalid domain name. */ /* Now the session is registered; we can send the encapsulated message. */ if (cf->ops.recv(server, s_new_stored, data + sizeof(struct curvecpr_packet_initiate_box), num + 16 - sizeof(struct curvecpr_packet_initiate_box))) return -EINVAL; return 0; } }
static int crypto_read(const char *path, char *buf, size_t size, off_t off, struct fuse_file_info *inf){ size_t red = 0; while(size > 0) { int idx = off / (block_size - crypto_PADDING); size_t delta = off % (block_size - crypto_PADDING); size_t bsize = block_size, fudge = 0; if(size < block_size - crypto_PADDING) { // We have to check that we aren't in partial block land, when reading from // the end of the file by stating the file and checking that the requested // offset isn't a slice of a partial block. struct stat st = {0}; int staterr = crypto_getattr(path, &st); if(staterr < 0) return staterr; size_t next_block = (idx + 1) * (block_size - crypto_PADDING); if(st.st_size < next_block) next_block = st.st_size; if(next_block - off > size) fudge = next_block - off - size; } if(bsize > block_size) printf("bzize: %zu size: %zu delta: %zu\n", bsize, size, delta); char block[bsize]; int res = pread(inf->fh, block, bsize, block_size * idx); if(res == -1) return -errno; if(res == 0) return red; unsigned char nonce[crypto_secretbox_NONCEBYTES]; memcpy(nonce, block, crypto_secretbox_NONCEBYTES); size_t csize = res - crypto_secretbox_NONCEBYTES + crypto_secretbox_BOXZEROBYTES; unsigned char cpad[csize]; memset(cpad, 0, csize); memcpy(cpad + crypto_secretbox_BOXZEROBYTES, block + crypto_secretbox_NONCEBYTES, csize); unsigned char mpad[csize]; memset(mpad, 0, csize); int ruroh = crypto_secretbox_open(mpad, cpad, csize, nonce, key); if(ruroh == -1) { printf("error at index: %i offset: %llu read: %i size: %zu path: %s\n", idx, off, res, bsize, path); return -ENXIO; } memcpy(buf + red, mpad + delta + crypto_secretbox_ZEROBYTES, csize - delta - fudge - crypto_secretbox_ZEROBYTES); size -= res - crypto_PADDING - fudge - delta; red += res - crypto_PADDING - fudge - delta; off += res - crypto_PADDING - fudge - delta; } return red; }
int main(){ int s,b,on=1,i; struct sockaddr_in channel, server; unsigned char buf[BUF_SIZE]; unsigned char k[crypto_secretbox_KEYBYTES]; unsigned char n[crypto_secretbox_NONCEBYTES]; unsigned char m[BUF_SIZE]; unsigned long long mlen = BUF_SIZE; unsigned char c[BUF_SIZE]; /* Address structure */ memset(&channel,0,sizeof(channel)); channel.sin_family = AF_INET; channel.sin_addr.s_addr = htonl(INADDR_ANY); channel.sin_port = htons(CLIENT_PORT); /* Build socket and Bind */ s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); /* Create socket */ if(s<0) fatal("Failed to create socket!"); setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on)); //Osäker på denna b = bind(s,(struct sockaddr *)&channel,sizeof(channel)); if(b<0){ fatal("Bind failed "); } //Setting up server address memset(&server,0,sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //INADDR_LOOPBACK är denna datorns ip i.e 127.0.0.1 //inet_addr(serverIP); <- får användas över nätverk där serverIP ges som klassisk xxx.xxx.xxx.xxx server.sin_port = htons(SERVER_PORT); //Serverns portnummer /* Time to start sending */ if(connect(s,(struct sockaddr *)&server,sizeof(server))){ fatal("Could not connect to server"); } //usleep(1000); //Ska tydligen ge server tid fast det funkar utan detta, iallafall när localhost-localhost // Här börjar diffie-hellman ************************************************************************* if(!dh(k,crypto_secretbox_KEYBYTES,n,crypto_secretbox_NONCEBYTES,s)){ fatal("Diffie-hellman fail!"); } // S**t på diffie-hellman ********************************************************* // Här Börjar symetrisk krytering ************************************************* while(1){ //Infinite message chain loop for(i=0;i<BUF_SIZE;i++){ //Reset message m[i] = 0; } i = crypto_secretbox_ZEROBYTES; //Begin message at byte 32 printf("\nWrite your message(q/Q to quit):\n"); fgets((char *)&m[i],200,stdin); // Get message from user max 200 charachters (should be enough) if((m[i] =='q' || m[i] == 'Q') && strlen((char *)&m[i]) == 2){ break; } if(VISIBLE){ printf("\n\n****** Symmetric encryption/decryption echo begin ******\n\n"); printf("\nClient plaintext:\n%s\n",&m[i]); } if(crypto_secretbox(c,m,mlen,n,k)!=0){ fatal("Cryptobox fail!"); } inc_nonce(n); if(VISIBLE){ printf("\nClient ciphertext:\n%s\n",&c[crypto_secretbox_ZEROBYTES]); //Kolla om detta borde stämma } if(write(s,c,BUF_SIZE)==-1){ // Skriver meddelandet till server. _!check!_ check funkar ej pröva annat (send)! fatal("Server not responding"); } for(i=0;i<BUF_SIZE;i++){ buf[i] = 0; } read(s,c,BUF_SIZE); // Läser in svar _!check!_ if(VISIBLE){ printf("\nServer ciphertext:\n%s\n",&c[crypto_secretbox_ZEROBYTES]); } if(crypto_secretbox_open(buf,c,BUF_SIZE,n,k)==-1){ fatal("Decryption fail!"); } inc_nonce(n); if(VISIBLE){ printf("\nServer plaintext:\n%s\n",&buf[crypto_secretbox_ZEROBYTES]); printf("\n\n****** Symmetric encrytion/decryption echo end ******\n\n"); } printf("\n\n"); printf("Server says: %s\n", &buf[32]); } close(s); printf("Exiting program!\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); }
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); }