Example #1
0
int
main(void)
{
    size_t i;
    int    ret;

    ret = crypto_box_easy(c, m, 131, nonce, bobpk, alicesk);
    assert(ret == 0);
    for (i = 0; i < 131 + crypto_box_MACBYTES; ++i) {
        printf(",0x%02x", (unsigned int) c[i]);
    }
    printf("\n");

    /* Null message */

    ret = crypto_box_easy(c, c, 0, nonce, bobpk, alicesk);
    assert(ret == 0);
    for (i = 0; i < 1 + crypto_box_MACBYTES; ++i) {
        printf(",0x%02x", (unsigned int) c[i]);
    }
    printf("\n");
    ret =
        crypto_box_open_easy(c, c, crypto_box_MACBYTES, nonce, bobpk, alicesk);
    assert(ret == 0);
    for (i = 0; i < 1 + crypto_box_MACBYTES; ++i) {
        printf(",0x%02x", (unsigned int) c[i]);
    }
    printf("\n");
    c[randombytes_uniform(crypto_box_MACBYTES)]++;
    ret = crypto_box_open_easy(c, c, crypto_box_MACBYTES, nonce, bobpk, alicesk);
    assert(ret == -1);

    return 0;
}
Example #2
0
int main(void)
{
    size_t i;

    crypto_box_easy(c, m, 131, nonce, bobpk, alicesk);
    for (i = 0; i < 131 + crypto_box_MACBYTES; ++i) {
        printf(",0x%02x", (unsigned int)c[i]);
        if (i % 8 == 7)
            printf("\n");
    }
    printf("\n");

    assert(crypto_box_easy(c, m, SIZE_MAX - 1U, nonce, bobpk, alicesk) == -1);

    return 0;
}
Example #3
0
int
shick_crypto_enc_message(const SC_CHAR sender_secret_key[crypto_box_SECRETKEYBYTES],
                         const SC_CHAR** recipient_public_keys,
                         const int amount_of_recipients,
                         const SC_CHAR* message,
                         const SC_LEN message_len,
                         SC_CHAR nonce[crypto_box_NONCEBYTES],
                         SC_ENC_SYM_KEY* encrypted_symmetric_keys,
                         SC_CHAR* ciphertext) {
  int failed = 0;

  // Create symmetric key
  SC_SYM_KEY sym_key;
  randombytes_buf((void*) sym_key.key, sizeof sym_key.key);
  randombytes_buf((void*) sym_key.nonce, sizeof sym_key.nonce);

  // Encrypt message symmetrically
  failed = crypto_secretbox_easy(ciphertext, message, message_len, sym_key.nonce, sym_key.key);
  if (failed) return SC_ENC_SYM_FAILED;

  // Encrypt symmetric key asymmetrically for each recipient
  for (int i = 0; i < amount_of_recipients; i++) {
    SC_CHAR public_key[crypto_box_PUBLICKEYBYTES];
    memcpy(public_key, recipient_public_keys[i], crypto_box_PUBLICKEYBYTES);
    failed = crypto_box_easy((SC_CHAR*) &encrypted_symmetric_keys[i], (SC_CHAR*) &sym_key, sizeof sym_key, nonce, public_key, sender_secret_key);
    if (failed) return SC_ENC_ASYM_FAILED;
  }

  return 0;
}
Example #4
0
static void
sigabrt_handler_11(int sig)
{
    (void) sig;
    signal(SIGABRT, sigabrt_handler_12);
    assert(crypto_box_easy(NULL, NULL, crypto_stream_xsalsa20_MESSAGEBYTES_MAX,
                           NULL, NULL, NULL) == -1);
    exit(1);
}
int
crypto_box_seal(unsigned char *c, const unsigned char *m,
                unsigned long long mlen, const unsigned char *pk)
{
    unsigned char nonce[crypto_box_NONCEBYTES];
    unsigned char epk[crypto_box_PUBLICKEYBYTES];
    unsigned char esk[crypto_box_SECRETKEYBYTES];
    int           ret;

    if (crypto_box_keypair(epk, esk) != 0) {
        return -1; /* LCOV_EXCL_LINE */
    }
    memcpy(c, epk, crypto_box_PUBLICKEYBYTES);
    _crypto_box_seal_nonce(nonce, epk, pk);
    ret = crypto_box_easy(c + crypto_box_PUBLICKEYBYTES, m, mlen,
                          nonce, pk, esk);
    sodium_memzero(nonce, sizeof nonce);
    sodium_memzero(epk, sizeof epk);
    sodium_memzero(esk, sizeof esk);

    return ret;
}
    bool
    encrypt_to(
      nonce const& nonce
    , public_key const& public_key
    , private_key const& private_key
    )
    noexcept {
      auto full_span = view_.span();
      auto data_span = view_.data_span();

      return
        crypto_box_easy(
          &full_span[0]
        , &data_span[0]
        , static_cast<std::size_t>(data_span.size())
        , &nonce[0]
        , &public_key[0]
        , &private_key[0]
        )
        == 0
      ;
    }
