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; }
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; }
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; }
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 ; }
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(); }
/// /// 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__); }
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; }
/* * 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; }
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; } } } } }