int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], const char * const passwd, unsigned long long passwdlen) { char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; escrypt_local_t escrypt_local; int ret = -1; if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { return -1; } if (escrypt_init_local(&escrypt_local) != 0) { return -1; /* LCOV_EXCL_LINE */ } memset(wanted, 0, sizeof wanted); if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) str, (uint8_t *) wanted, sizeof wanted) == NULL) { escrypt_free_local(&escrypt_local); return -1; } escrypt_free_local(&escrypt_local); ret = sodium_memcmp(wanted, str, sizeof wanted); sodium_memzero(wanted, sizeof wanted); return ret; }
int crypto_auth_hmacsha256_verify(const unsigned char *h,const unsigned char *in,unsigned long long inlen,const unsigned char *k) { unsigned char correct[32]; crypto_auth_hmacsha256(correct,in,inlen,k); return crypto_verify_32(h,correct) | (-(h == correct)) | sodium_memcmp(correct,h,32); }
int crypto_auth_hmacsha512_verify(const unsigned char *h, const unsigned char *in, unsigned long long inlen, const unsigned char *k) { unsigned char correct[64]; crypto_auth_hmacsha512(correct,in,inlen,k); return crypto_verify_64(h,correct) | (-(h == correct)) | sodium_memcmp(correct,h,64); }
int dfcrypt_decrypt( const dfcrypt_state_t *state, const unsigned char *ctxt, size_t ctxt_len_bytes, const unsigned char *message_number, unsigned char *ptxt_out ) { const unsigned char *salt = ctxt; const unsigned char *nonce = ctxt + DFCRYPT_INTERNAL_SALT_BYTES; const unsigned char *encrypted = nonce + crypto_stream_chacha20_NONCEBYTES; const unsigned char *ciphertext_mac = ctxt + ctxt_len_bytes - DFCRYPT_INTERNAL_MAC_BYTES; unsigned char keys[DFCRYPT_INTERNAL_AKEY_BYTES + DFCRYPT_INTERNAL_EKEY_BYTES]; const unsigned char *akey = keys; const unsigned char *ekey = keys + DFCRYPT_INTERNAL_AKEY_BYTES; unsigned char computed_mac[DFCRYPT_INTERNAL_MAC_BYTES]; /* Derive the authentication and encryption keys. */ assert(sizeof(keys) == 64); crypto_generichash_blake2b_salt_personal( keys, /* output */ sizeof(keys), /* output length */ state->appseed, /* input */ state->appseed_length, /* input length */ state->key, /* key */ DFCRYPT_KEY_BYTES, /* key length */ salt, /* salt */ message_number /* personalization (can be NULL) */ ); /* Re-compute the MAC. */ crypto_generichash_blake2b( computed_mac, /* output */ DFCRYPT_INTERNAL_MAC_BYTES, /* output length */ ctxt, /* input */ ctxt_len_bytes - DFCRYPT_INTERNAL_MAC_BYTES, /* input length */ akey, /* key */ DFCRYPT_INTERNAL_AKEY_BYTES /* key length */ ); /* Check the MAC. */ if (sodium_memcmp(computed_mac, ciphertext_mac, DFCRYPT_INTERNAL_MAC_BYTES) != 0) { return -1; } /* Decrypt the plaintext. */ crypto_stream_chacha20_xor( ptxt_out, /* output */ encrypted, /* input */ ctxt_len_bytes - DFCRYPT_CIPHERTEXT_GROWTH, /* input length */ nonce, /* nonce */ ekey /* key */ ); return 0; }
int main(void) { unsigned char buf1[1000]; unsigned char buf2[1000]; randombytes(buf1, sizeof buf1); memcpy(buf2, buf1, sizeof buf2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, 0U); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, sizeof buf1 / 2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf ("%d\n", sodium_memcmp(buf1, buf2, 0U)); sodium_memzero(buf2, sizeof buf2 / 2); printf ("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); return 0; }
int main(void) { sodium_init(); //create random key unsigned char key[crypto_secretbox_KEYBYTES]; randombytes_buf(key, crypto_secretbox_KEYBYTES); //print key printf("Key (%i Bytes):\n", crypto_secretbox_KEYBYTES); print_hex(key, crypto_secretbox_KEYBYTES, 30); putchar('\n'); //encrypted message unsigned char ciphertext[500]; //TODO don't use fixed size buffer here size_t ciphertext_length = 0; int status; status = encrypt(ciphertext, &ciphertext_length, key); if (status != 0) { fprintf(stderr, "ERROR: Failed to encrypt message. (%i)\n", status); return status; } //print the ciphertext printf("Ciphertext (packet, %zu Bytes):\n", ciphertext_length); print_hex(ciphertext, ciphertext_length, 30); putchar('\n'); puts("NOW DECRYPT -------------------------------------------------------------------\n"); unsigned char header[ciphertext_length]; size_t header_length = 0; status = extract_header_without_verifying( header, &header_length, ciphertext, ciphertext_length); if (status != 0) { fprintf(stderr, "ERROR: Failed to extract header from packet. (%i)\n", status); return status; } //print header printf("Received header (%zu Bytes):\n%s\n\n", header_length, header); //check header if (sodium_memcmp(header, HEADER, sizeof(HEADER)) != 0) { fprintf(stderr, "ERROR: Headers aren't the same!\n"); return -1; } return EXIT_SUCCESS; }
int main(void) { unsigned char buf1[1000]; unsigned char buf2[1000]; char buf3[33]; randombytes(buf1, sizeof buf1); memcpy(buf2, buf1, sizeof buf2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, 0U); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, sizeof buf1 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%d\n", sodium_memcmp(buf1, buf2, 0U)); sodium_memzero(buf2, sizeof buf2 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%s\n", sodium_bin2hex(buf3, 33U, (const unsigned char *) "0123456789ABCDEF", 16U)); return 0; }
/* * Helper function that checks if a buffer is <none> * (filled with zeroes), and does so without introducing * side channels, especially timing side channels. */ bool is_none( const unsigned char * const buffer, const size_t length) { //TODO: Find better implementation that //doesn't create an additional array. I don't //do that currently because I haven't enough //confidence that I'm not introducing any side //channels. //fill a buffer with zeroes unsigned char none[length]; sodium_memzero(none, sizeof(none)); return 0 == sodium_memcmp(none, buffer, sizeof(none)); }
int crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *m, unsigned long long mlen, const unsigned char *pk) { crypto_hash_sha512_state hs; unsigned char h[64]; unsigned char rcheck[32]; unsigned int i; unsigned char d = 0; ge_p3 A; ge_p2 R; #ifdef ED25519_PREVENT_MALLEABILITY if (crypto_sign_check_S_lt_l(sig + 32) != 0) { return -1; } #else if (sig[63] & 224) { return -1; } #endif if (ge_frombytes_negate_vartime(&A, pk) != 0) { return -1; } for (i = 0; i < 32; ++i) { d |= pk[i]; } if (d == 0) { return -1; } crypto_hash_sha512_init(&hs); crypto_hash_sha512_update(&hs, sig, 32); crypto_hash_sha512_update(&hs, pk, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, h); sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, sig + 32); ge_tobytes(rcheck, &R); return crypto_verify_32(rcheck, sig) | (-(rcheck - sig == 0)) | sodium_memcmp(sig, rcheck, 32); }
ClientConfiguration::BackupData ClientConfiguration::fromBackup(QString const& backup, QString const& password) { QByteArray decodedBase32 = Base32::decodeBase32Sequence(backup); if (decodedBase32.size() != BACKUP_DECODED_BYTES) { throw IllegalArgumentException() << "Invalid Backup: Size of decoded Backup String is incorrect (" << decodedBase32.size() << " Bytes instead of " << BACKUP_DECODED_BYTES << " Bytes)."; } unsigned char encryptionKey[BACKUP_ENCRYPTION_KEY_BYTES]; sodium_memzero(encryptionKey, BACKUP_ENCRYPTION_KEY_BYTES); // The pointer to the base32-decoded Backup unsigned char* decodedBase32Ptr = reinterpret_cast<unsigned char*>(decodedBase32.data()); // The Salt used in the PBKDF2 Key Derivation process is embedded in the first 8 bytes of the Backup. QByteArray password8Bit = password.toUtf8(); PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), decodedBase32Ptr, BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, encryptionKey); unsigned char nonceBytes[crypto_stream_NONCEBYTES]; sodium_memzero(nonceBytes, crypto_stream_NONCEBYTES); crypto_stream_xor(&decodedBase32Ptr[BACKUP_SALT_BYTES], &decodedBase32Ptr[BACKUP_SALT_BYTES], BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, nonceBytes, encryptionKey); // The last two bytes of the Backup contain the truncated SHA-256 Hash over the identity and its Private Key. unsigned char controlHash[crypto_hash_sha256_BYTES]; sodium_memzero(controlHash, crypto_hash_sha256_BYTES); crypto_hash_sha256(controlHash, &(decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES); if (sodium_memcmp(&(decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES]), controlHash, BACKUP_HASH_BYTES) != 0) { throw IllegalArgumentException() << "Decryption of Backup failed: Invalid Control Hash (" << controlHash[0] << controlHash[1] << " vs. " << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES] << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + 1] << ")."; } unsigned char derivedPublicKey[PROTO_KEY_LENGTH_BYTES]; crypto_scalarmult_base(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); KeyPair kp = KeyPair::fromArrays(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); QString identityString(QByteArray(reinterpret_cast<char*>(&decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES)); if (!isValidIdentity(identityString)) { throw IllegalArgumentException() << "Invalid ClientConfiguration: Decryption of Backup failed: Not a valid Identity."; } return BackupData(ContactId(identityString.toUtf8()), kp); }
int main(void) { sodium_init(); int status; //create Alice's keypair unsigned char alice_public_key[crypto_box_PUBLICKEYBYTES]; unsigned char alice_private_key[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( alice_public_key, alice_private_key, "Alice", ""); if (status != 0) { sodium_memzero(alice_private_key, crypto_box_SECRETKEYBYTES); return status; } //create Bob's keypair unsigned char bob_public_key[crypto_box_PUBLICKEYBYTES]; unsigned char bob_private_key[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( bob_public_key, bob_private_key, "Bob", ""); if (status != 0) { sodium_memzero(alice_private_key, crypto_box_SECRETKEYBYTES); sodium_memzero(bob_private_key, crypto_box_SECRETKEYBYTES); return status; } //Diffie Hellman on Alice's side unsigned char alice_shared_secret[crypto_generichash_BYTES]; status = diffie_hellman( alice_shared_secret, alice_private_key, alice_public_key, bob_public_key, true); sodium_memzero(alice_private_key, crypto_box_SECRETKEYBYTES); if (status != 0) { fprintf(stderr, "ERROR: Diffie Hellman with Alice's private key failed. (%i)\n", status); sodium_memzero(bob_private_key, crypto_box_SECRETKEYBYTES); sodium_memzero(alice_shared_secret, crypto_generichash_BYTES); return status; } //print Alice's shared secret printf("Alice's shared secret ECDH(A_priv, B_pub) (%i Bytes):\n", crypto_generichash_BYTES); print_hex(alice_shared_secret, crypto_generichash_BYTES, 30); putchar('\n'); //Diffie Hellman on Bob's side unsigned char bob_shared_secret[crypto_generichash_BYTES]; status = diffie_hellman( bob_shared_secret, bob_private_key, bob_public_key, alice_public_key, false); sodium_memzero(bob_private_key, crypto_box_SECRETKEYBYTES); if (status != 0) { fprintf(stderr, "ERROR: Diffie Hellman with Bob's private key failed. (%i)\n", status); sodium_memzero(alice_shared_secret, crypto_generichash_BYTES); sodium_memzero(bob_shared_secret, crypto_generichash_BYTES); return status; } //print Bob's shared secret printf("Bob's shared secret ECDH(B_priv, A_pub) (%i Bytes):\n", crypto_generichash_BYTES); print_hex(bob_shared_secret, crypto_generichash_BYTES, 30); putchar('\n'); //compare both shared secrets status = sodium_memcmp(alice_shared_secret, bob_shared_secret, crypto_generichash_BYTES); sodium_memzero(alice_shared_secret, crypto_generichash_BYTES); sodium_memzero(bob_shared_secret, crypto_generichash_BYTES); if (status != 0) { fprintf(stderr, "ERROR: Diffie Hellman didn't produce the same shared secret. (%i)\n", status); return status; } printf("Both shared secrets match!\n"); return EXIT_SUCCESS; }
int macaroon_memcmp(const void* data1, const void* data2, size_t data_sz) { return sodium_memcmp(data1, data2, data_sz); }
int main(void) { unsigned char buf1[1000]; unsigned char buf2[1000]; char buf3[33]; unsigned char buf4[4]; unsigned char nonce[24]; char nonce_hex[49]; const char *hex; const char *hex_end; size_t bin_len; int i; randombytes_buf(buf1, sizeof buf1); memcpy(buf2, buf1, sizeof buf2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, 0U); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); sodium_memzero(buf1, sizeof buf1 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%d\n", sodium_memcmp(buf1, buf2, 0U)); sodium_memzero(buf2, sizeof buf2 / 2); printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1)); printf("%s\n", sodium_bin2hex(buf3, 33U, (const unsigned char *)"0123456789ABCDEF", 16U)); hex = "Cafe : 6942"; sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, &hex_end); printf("%lu:%02x%02x%02x%02x\n", (unsigned long)bin_len, buf4[0], buf4[1], buf4[2], buf4[3]); printf("dt1: %ld\n", (long) (hex_end - hex)); hex = "Cafe : 6942"; sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, NULL); printf("%lu:%02x%02x%02x%02x\n", (unsigned long)bin_len, buf4[2], buf4[3], buf4[2], buf4[3]); hex = "deadbeef"; if (sodium_hex2bin(buf1, 1U, hex, 8U, NULL, &bin_len, &hex_end) != -1) { printf("sodium_hex2bin() overflow not detected\n"); } printf("dt2: %ld\n", (long) (hex_end - hex)); hex = "de:ad:be:eff"; if (sodium_hex2bin(buf1, 4U, hex, 12U, ":", &bin_len, &hex_end) != -1) { printf("sodium_hex2bin() with an odd input length and a short output buffer\n"); } printf("dt3: %ld\n", (long) (hex_end - hex)); hex = "de:ad:be:eff"; if (sodium_hex2bin(buf1, sizeof buf1, hex, 12U, ":", &bin_len, &hex_end) != 0) { printf("sodium_hex2bin() with an odd input length\n"); } printf("dt4: %ld\n", (long) (hex_end - hex)); hex = "de:ad:be:eff"; if (sodium_hex2bin(buf1, sizeof buf1, hex, 13U, ":", &bin_len, &hex_end) != 0) { printf("sodium_hex2bin() with an odd input length\n"); } printf("dt5: %ld\n", (long) (hex_end - hex)); memset(nonce, 0, sizeof nonce); sodium_increment(nonce, sizeof nonce); printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex, nonce, sizeof nonce)); memset(nonce, 255, sizeof nonce); sodium_increment(nonce, sizeof nonce); printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex, nonce, sizeof nonce)); nonce[1] = 1U; sodium_increment(nonce, sizeof nonce); printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex, nonce, sizeof nonce)); nonce[1] = 0U; sodium_increment(nonce, sizeof nonce); printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex, nonce, sizeof nonce)); nonce[0] = 255U; nonce[2] = 255U; sodium_increment(nonce, sizeof nonce); printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex, nonce, sizeof nonce)); for (i = 0; i < 1000; i++) { bin_len = (size_t) randombytes_uniform(sizeof buf1); randombytes_buf(buf1, bin_len); randombytes_buf(buf2, bin_len); if (memcmp(buf1, buf2, bin_len) * sodium_compare(buf1, buf2, bin_len) < 0) { printf("sodium_compare() failure with length=%u\n", (unsigned int) bin_len); } memcpy(buf1, buf2, bin_len); if (sodium_compare(buf1, buf2, bin_len)) { printf("sodium_compare() equality failure with length=%u\n", (unsigned int) bin_len); } } return 0; }
int main(void) { sodium_init(); //create ephemeral key unsigned char our_public_ephemeral_key[crypto_box_PUBLICKEYBYTES]; randombytes_buf(our_public_ephemeral_key, sizeof(our_public_ephemeral_key)); printf("Our public ephemeral key (%zi Bytes):\n", sizeof(our_public_ephemeral_key)); print_hex(our_public_ephemeral_key, sizeof(our_public_ephemeral_key), 30); //message numbers uint32_t message_number = 2; uint32_t previous_message_number = 10; printf("Message number: %u\n", message_number); printf("Previous message number: %u\n", previous_message_number); putchar('\n'); //create the header unsigned char header[crypto_box_PUBLICKEYBYTES + 8]; header_construct( header, our_public_ephemeral_key, message_number, previous_message_number); //print the header printf("Header (%zi Bytes):\n", sizeof(header)); print_hex(header, sizeof(header), 30); putchar('\n'); //get data back out of the header again unsigned char extracted_public_ephemeral_key[crypto_box_PUBLICKEYBYTES]; uint32_t extracted_message_number; uint32_t extracted_previous_message_number; header_extract( header, extracted_public_ephemeral_key, &extracted_message_number, &extracted_previous_message_number); printf("Extracted public ephemeral key (%zi Bytes):\n", sizeof(extracted_public_ephemeral_key)); print_hex(extracted_public_ephemeral_key, sizeof(extracted_public_ephemeral_key), 30); printf("Extracted message number: %u\n", extracted_message_number); printf("Extracted previous message number: %u\n", extracted_previous_message_number); putchar('\n'); //compare them if (sodium_memcmp(our_public_ephemeral_key, extracted_public_ephemeral_key, sizeof(our_public_ephemeral_key)) != 0) { fprintf(stderr, "ERROR: Public ephemeral keys don't match.\n"); return EXIT_FAILURE; } printf("Public ephemeral keys match.\n"); if (message_number != extracted_message_number) { fprintf(stderr, "ERROR: Message numbers don't match.\n"); return EXIT_FAILURE; } printf("Message numbers match.\n"); if (previous_message_number != extracted_previous_message_number) { fprintf(stderr, "ERROR: Message numbers don't match.\n"); return EXIT_FAILURE; } printf("Previous message numbers match.\n"); return EXIT_SUCCESS; }
int main(void) { sodium_init(); int status; //create Alice's identity keypair unsigned char alice_public_identity[crypto_box_PUBLICKEYBYTES]; unsigned char alice_private_identity[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( alice_public_identity, alice_private_identity, "Alice", "identity"); if (status != 0) { sodium_memzero(alice_private_identity, sizeof(alice_private_identity)); return status; } //create Alice's ephemeral keypair unsigned char alice_public_ephemeral[crypto_box_PUBLICKEYBYTES]; unsigned char alice_private_ephemeral[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( alice_public_ephemeral, alice_private_ephemeral, "Alice", "ephemeral"); if (status != 0) { sodium_memzero(alice_private_identity, sizeof(alice_private_identity)); sodium_memzero(alice_private_ephemeral, sizeof(alice_private_ephemeral)); return status; } //create Bob's identity keypair unsigned char bob_public_identity[crypto_box_PUBLICKEYBYTES]; unsigned char bob_private_identity[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( bob_public_identity, bob_private_identity, "Bob", "identity"); if (status != 0) { sodium_memzero(alice_private_identity, sizeof(alice_private_identity)); sodium_memzero(alice_private_ephemeral, sizeof(alice_private_ephemeral)); sodium_memzero(bob_private_identity, sizeof(bob_private_identity)); return status; } //create Bob's ephemeral keypair unsigned char bob_public_ephemeral[crypto_box_PUBLICKEYBYTES]; unsigned char bob_private_ephemeral[crypto_box_SECRETKEYBYTES]; status = generate_and_print_keypair( bob_public_ephemeral, bob_private_ephemeral, "Bob", "ephemeral"); if (status != 0) { sodium_memzero(alice_private_identity, sizeof(alice_private_identity)); sodium_memzero(alice_private_ephemeral, sizeof(alice_private_ephemeral)); sodium_memzero(bob_private_identity, sizeof(bob_private_identity)); sodium_memzero(bob_private_ephemeral, sizeof(bob_private_ephemeral)); return status; } //derive Alice's initial root and chain key unsigned char alice_root_key[crypto_secretbox_KEYBYTES]; unsigned char alice_send_chain_key[crypto_secretbox_KEYBYTES]; unsigned char alice_receive_chain_key[crypto_secretbox_KEYBYTES]; unsigned char alice_send_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char alice_receive_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char alice_next_send_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char alice_next_receive_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; status = derive_initial_root_chain_and_header_keys( alice_root_key, alice_send_chain_key, alice_receive_chain_key, alice_send_header_key, alice_receive_header_key, alice_next_send_header_key, alice_next_receive_header_key, alice_private_identity, alice_public_identity, bob_public_identity, alice_private_ephemeral, alice_public_ephemeral, bob_public_ephemeral, true); sodium_memzero(alice_private_identity, sizeof(alice_private_identity)); sodium_memzero(alice_private_ephemeral, sizeof(alice_private_ephemeral)); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive Alice's initial root and chain key. (%i)\n", status); sodium_memzero(alice_root_key, sizeof(alice_root_key)); sodium_memzero(alice_send_chain_key, sizeof(alice_send_chain_key)); sodium_memzero(alice_receive_chain_key, sizeof(alice_receive_chain_key)); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_private_identity, sizeof(bob_private_identity)); sodium_memzero(bob_private_ephemeral, sizeof(bob_private_ephemeral)); return status; } //print Alice's initial root and chain key printf("Alice's initial root key (%zi Bytes):\n", sizeof(alice_root_key)); print_hex(alice_root_key, sizeof(alice_root_key), 30); putchar('\n'); printf("Alice's initial send chain key (%zi Bytes):\n", sizeof(alice_send_chain_key)); print_hex(alice_send_chain_key, sizeof(alice_send_chain_key), 30); putchar('\n'); printf("Alice's initial receive chain key (%zi Bytes):\n", sizeof(alice_receive_chain_key)); print_hex(alice_receive_chain_key, sizeof(alice_receive_chain_key), 30); putchar('\n'); printf("Alice's initial send header key (%zi Bytes):\n", sizeof(alice_send_header_key)); print_hex(alice_send_header_key, sizeof(alice_send_header_key), 30); putchar('\n'); printf("Alice's initial receive header key (%zi Bytes):\n", sizeof(alice_receive_header_key)); print_hex(alice_receive_header_key, sizeof(alice_receive_header_key), 30); printf("Alice's initial next send header key (%zi Bytes):\n", sizeof(alice_next_send_header_key)); print_hex(alice_next_send_header_key, sizeof(alice_next_send_header_key), 30); putchar('\n'); printf("Alice's initial next receive header key (%zi Bytes):\n", sizeof(alice_next_receive_header_key)); print_hex(alice_next_receive_header_key, sizeof(alice_next_receive_header_key), 30); putchar('\n'); //derive Bob's initial root and chain key unsigned char bob_root_key[crypto_secretbox_KEYBYTES]; unsigned char bob_send_chain_key[crypto_secretbox_KEYBYTES]; unsigned char bob_receive_chain_key[crypto_secretbox_KEYBYTES]; unsigned char bob_send_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char bob_receive_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char bob_next_send_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; unsigned char bob_next_receive_header_key[crypto_aead_chacha20poly1305_KEYBYTES]; status = derive_initial_root_chain_and_header_keys( bob_root_key, bob_send_chain_key, bob_receive_chain_key, bob_send_header_key, bob_receive_header_key, bob_next_send_header_key, bob_next_receive_header_key, bob_private_identity, bob_public_identity, alice_public_identity, bob_private_ephemeral, bob_public_ephemeral, alice_public_ephemeral, false); sodium_memzero(bob_private_identity, sizeof(bob_private_identity)); sodium_memzero(bob_private_ephemeral, sizeof(bob_private_ephemeral)); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive Bob's initial root and chain key. (%i)", status); sodium_memzero(alice_root_key, sizeof(alice_root_key)); sodium_memzero(alice_send_chain_key, sizeof(alice_send_chain_key)); sodium_memzero(alice_receive_chain_key, sizeof(alice_receive_chain_key)); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_root_key, sizeof(bob_root_key)); sodium_memzero(bob_send_chain_key, sizeof(bob_send_chain_key)); sodium_memzero(bob_receive_chain_key, sizeof(bob_receive_chain_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return status; } //print Bob's initial root and chain key printf("Bob's initial root key (%zi Bytes):\n", sizeof(bob_root_key)); print_hex(bob_root_key, sizeof(bob_root_key), 30); putchar('\n'); printf("Bob's initial send chain key (%zi Bytes):\n", sizeof(bob_send_chain_key)); print_hex(bob_send_chain_key, sizeof(bob_send_chain_key), 30); putchar('\n'); printf("Bob's initial receive chain key (%zi Bytes):\n", sizeof(bob_receive_chain_key)); print_hex(bob_receive_chain_key, sizeof(bob_receive_chain_key), 30); putchar('\n'); printf("Bob's initial send header key (%zi Bytes):\n", sizeof(bob_send_header_key)); print_hex(bob_send_header_key, sizeof(bob_send_header_key), 30); putchar('\n'); printf("Bob's initial receive header key (%zi Bytes):\n", sizeof(bob_receive_header_key)); print_hex(bob_receive_header_key, sizeof(bob_receive_header_key), 30); printf("Bob's initial next send header key (%zi Bytes):\n", sizeof(bob_next_send_header_key)); print_hex(bob_next_send_header_key, sizeof(bob_next_send_header_key), 30); putchar('\n'); printf("Bob's initial next receive header key (%zi Bytes):\n", sizeof(bob_next_receive_header_key)); print_hex(bob_next_receive_header_key, sizeof(bob_next_receive_header_key), 30); putchar('\n'); //compare Alice's and Bob's initial root key if (sodium_memcmp(alice_root_key, bob_root_key, sizeof(alice_root_key)) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial root keys don't match.\n"); sodium_memzero(alice_root_key, sizeof(alice_root_key)); sodium_memzero(alice_send_chain_key, sizeof(alice_send_chain_key)); sodium_memzero(alice_receive_chain_key, sizeof(alice_receive_chain_key)); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_root_key, sizeof(bob_root_key)); sodium_memzero(bob_send_chain_key, sizeof(bob_send_chain_key)); sodium_memzero(bob_receive_chain_key, sizeof(bob_receive_chain_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's and Bob's initial root keys match.\n"); sodium_memzero(alice_root_key, sizeof(alice_root_key)); sodium_memzero(bob_root_key, sizeof(bob_root_key)); //compare Alice's and Bob's initial chain keys if (sodium_memcmp(alice_send_chain_key, bob_receive_chain_key, sizeof(alice_send_chain_key)) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial chain keys don't match.\n"); sodium_memzero(alice_send_chain_key, sizeof(alice_send_chain_key)); sodium_memzero(alice_receive_chain_key, sizeof(alice_receive_chain_key)); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_send_chain_key, sizeof(bob_send_chain_key)); sodium_memzero(bob_receive_chain_key, sizeof(bob_receive_chain_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's and Bob's initial chain keys match.\n"); sodium_memzero(alice_send_chain_key, sizeof(alice_send_chain_key)); sodium_memzero(bob_receive_chain_key, sizeof(bob_receive_chain_key)); if (sodium_memcmp(alice_receive_chain_key, bob_send_chain_key, sizeof(alice_receive_chain_key)) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial chain keys don't match.\n"); sodium_memzero(alice_receive_chain_key, sizeof(alice_receive_chain_key)); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_send_chain_key, sizeof(bob_send_chain_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's and Bob's initial chain keys match.\n"); //compare Alice's and Bob's initial header keys 1/2 if (sodium_memcmp(alice_send_header_key, bob_receive_header_key, sizeof(alice_send_header_key)) != 0) { fprintf(stderr, "ERROR: Alice's initial send and Bob's initial receive header keys don't match.\n"); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's initial send and Bob's initial receive header keys match.\n"); sodium_memzero(alice_send_header_key, sizeof(alice_send_header_key)); sodium_memzero(bob_receive_header_key, sizeof(bob_receive_header_key)); //compare Alice's and Bob's initial header keys 2/2 if (sodium_memcmp(alice_receive_header_key, bob_send_header_key, sizeof(alice_receive_header_key)) != 0) { fprintf(stderr, "ERROR: Alice's initial receive and Bob's initial send header keys don't match.\n"); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's initial receive and Bob's initial send header keys match.\n"); sodium_memzero(alice_receive_header_key, sizeof(alice_receive_header_key)); sodium_memzero(bob_send_header_key, sizeof(bob_send_header_key)); //compare Alice's and Bob's initial next header keys 1/2 if (sodium_memcmp(alice_next_send_header_key, bob_next_receive_header_key, sizeof(alice_next_send_header_key)) != 0) { fprintf(stderr, "ERROR: Alice's initial next send and Bob's initial next receive header keys don't match.\n"); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); return -10; } printf("Alice's initial next send and Bob's initial next receive header keys match.\n"); sodium_memzero(alice_next_send_header_key, sizeof(alice_next_send_header_key)); sodium_memzero(bob_next_receive_header_key, sizeof(bob_next_receive_header_key)); //compare Alice's and Bob's initial next header keys 2/2 if (sodium_memcmp(alice_next_receive_header_key, bob_next_send_header_key, sizeof(alice_next_receive_header_key)) != 0) { fprintf(stderr, "ERROR: Alice's initial next receive and Bob's initial next send header keys don't match.\n"); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); return -10; } printf("Alice's initial next receive and Bob's initial next send header keys match.\n"); sodium_memzero(alice_next_receive_header_key, sizeof(alice_next_receive_header_key)); sodium_memzero(bob_next_send_header_key, sizeof(bob_next_send_header_key)); return EXIT_SUCCESS; }
BOOL SodiumDecryptFile(LPTSTR password) { ULONG numread; BOOL bErrorFlag; HLOCAL hFileBuffer = NULL; HLOCAL hCipherBuffer = NULL; YENCFILE encFileStrct; if (SetFilePointer(hFileIn, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { MessageBox(NULL, L"Cannot set file pointer", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } if (!ReadFile(hFileIn, &encFileStrct, sizeof(YENCFILE), &numread, NULL)) { MessageBox(NULL, L"Cannot read file into memory", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } if (sodium_memcmp(encFileStrct.cbSignature, pszSignature, MAX_SIGNATURE)) { MessageBox(NULL, L"This is not an encrypted file", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } if (encFileStrct.algorithm != YC_SCRYPT_SALSA_POLY) { MessageBox(NULL, L"Encryption method not available", L"Decryption error", MB_ICONEXCLAMATION); bErrorFlag = FALSE; goto dec_exit_on_failure; } hCipherBuffer = LocalAlloc(LPTR, (encFileStrct.rawSize + crypto_secretbox_MACBYTES) * sizeof(BYTE)); if (!hCipherBuffer) { MessageBox(NULL, L"Cannot allocate memory", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } if (!ReadFile(hFileIn, hCipherBuffer, encFileStrct.rawSize + crypto_secretbox_MACBYTES, &numread, NULL)) { MessageBox(NULL, L"Cannot read file into memory", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } // For now read byes must equal filesize assert((encFileStrct.rawSize + crypto_secretbox_MACBYTES) == numread); // Wide password to multibyte password size_t nConvChars; char c_szPassword[100]; //TODO This might not be enough wcstombs_s(&nConvChars, c_szPassword, password, wcslen(password) + 1); // DERIVE KEY BYTE key[crypto_secretbox_KEYBYTES]; if (crypto_pwhash_scryptsalsa208sha256(key, crypto_secretbox_KEYBYTES, c_szPassword, strlen(c_szPassword), encFileStrct.cbPasswordSalt, encFileStrct.dwOps, encFileStrct.dwMemory) != 0) { MessageBox(NULL, L"Operation takes too much system resources", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } hFileBuffer = LocalAlloc(LPTR, encFileStrct.rawSize * sizeof(char)); if (!hFileBuffer) { MessageBox(NULL, L"Cannot allocate memory", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } if (crypto_secretbox_open_easy((LPBYTE)hFileBuffer, (LPBYTE)hCipherBuffer, encFileStrct.rawSize + crypto_secretbox_MACBYTES, encFileStrct.cbNonce, key) != 0) { MessageBox(NULL, L"Decryption failed, please try again", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } LPCWSTR szOriginalFileName = fileNameStripExt(szFile); // WRITE HANDLE hFileOut = CreateFile( szOriginalFileName, // Name of the write GENERIC_WRITE, // Open for writing 0, // Do not share NULL, // Default security CREATE_NEW, // Create new file only FILE_ATTRIBUTE_NORMAL, // Normal file NULL); // No attr. template if (hFileOut == INVALID_HANDLE_VALUE) { MessageBox(NULL, L"Cannot open file", L"Decryption error", MB_ICONERROR); bErrorFlag = FALSE; goto dec_exit_on_failure; } bErrorFlag = WriteFile( hFileOut, // Open file handle hFileBuffer, // Start of data to write encFileStrct.rawSize, // Number of bytes to write &numread, // Number of bytes that were written NULL); // No overlapped structure' CloseHandle(hFileOut); dec_exit_on_failure: // Override sensitive in memory sodium_memzero(password, wcslen(password) * sizeof(TCHAR)); sodium_memzero(c_szPassword, strlen(c_szPassword) * sizeof(BYTE)); sodium_memzero(key, crypto_secretbox_KEYBYTES); LocalFree(hFileBuffer); LocalFree(hCipherBuffer); return bErrorFlag; }
int main(void) { unsigned char *v16, *v16x; unsigned char *v32, *v32x; unsigned char *v64, *v64x; uint32_t r; uint8_t o; int i; v16 = (unsigned char *) sodium_malloc(16); v16x = (unsigned char *) sodium_malloc(16); v32 = (unsigned char *) sodium_malloc(32); v32x = (unsigned char *) sodium_malloc(32); v64 = (unsigned char *) sodium_malloc(64); v64x = (unsigned char *) sodium_malloc(64); for (i = 0; i < 10000; i++) { randombytes_buf(v16, 16); randombytes_buf(v32, 32); randombytes_buf(v64, 64); memcpy(v16x, v16, 16); memcpy(v32x, v32, 32); memcpy(v64x, v64, 64); if (crypto_verify_16(v16, v16x) != 0 || crypto_verify_32(v32, v32x) != 0 || crypto_verify_64(v64, v64x) != 0 || sodium_memcmp(v16, v16x, 16) != 0 || sodium_memcmp(v32, v32x, 32) != 0 || sodium_memcmp(v64, v64x, 64) != 0) { printf("Failed\n"); } } printf("OK\n"); for (i = 0; i < 100000; i++) { r = randombytes_random(); o = (uint8_t) randombytes_random(); if (o == 0) { continue; } v16x[r & 15U] ^= o; v32x[r & 31U] ^= o; v64x[r & 63U] ^= o; if (crypto_verify_16(v16, v16x) != -1 || crypto_verify_32(v32, v32x) != -1 || crypto_verify_64(v64, v64x) != -1 || sodium_memcmp(v16, v16x, 16) != -1 || sodium_memcmp(v32, v32x, 32) != -1 || sodium_memcmp(v64, v64x, 64) != -1) { printf("Failed\n"); } v16x[r & 15U] ^= o; v32x[r & 31U] ^= o; v64x[r & 63U] ^= o; } printf("OK\n"); assert(crypto_verify_16_bytes() == 16U); assert(crypto_verify_32_bytes() == 32U); assert(crypto_verify_64_bytes() == 64U); sodium_free(v16); sodium_free(v16x); sodium_free(v32); sodium_free(v32x); sodium_free(v64); sodium_free(v64x); return 0; }