Example #7
0
QByteArray Toxme::prepareEncryptedJson(QString url, int action, QString payload)
{
    QPair<QByteArray, QByteArray> keypair = Core::getInstance()->getKeypair();
    if (keypair.first.isEmpty() || keypair.second.isEmpty()) {
        qWarning() << "prepareEncryptedJson: Couldn't get our keypair, aborting";
        return QByteArray();
    }

    QNetworkReply::NetworkError error = QNetworkReply::NoError;
    QByteArray key = getServerPubkey(url, error);
    if (error != QNetworkReply::NoError)
        return QByteArray();

    QByteArray nonce(crypto_box_NONCEBYTES, 0);
    randombytes((uint8_t*)nonce.data(), crypto_box_NONCEBYTES);

    QByteArray payloadData = payload.toUtf8();
    const size_t cypherlen = crypto_box_MACBYTES + payloadData.size();
    unsigned char* payloadEnc = new unsigned char[cypherlen];

    int cryptResult = crypto_box_easy(payloadEnc, (uint8_t*)payloadData.data(), payloadData.size(),
                                      (uint8_t*)nonce.data(), (unsigned char*)key.constData(),
                                      (uint8_t*)keypair.second.data());

    if (cryptResult != 0) // error
        return QByteArray();

    QByteArray payloadEncData(reinterpret_cast<char*>(payloadEnc), cypherlen);
    delete[] payloadEnc;

    const QString json{"{\"action\":" + QString().setNum(action) + ","
                                                                   "\"public_key\":\""
                       + keypair.first.toHex() + "\","
                                                 "\"encrypted\":\""
                       + payloadEncData.toBase64() + "\","
                                                     "\"nonce\":\""
                       + nonce.toBase64() + "\"}"};
    return json.toUtf8();
}
Example #8
0
///
/// We update the data in the packet from our CryptCurve25519 object with the
/// side-effect of encrypting all the frames already put into the packet.  Note that
/// this only works because we always construct the packet from the end back to the
/// beginning.  We do this in-place - fortunately the algorithms allow that...
/// We effectively suck all the remaining frames into a single encrypted frame...
FSTATIC void	
_cryptcurve25519_updatedata(Frame* f,			///< Frame to marshall
			    gpointer tlvstart,		///< Start of our Frame in the packet
			    gconstpointer pktend,	///< Last byte in the allocated packet
			    FrameSet* unused_fs)	///< Pointer to our containing frameset
{
	CryptCurve25519*self		= CASTTOCLASS(CryptCurve25519, f);
	const guint8*	pktend8		= pktend;
	//guint8*	tlvstart8	= tlvstart;
	guint8*		tlvval;
	guint8*		valptr;
	guint32		plaintextoffset;
	guint32		plaintextsize;
	guint32		cyphertextoffset;
	guint32		nonceoffset;
	guint32		tlvsize;
	unsigned char*	nonce;
	int		j;

	(void)unused_fs;
	
	// [key1, key2, nonce, MAC, plaintext]

	DUMP3(__FUNCTION__, &f->baseclass, " is CryptCurve25519 Frame being processed.");
	DEBUGMSG3("%s.%d: tlvstart:%p, pktend:%p", __FUNCTION__, __LINE__, tlvstart, pktend);
	// The plain text starts immediately after our (incoming) frame
	plaintextoffset = f->length;					// Plain text starts here
	cyphertextoffset = plaintextoffset - crypto_box_MACBYTES;	// Preceded by MAC
	nonceoffset = cyphertextoffset - crypto_box_NONCEBYTES;		// Preceded by nonce
	// Our (outgoing) frame consists of the original incoming frame plus all other frames after ours
	tlvval = get_generic_tlv_nonconst_value(tlvstart, pktend);
	tlvsize = pktend8 - tlvval;
	plaintextsize = (tlvsize - plaintextoffset);

	// Generate a "nonce" as part of the packet - make known plaintext attacks harder
	// ... lots of our plaintext is easy to figure out ...
	nonce = tlvval + nonceoffset;
	DEBUGMSG3("%s.%d: generating random nonce (%p, %d, %p)", __FUNCTION__, __LINE__
	,	nonce, (int)crypto_box_NONCEBYTES, nonce+crypto_box_NONCEBYTES);
	randombytes_buf(nonce, crypto_box_NONCEBYTES);
	DEBUGMSG3("%s.%d: random nonce generated.", __FUNCTION__, __LINE__);

	DEBUGMSG3("%s.%d: public->key_id: [%s], private_key->key_id: [%s]", __FUNCTION__, __LINE__
	,	self->public_key->key_id, self->private_key->key_id);
	DEBUGMSG3("%s.%d: calling crypto_box_easy(%p,%p,%d,%p,%p,%p)", __FUNCTION__, __LINE__
	,	tlvval+cyphertextoffset, tlvval+plaintextoffset, plaintextsize
	,	nonce, self->public_key->public_key, self->private_key->private_key);
	DEBUGCKSUM4("plain text cksum:", tlvval+plaintextoffset, plaintextsize);
	DEBUGCKSUM4("receiver public key cksum:",self->public_key -> public_key, crypto_box_PUBLICKEYBYTES);
	DEBUGCKSUM4("sender  private key cksum:", self->private_key->private_key, crypto_box_SECRETKEYBYTES);
	DEBUGCKSUM4("nonce cksum:", nonce, crypto_box_NONCEBYTES);
	// Encrypt in-place [we previously allocated enough space for authentication info]
	crypto_box_easy(tlvval+cyphertextoffset, tlvval+plaintextoffset, plaintextsize
	,	nonce, self->public_key->public_key, self->private_key->private_key);
	DEBUGMSG4("cypher offset versus tlvstart: %ld", (long)(tlvval+cyphertextoffset-(guint8*)tlvstart));
	DEBUGCKSUM4("cypher text checksum:", tlvval+cyphertextoffset, plaintextsize+crypto_box_MACBYTES);
	set_generic_tlv_type(tlvstart, self->baseclass.baseclass.type, pktend);
	set_generic_tlv_len(tlvstart, tlvsize, pktend);
	// Put in the frame type, length, key name length, and key name for both keys
	// We're the sender - our [private] key name goes first, then the receiver's [public] key name
	valptr = get_generic_tlv_nonconst_value(tlvstart, pktend);
	for (j=0; j < 2; ++j) {
		char *	key_id = (j == 0 ? self->baseclass.sender_key_id : self->baseclass.receiver_key_id);
		int	keylen = strlen(key_id)+1;
		tlv_set_guint8(valptr, keylen, pktend);
		valptr += 1;
		g_strlcpy((char *)valptr, key_id, keylen);
		valptr += keylen;
	}
	DEBUGMSG3("%s.%d: returning after next assert (tlvval:%p, tlvsize%d, pktend:%p"
	,	__FUNCTION__, __LINE__, tlvval, (int)tlvsize, pktend);
	g_assert((tlvval + tlvsize) == pktend);
	DEBUGMSG3("%s.%d: returning (assert passed).", __FUNCTION__, __LINE__);
}
Example #9
0
int main(void)
{
    unsigned char *alicepk;
    unsigned char *alicesk;
    unsigned char *bobpk;
    unsigned char *bobsk;
    unsigned char *mac;
    unsigned char *nonce;
    unsigned char *k1;
    unsigned char *k2;
    unsigned char *m;
    unsigned char *m2;
    unsigned char *c;
    size_t         mlen;
    size_t         i;
    size_t         m_size;
    size_t         m2_size;
    size_t         c_size;
    int            ret;

    m2_size = m_size = 1U + randombytes_uniform(10000);
    c_size = crypto_box_MACBYTES + m_size;
    m = (unsigned char *) sodium_malloc(m_size);
    m2 = (unsigned char *) sodium_malloc(m2_size);
    c = (unsigned char *) sodium_malloc(c_size);
    alicepk = (unsigned char *) sodium_malloc(crypto_box_PUBLICKEYBYTES);
    alicesk = (unsigned char *) sodium_malloc(crypto_box_SECRETKEYBYTES);
    bobpk = (unsigned char *) sodium_malloc(crypto_box_PUBLICKEYBYTES);
    bobsk = (unsigned char *) sodium_malloc(crypto_box_SECRETKEYBYTES);
    mac = (unsigned char *) sodium_malloc(crypto_box_MACBYTES);
    nonce = (unsigned char *) sodium_malloc(crypto_box_NONCEBYTES);
    k1 = (unsigned char *) sodium_malloc(crypto_box_BEFORENMBYTES);
    k2 = (unsigned char *) sodium_malloc(crypto_box_BEFORENMBYTES);
    crypto_box_keypair(alicepk, alicesk);
    crypto_box_keypair(bobpk, bobsk);
    mlen = (size_t) randombytes_uniform((uint32_t) m_size) + 1U;
    randombytes_buf(m, mlen);
    randombytes_buf(nonce, crypto_box_NONCEBYTES);
    ret = crypto_box_easy(c, m, mlen, nonce, bobpk, alicesk);
    assert(ret == 0);
    if (crypto_box_open_easy(m2, c,
                             (unsigned long long) mlen + crypto_box_MACBYTES,
                             nonce, alicepk, bobsk) != 0) {
        printf("open() failed");
        return 1;
    }
    printf("%d\n", memcmp(m, m2, mlen));

    for (i = 0; i < mlen + crypto_box_MACBYTES - 1; i++) {
        if (crypto_box_open_easy(m2, c, (unsigned long long) i,
                                 nonce, alicepk, bobsk) == 0) {
            printf("short open() should have failed");
            return 1;
        }
    }
    memcpy(c, m, mlen);
    ret = crypto_box_easy(c, c, (unsigned long long) mlen, nonce, bobpk, alicesk);
    assert(ret == 0);
    printf("%d\n", memcmp(m, c, mlen) == 0);
    printf("%d\n", memcmp(m, c + crypto_box_MACBYTES, mlen) == 0);
    if (crypto_box_open_easy(c, c,
                             (unsigned long long) mlen + crypto_box_MACBYTES,
                             nonce, alicepk, bobsk) != 0) {
        printf("crypto_box_open_easy() failed\n");
    }

    ret = crypto_box_beforenm(k1, alicepk, bobsk);
    assert(ret == 0);
    ret = crypto_box_beforenm(k2, bobpk, alicesk);
    assert(ret == 0);

    memset(m2, 0, m2_size);

    if (crypto_box_easy_afternm(c, m, SIZE_MAX - 1U, nonce, k1) == 0) {
        printf("crypto_box_easy_afternm() with a short ciphertext should have failed\n");
    }
    crypto_box_easy_afternm(c, m, (unsigned long long) mlen, nonce, k1);
    if (crypto_box_open_easy_afternm(m2, c,
                                     (unsigned long long) mlen + crypto_box_MACBYTES,
                                 nonce, k2) != 0) {
        printf("crypto_box_open_easy_afternm() failed\n");
    }
    printf("%d\n", memcmp(m, m2, mlen));
    if (crypto_box_open_easy_afternm(m2, c, crypto_box_MACBYTES - 1U,
                                     nonce, k2) == 0) {
        printf("crypto_box_open_easy_afternm() with a huge ciphertext should have failed\n");
    }
    memset(m2, 0, m2_size);
    ret = crypto_box_detached(c, mac, m, (unsigned long long) mlen,
                              nonce, alicepk, bobsk);
    assert(ret == 0);
    if (crypto_box_open_detached(m2, c, mac, (unsigned long long) mlen,
                                 nonce, bobpk, alicesk) != 0) {
        printf("crypto_box_open_detached() failed\n");
    }
    printf("%d\n", memcmp(m, m2, mlen));

    memset(m2, 0, m2_size);
    crypto_box_detached_afternm(c, mac, m, (unsigned long long) mlen,
                                nonce, k1);
    if (crypto_box_open_detached_afternm(m2, c, mac, (unsigned long long) mlen,
                                         nonce, k2) != 0) {
        printf("crypto_box_open_detached_afternm() failed\n");
    }
    printf("%d\n", memcmp(m, m2, mlen));

    sodium_free(alicepk);
    sodium_free(alicesk);
    sodium_free(bobpk);
    sodium_free(bobsk);
    sodium_free(mac);
    sodium_free(nonce);
    sodium_free(k1);
    sodium_free(k2);
    sodium_free(m);
    sodium_free(m2);
    sodium_free(c);
    printf("OK\n");

    return 0;
}
Example #10
0
/*
 * Using public-key authenticated encryption, Bob can encrypt a
 * confidential message specifically for Alice, using Alice's public
 * key.
 *
 * Using Bob's public key, Alice can verify that the encrypted
 * message was actually created by Bob and was not tampered with,
 * before eventually decrypting it.
 *
 * Alice only needs Bob's public key, the nonce and the ciphertext.
 * Bob should never ever share his secret key, even with Alice.
 *
 * And in order to send messages to Alice, Bob only needs Alice's
 * public key. Alice should never ever share her secret key either,
 * even with Bob.
 *
 * Alice can reply to Bob using the same system, without having to
 * generate a distinct key pair.
 *
 * The nonce doesn't have to be confidential, but it should be used
 * with just one invokation of crypto_box_open_easy() for a
 * particular pair of public and secret keys.
 *
 * One easy way to generate a nonce is to use randombytes_buf(),
 * considering the size of nonces the risk of any random collisions
 * is negligible. For some applications, if you wish to use nonces to
 * detect missing messages or to ignore replayed messages, it is also
 * ok to use a simple incrementing counter as a nonce.
 *
 * When doing so you must ensure that the same value can never be
 * re-used (for example you may have multiple threads or even hosts
 * generating messages using the same key pairs).
 *
 * This system provides mutual authentication. However, a typical use
 * case is to secure communications between a server, whose public
 * key is known in advance, and clients connecting anonymously.
 */
static int
box(void)
{
    unsigned char bob_pk[crypto_box_PUBLICKEYBYTES]; /* Bob's public key */
    unsigned char bob_sk[crypto_box_SECRETKEYBYTES]; /* Bob's secret key */

    unsigned char alice_pk[crypto_box_PUBLICKEYBYTES]; /* Alice's public key */
    unsigned char alice_sk[crypto_box_SECRETKEYBYTES]; /* Alice's secret key */

    unsigned char nonce[crypto_box_NONCEBYTES];
    unsigned char message[MAX_INPUT_LEN];
    unsigned char ciphertext[crypto_box_MACBYTES + MAX_INPUT_LEN];
    size_t        message_len;
    size_t        ciphertext_len;
    int           ret;

    puts("Example: crypto_box_easy\n");

    puts("Generating keypairs...\n");
    crypto_box_keypair(bob_pk, bob_sk);     /* generate Bob's keys */
    crypto_box_keypair(alice_pk, alice_sk); /* generate Alice's keys */

    puts("Bob");
    printf("Public key: ");
    print_hex(bob_pk, sizeof bob_pk);
    printf("Secret key: ");
    print_hex(bob_sk, sizeof bob_sk);

    puts("Alice");
    printf("Public key: ");
    print_hex(alice_pk, sizeof alice_pk);
    printf("Secret key: ");
    print_hex(alice_sk, sizeof alice_sk);

    /* nonce must be unique per (key, message) - it can be public and deterministic */
    puts("Generating nonce...");
    randombytes_buf(nonce, sizeof nonce);
    printf("Nonce: ");
    print_hex(nonce, sizeof nonce);

    /* read input */
    message_len = prompt_input("a message", (char*)message, sizeof message, 1);

    print_hex(message, message_len);

    /* encrypt and authenticate the message */
    printf("Encrypting and authenticating with %s\n\n", crypto_box_primitive());
    crypto_box_easy(ciphertext, message, message_len, nonce, alice_pk, bob_sk);
    ciphertext_len = crypto_box_MACBYTES + message_len;

    /* send the nonce and the ciphertext */
    puts("Bob sends the nonce and the ciphertext...\n");
    printf("Ciphertext len: %zu bytes - Original message length: %zu bytes\n",
           ciphertext_len, message_len);
    puts("Notice the prepended 16 byte authentication token\n");
    printf("Nonce: ");
    print_hex(nonce, sizeof nonce);
    printf("Ciphertext: ");
    print_hex(ciphertext, ciphertext_len);

    /* decrypt the message */
    puts("Alice verifies and decrypts the ciphertext...");
    ret = crypto_box_open_easy(message, ciphertext, ciphertext_len, nonce, bob_pk,
                               alice_sk);
    print_hex(message, message_len);

    print_verification(ret);
    if (ret == 0) {
        printf("Plaintext: ");
        fwrite(message, 1U, message_len, stdout);
        putchar('\n');
    }
    sodium_memzero(bob_sk, sizeof bob_sk); /* wipe sensitive data */
    sodium_memzero(alice_sk, sizeof alice_sk);
    sodium_memzero(message, sizeof message);
    sodium_memzero(ciphertext, sizeof ciphertext);

    return ret;
}
Example #11
0
void
nc_otoc_start(nc_opts *opts, int pair_raw_sock)
{
  int shell_fd_sock;
  int pair_fd_sock;

  fd_set readfds;
  int maxfds;
  char time_str[NOW_STR_LEN];

  enum {init, none,
	text_sent, text_received,
	pkey_sent, pkey_received} last_action = init;

  shell_fd_sock = fileno(stdin);
  pair_fd_sock = nc_utils_get_rec_sockfd(pair_raw_sock);
  maxfds = pair_fd_sock + 1;

  /* --- start of sending public key --- */
  if(opts->secure) {

    char *msg = NULL;
    char *msg_type = OTOC_MTYPE_PKEY;
    char *msg_body = NULL;

    /* --- start of encoding public key --- */
    const char *plain_pkey = (const char*) my_publickey;
    int plain_pkey_len = crypto_box_PUBLICKEYBYTES;
    char encoded_pkey[Base64encode_len(plain_pkey_len)];
    Base64encode(encoded_pkey, plain_pkey, plain_pkey_len);
    nc_log_writef("debug", "encode my public key: %s", encoded_pkey);
    /* --- end of encoding public key --- */

    msg_body = encoded_pkey;
    nc_json_make_otoc_msg(&msg_type, &msg_body, plain_pkey_len, &msg);
    nn_send(pair_raw_sock, msg, strlen(msg), 0);
    nc_log_writef("debug", "one to one chat sent public key: %s", msg);
    last_action = pkey_sent;
    
  }
  /* --- end of sending public key --- */
  
  /* --- start of shel command registration --- */
  nc_otoc_register_cmd("/help", func_cmd_help);
  nc_otoc_register_cmd("/leave", func_cmd_leave);
  /* --- end of shell commmand registration --- */

  for(;;) {

    switch(last_action) {
    case init:
    case pkey_sent:
      fprintf(stdout,
	      ">> Entering (room code %d) ...\n",
	      pair_raw_sock);
      fprintf(stdout, ">>> ");
      fflush(stdout); 
      break;
    case text_received: 
      fprintf(stdout, ">>> ");
      fflush(stdout); 
      break;
    case text_sent: 
      fprintf(stdout, ">>> "); 
      fflush(stdout); 
      break;
    case none:
      fprintf(stdout, ">>> ");
      fflush(stdout);
      break;
    case pkey_received:
      break;
    }

    FD_ZERO(&readfds);
    FD_SET(pair_fd_sock, &readfds);
    FD_SET(shell_fd_sock, &readfds);

    select(maxfds, &readfds, NULL, NULL, NULL);

    if(FD_ISSET(shell_fd_sock, &readfds)) {      

      char *buf = NULL;
      size_t buf_sz = 1024;
      int i;

      nc_utils_now_str(time_str);      
      getline(&buf, &buf_sz, stdin);

      if(buf[0] == '\n') {
	
	last_action = none;

      } else if(buf[0] == '/') {

	nc_utils_del_new_line(buf);
	for(i = 0; i < cmd_current_code; i++) {
	  
	  if(strstr(buf, cmds[i].name)) {

	    if(cmds[i].func(buf) < 0) {
	      return;
	    }

	    break;
	  }
	}

	last_action = none;

      } else {

	if(opts->secure) {

	  /* --- make ciphermsg with key pairs --- */
	  int ciphermsg_len = crypto_box_MACBYTES + strlen(buf);
	  unsigned char nonce[crypto_box_NONCEBYTES];
	  unsigned char ciphermsg[ciphermsg_len];

	  /* @TODO: use random nonce */
	  //randombytes_buf(nonce, sizeof nonce);
	  memset(nonce, '\0', sizeof nonce);
	  
	  crypto_box_easy(ciphermsg, (const unsigned char*) buf,
	  		  strlen(buf), nonce,
	  		  peers_publickey[pair_raw_sock], my_secretkey);

	  /* --- make msg encoded with base64  --- */
	  const char *plain_ciphermsg = (const char*) ciphermsg;
	  int plain_ciphermsg_len = ciphermsg_len;
	  int encoded_ciphermsg_len = Base64encode_len(plain_ciphermsg_len);
	  char encoded_ciphermsg[encoded_ciphermsg_len];

	  Base64encode(encoded_ciphermsg, plain_ciphermsg, plain_ciphermsg_len);
	  nc_log_writef("debug", "encode ciphermsg: %s", encoded_ciphermsg);

	  /* --- serialize msg with json --- */
	  char *msg = NULL;
	  char *msg_type = OTOC_MTYPE_STXT;
	  char *msg_body = NULL;

	  msg_body = encoded_ciphermsg;
	  nc_json_make_otoc_msg(&msg_type, &msg_body, strlen(buf), &msg);
	  nc_log_writef("debug", "serialize encoded ciphermsg: %s", msg);
	  
	  /* --- send msg --- */
	  nn_send(pair_raw_sock, msg, strlen(msg), 0);

	} else {

	  char *msg = NULL;
	  char *msg_type = OTOC_MTYPE_RTXT;

	  nc_json_make_otoc_msg(&msg_type, &buf, strlen(buf), &msg);
	  nn_send(pair_raw_sock, msg, strlen(msg), 0);
	  fprintf(stdout, "[%s] >>> %s", time_str, buf);
	  fflush(stdout);
	  nc_utils_del_new_line(buf);
	  nc_log_writef("debug", "one to one chat sent: %s", buf);
	  nc_utils_empty_string(buf);
	  last_action = text_sent;

	}

      }
      
    } else if(FD_ISSET(pair_fd_sock, &readfds)) {

      char *buf = NULL;
      char *msg_body = NULL;
      char *msg_type = NULL;
      int original_msg_body_len;
      
      nn_recv(pair_raw_sock, &buf, NN_MSG, 0);
      nc_json_extract_otoc_msg(&buf, &msg_type, &original_msg_body_len, &msg_body);

      nc_utils_del_new_line(buf);
      nc_log_writef("debug", "one to one chat received: %s", msg_type);
      nn_freemsg(buf);
      
      if(strncmp(msg_type, OTOC_MTYPE_PKEY, OTOC_MTYPE_LEN) == 0) {

	/* public key message */

	/* --- start of decoding public key --- */
	int plain_pkey_len = Base64decode_len(msg_body);
	char plain_pkey[plain_pkey_len];

	Base64decode(plain_pkey, (const char*) msg_body);
	strncpy(peers_publickey[pair_raw_sock], plain_pkey, crypto_box_PUBLICKEYBYTES);
	nc_log_writef("debug", "decoded peer's public key was stored.");
	/* --- end of decoding public key --- */
	
	last_action = pkey_received;
	
      } else if(strncmp(msg_type, OTOC_MTYPE_RTXT, OTOC_MTYPE_LEN) == 0) {

	/* raw text message */

	nc_utils_now_str(time_str);
	fprintf(stdout, "\r[%s] <<< %s", time_str, msg_body);
	fflush(stdout);
	last_action = text_received;

      } else if(strncmp(msg_type, OTOC_MTYPE_STXT, OTOC_MTYPE_LEN) == 0) {

	/* secure text message */

	if(!opts->secure) {

	  char *alert =
	    "\r[%s] <<< { ... encrypted message ... }\n"
	    "==========================================\n"
	    "Your peer uses NanoChat undre secure mode.\n"
	    "Use -s flag to see his encrypted messages.\n"
	    "==========================================\n";

	  nc_utils_now_str(time_str);
	  fprintf(stdout, alert, time_str);
	  fflush(stdout);
	  last_action = text_received;

	} else {

	  /* --- decode  secure msg body --- */
	  int plain_ciphermsg_len = Base64decode_len(msg_body);
	  char plain_ciphermsg[plain_ciphermsg_len];

	  Base64decode(plain_ciphermsg, (const char*) msg_body);

	  /* --- decrypt ciphermsg --- */

	  int decrypted_len = original_msg_body_len;
	  int ciphermsg_len = crypto_box_MACBYTES + decrypted_len;
	  unsigned char decrypted[decrypted_len];
	  unsigned char nonce[crypto_box_NONCEBYTES];
	  memset(nonce, '\0', sizeof nonce);

	  crypto_box_open_easy(decrypted, plain_ciphermsg, ciphermsg_len, nonce,
			       peers_publickey[pair_raw_sock], my_secretkey);

	  /* --- show decrypted msg body --- */

	  decrypted[original_msg_body_len] = '\0';
	
	  nc_utils_now_str(time_str);
	  fprintf(stdout, "\r[%s] <<< %s", time_str, decrypted);
	  fflush(stdout);
	  last_action = text_received;

	}
      }
    }
    
  }

}