int main(void) { #define MAXLEN 64 unsigned char in[MAXLEN], out[crypto_generichash_BYTES_MAX], k[crypto_generichash_KEYBYTES_MAX]; size_t h, i, j; for (h = 0; h < crypto_generichash_KEYBYTES_MAX; ++h) k[h] = h; for (i = 0; i < MAXLEN; ++i) { in[i] = i; crypto_generichash(out, 1 + i % crypto_generichash_BYTES_MAX, in, i, k, 1 + i % crypto_generichash_KEYBYTES_MAX); for (j = 0; j < 1 + i % crypto_generichash_BYTES_MAX; ++j) { printf("%02x", (unsigned int)out[j]); } printf("\n"); } assert(crypto_generichash(out, 0U, in, sizeof in, k, sizeof k) == -1); assert(crypto_generichash(out, crypto_generichash_BYTES_MAX + 1U, in, sizeof in, k, sizeof k) == -1); assert(crypto_generichash(out, sizeof out, in, sizeof in, k, crypto_generichash_KEYBYTES_MAX + 1U) == -1); assert(crypto_generichash_bytes_min() > 0U); assert(crypto_generichash_bytes_max() > 0U); assert(crypto_generichash_bytes() > 0U); assert(crypto_generichash_bytes() >= crypto_generichash_bytes_min()); assert(crypto_generichash_bytes() <= crypto_generichash_bytes_max()); assert(crypto_generichash_keybytes_min() > 0U); assert(crypto_generichash_keybytes_max() > 0U); assert(crypto_generichash_keybytes() > 0U); assert(crypto_generichash_keybytes() >= crypto_generichash_keybytes_min()); assert(crypto_generichash_keybytes() <= crypto_generichash_keybytes_max()); assert(strcmp(crypto_generichash_primitive(), "blake2b") == 0); assert(crypto_generichash_bytes_min() == crypto_generichash_blake2b_bytes_min()); assert(crypto_generichash_bytes_max() == crypto_generichash_blake2b_bytes_max()); assert(crypto_generichash_bytes() == crypto_generichash_blake2b_bytes()); assert(crypto_generichash_keybytes_min() == crypto_generichash_blake2b_keybytes_min()); assert(crypto_generichash_keybytes_max() == crypto_generichash_blake2b_keybytes_max()); assert(crypto_generichash_keybytes() == crypto_generichash_blake2b_keybytes()); assert(crypto_generichash_blake2b_saltbytes() > 0U); assert(crypto_generichash_blake2b_personalbytes() > 0U); return 0; }
int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], unsigned char sk[crypto_kx_SECRETKEYBYTES], const unsigned char seed[crypto_kx_SEEDBYTES]) { crypto_generichash(sk, crypto_kx_SECRETKEYBYTES, seed, crypto_kx_SEEDBYTES, NULL, 0); return crypto_scalarmult_base(pk, sk); }
int crypto_init(const char *password) { if (sodium_init() == -1) { return 1; } randombytes_set_implementation(&randombytes_salsa20_implementation); randombytes_stir(); return crypto_generichash(secret_key, sizeof secret_key, (uint8_t*)password, strlen(password), NULL, 0); }
QString Profile::avatarPath(const QString &ownerId, bool forceUnencrypted) { if (password.isEmpty() || forceUnencrypted) return Settings::getInstance().getSettingsDirPath() + "avatars/" + ownerId + ".png"; QByteArray idData = ownerId.toUtf8(); constexpr int hashSize = TOX_PUBLIC_KEY_SIZE; // As long as an unencrypted hash static_assert(hashSize >= crypto_generichash_BYTES_MIN && hashSize <= crypto_generichash_BYTES_MAX, "Hash size not supported by libsodium"); QByteArray hash(hashSize, 0); crypto_generichash((uint8_t*)hash.data(), hashSize, (uint8_t*)idData.data(), idData.size(), nullptr, 0); return Settings::getInstance().getSettingsDirPath() + "avatars/" + hash.toHex().toUpper() + ".png"; }
int main () { unsigned char hash[crypto_generichash_BYTES + 1] = {0}; unsigned char minhash[crypto_generichash_BYTES_MIN + 1] = {0}; unsigned char maxhash[crypto_generichash_BYTES_MAX + 1] = {0}; unsigned char key[crypto_generichash_KEYBYTES] = "123456789 123456789 123456789 12"; if (sodium_init() != 0) { return -1; } size_t min_hex_maxlen = crypto_generichash_BYTES_MIN * 2 + 1; size_t std_hex_maxlen = crypto_generichash_BYTES * 2 + 1; size_t max_hex_maxlen = crypto_generichash_BYTES_MAX * 2 + 1; unsigned char min_hex[min_hex_maxlen]; unsigned char std_hex[std_hex_maxlen]; unsigned char max_hex[max_hex_maxlen]; printf ("text: %s\n", MESSAGE); crypto_generichash(minhash, crypto_generichash_BYTES_MIN, MESSAGE, MESSAGE_LEN, NULL, 0); sodium_bin2hex (min_hex, min_hex_maxlen, minhash, crypto_generichash_BYTES_MIN); printf ("min hash: %s\n", min_hex); printf ("hash length is %d\n", strlen (minhash)); crypto_generichash(hash, crypto_generichash_BYTES, MESSAGE, MESSAGE_LEN, NULL, 0); sodium_bin2hex (std_hex, std_hex_maxlen, hash, crypto_generichash_BYTES); printf ("\nstd hash: %s\n", std_hex); printf ("hash length is %d\n", strlen (hash)); crypto_generichash(maxhash, crypto_generichash_BYTES_MAX, MESSAGE, MESSAGE_LEN, NULL, 0); sodium_bin2hex (max_hex, max_hex_maxlen, maxhash, crypto_generichash_BYTES_MAX); printf ("\nmax hash: %s\n", max_hex); printf ("hash length is %d\n", strlen (maxhash)); crypto_generichash(minhash, crypto_generichash_BYTES_MIN, MESSAGE, MESSAGE_LEN, key, sizeof key); sodium_bin2hex (min_hex, min_hex_maxlen, minhash, crypto_generichash_BYTES_MIN); printf ("\nkeyed min hash: %s\n", min_hex); crypto_generichash(hash, crypto_generichash_BYTES, MESSAGE, MESSAGE_LEN, key, sizeof key); sodium_bin2hex (std_hex, std_hex_maxlen, hash, crypto_generichash_BYTES); printf ("keyed std hash: %s\n", std_hex); crypto_generichash(maxhash, crypto_generichash_BYTES_MAX, MESSAGE, MESSAGE_LEN, key, sizeof key); sodium_bin2hex (max_hex, max_hex_maxlen, maxhash, crypto_generichash_BYTES_MAX); printf ("keyed max hash: %s\n", max_hex); return 0; }
/* Function is used to generate a unique string used as a filename for incomming mail. unique_file_name_buffer should be 86 bytes for full encode of the 64 byte hash (4/3 * 64) = 85.333 @param Salt used to mix up the hashing. @param Pointer to a buffer where the unique file name will be written. @return Length of the string written to unique_file_name_buffer */ int generate_unique_string(int salt, char * unique_file_name_buffer) { struct timespec time_used_in_string_creation; clock_gettime(CLOCK_REALTIME, &time_used_in_string_creation); char meat_and_potatoes[24]; memset(meat_and_potatoes, 0, sizeof(meat_and_potatoes)); memcpy(meat_and_potatoes, &time_used_in_string_creation.tv_sec, sizeof(time_used_in_string_creation.tv_sec)); memcpy(meat_and_potatoes+sizeof(time_used_in_string_creation.tv_sec), &salt, sizeof(salt)); memcpy(meat_and_potatoes+sizeof(time_used_in_string_creation.tv_sec)+sizeof(salt), &time_used_in_string_creation.tv_nsec, sizeof(time_used_in_string_creation.tv_nsec)); unsigned char hash[64]; //64 bytes because hash has a fixed size output crypto_generichash(hash, sizeof(hash), (const unsigned char *)meat_and_potatoes, sizeof(meat_and_potatoes),NULL, 0); int unique_file_name_length = base64_encode((char *)hash, sizeof(hash), unique_file_name_buffer, sizeof(unique_file_name_buffer), (char *)filesystem_safe_base64_string, 64); return unique_file_name_length; }
static void mm_generichash(void) { crypto_generichash_state st; unsigned char *h, *h2; unsigned char *k; unsigned char *m; size_t hlen; size_t klen; size_t mlen; size_t l1, l2; int i; for (i = 0; i < MAX_ITER; i++) { mlen = randombytes_uniform(MAXLEN); m = (unsigned char *) sodium_malloc(mlen); klen = randombytes_uniform(crypto_generichash_KEYBYTES_MAX - crypto_generichash_KEYBYTES_MIN + 1U) + crypto_generichash_KEYBYTES_MIN; k = (unsigned char *) sodium_malloc(klen); hlen = randombytes_uniform(crypto_generichash_BYTES_MAX - crypto_generichash_BYTES_MIN + 1U) + crypto_generichash_BYTES_MIN; h = (unsigned char *) sodium_malloc(hlen); h2 = (unsigned char *) sodium_malloc(hlen); randombytes_buf(k, klen); randombytes_buf(m, mlen); crypto_generichash_init(&st, k, klen, hlen); l1 = randombytes_uniform(mlen); l2 = randombytes_uniform(mlen - l1); crypto_generichash_update(&st, m, l1); crypto_generichash_update(&st, m + l1, l2); crypto_generichash_update(&st, m + l1 + l2, mlen - l1 - l2); crypto_generichash_final(&st, h, hlen); crypto_generichash(h2, hlen, m, mlen, k, klen); assert(memcmp(h, h2, hlen) == 0); sodium_free(h2); sodium_free(h); sodium_free(k); sodium_free(m); } }
byte* pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_t noncelen) { byte *dk = smalloc(64); byte *salt = malloc(crypto_pwhash_scryptsalsa208sha256_SALTBYTES); crypto_generichash(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES, nonce, noncelen, NULL, 0); int status = crypto_pwhash_scryptsalsa208sha256(dk, 64, passwd, passwdlen, salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE); ucfree(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); if (status == 0) { return dk; } else { fatal(ptx, "crypto_pwhash_scryptsalsa208sha256() failed\n"); return NULL; } }
int enc_init(const char *pass, const char *method) { int m = TABLE; if (method != NULL) { for (m = TABLE; m < CIPHER_NUM; m++) { if (strcmp(method, supported_ciphers[m]) == 0) { break; } } if (m >= CIPHER_NUM) { LOGE("Invalid cipher name: %s, use table instead", method); m = TABLE; } } if (m == TABLE) { enc_table_init(pass); } else { enc_key_init(m, pass); } crypto_generichash(auth_key, ONETIMEAUTH_KEYBYTES, (uint8_t *)pass, strlen(pass), NULL, 0); return m; }
int crypto_set_password(const char *password, unsigned long long password_len) { return crypto_generichash(key, sizeof key, (unsigned char *)password, password_len, NULL, 0); }
int get_key_from_password(unsigned char *k, size_t k_bytes, int confirm) { #define SALT_PREFIX "Personalization for this example" #define SALT_PREFIX_LEN 32 char email[1024U]; char pwd2[1024U]; char pwd[1024U]; unsigned char salt[SALT_PREFIX_LEN + 1024U]; unsigned char h0[56]; size_t email_len; size_t i; int ret; assert(strlen(SALT_PREFIX) == SALT_PREFIX_LEN); if (get_line(email, sizeof email, "Email: ") != 0) { return -1; } email_len = strlen(email); for (i = 0U; i < email_len; i++) { email[i] = (char) tolower((unsigned char) email[i]); } if (get_password(pwd, sizeof pwd, "Password: "******"Password (one more time): ") != 0) { sodium_memzero(pwd, sizeof pwd); sodium_memzero(pwd2, sizeof pwd2); return -1; } if (strcmp(pwd, pwd2) != 0) { sodium_memzero(pwd, sizeof pwd); sodium_memzero(pwd2, sizeof pwd2); safe_write(2, "Passwords don't match\n", sizeof "Passwords don't match\n" - 1U, -1); return -1; } sodium_memzero(pwd2, sizeof pwd2); } safe_write(2, "Deriving key from password... ", sizeof "Deriving key from password... " - 1U, -1); crypto_generichash(h0, sizeof h0, (const unsigned char *) pwd, strlen(pwd), NULL, 0); sodium_memzero(pwd, sizeof pwd); memcpy(salt + SALT_PREFIX_LEN, email, email_len); sodium_memzero(email, sizeof email); ret = crypto_pwhash_scryptsalsa208sha256_ll(h0, sizeof h0, salt, SALT_PREFIX_LEN + email_len, 1ULL << 18, 1U, 8U, k, k_bytes); sodium_memzero(h0, sizeof h0); sodium_memzero(salt, sizeof salt); safe_write(2, "done\n", sizeof "done\n" - 1U, -1); return ret; }
int crypto_generickey(uint8_t *out, size_t outlen, uint8_t *in, size_t inlen, uint8_t *key, size_t keylen) { return crypto_generichash(out, outlen, in, inlen, key, keylen); }
int32_t mail_responder(uint32_t socket) { #ifdef DEBUG printf("Entering MAIL subroutine\n"); #endif /*DEBUG*/ //Allocate general variables //Allocate primary buffers and counters char source_account_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t source_account_length = 0; char source_domain_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t source_domain_length = 0; char dest_account_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t dest_account_length = 0; char dest_domain_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t dest_domain_length = 0; uint32_t version = 0; uint32_t attachment_count = 0; uint64_t message_length = 0; uint64_t log_length = 0; //Generate unique file from current time and current FD //Get time with nanosecond resolution (or so they say) struct timespec time_for_file; clock_gettime(CLOCK_REALTIME, &time_for_file); //Mix time with FD and hash //We are hashing two ints and a long, so char meat_and_potatoes[24] = {0}; //memset(meat_and_potatoes, 0, sizeof(meat_and_potatoes)); memcpy(meat_and_potatoes, &time_for_file.tv_sec, sizeof(time_for_file.tv_sec)); memcpy(meat_and_potatoes+sizeof(time_for_file.tv_sec), &socket, sizeof(socket)); memcpy(meat_and_potatoes+sizeof(time_for_file.tv_sec)+sizeof(socket), &time_for_file.tv_nsec, sizeof(time_for_file.tv_nsec)); unsigned char hash[64]; //64 bytes because hash has a fixed size output crypto_generichash(hash, sizeof(hash), (const unsigned char *)meat_and_potatoes, sizeof(meat_and_potatoes),NULL, 0); //Get file ready to write //TODO needs to be /mail/user/unique_file_name char unique_file_name[129] = {0}; //char base64_username[341] = {0}; char unique_file_location[522] = {0}; //TODO Need to check if user is part of this domain. If not the file location should be some temporary storage. //unique_file_name_length is not currently used. Should be fine. uint32_t unique_file_name_length = base64_encode((char *)hash, sizeof(hash), unique_file_name, sizeof(unique_file_name), (char *)filesystem_safe_base64_string, 64); if (unique_file_name_length<=0) { perror("base64_encode. unique_file_name failed to be created"); print_to_log("base64_encode failed to create a unique_file_name.", LOG_ERR); return -1; } //uint32_t base64_username_length = base64_encode((char *)dest_account_buffer, strlen(dest_account_buffer), base64_username, strlen(base64_username), (char *)filesystem_safe_base64_string, 64); //Read primary routing and processing information //First read in fixed length fields if (read_n_bytes(socket, (unsigned char *)&version, 4)!=4) { perror("read_n_bytes version"); print_to_log("Read error while reading crypto type", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&attachment_count, 4)!=4) { perror("read_n_bytes attachment_count"); print_to_log("Read error while reading attachment count", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&log_length, 8)!=8) { perror("read_n_bytes log_length"); print_to_log("Read error while reading message length", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&message_length, 8)!=8) { perror("read_n_bytes message_length"); print_to_log("Read error while reading message length", LOG_ERR); return -1; } //Read in account and domain info if ((dest_account_length=read_until(socket, (unsigned char *)dest_account_buffer, sizeof(dest_account_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading dest_account_buffer", LOG_ERR); return -1; } if (snprintf(unique_file_location, sizeof(unique_file_location), "%s%s%s%s", "/mail/", dest_account_buffer, "/" , unique_file_name)<0) { perror("snprintf"); print_to_log("snprintf failed to create a new file string. Cannot write message out",LOG_ERR); return -1; } write_to_file((char *)&version, 4, unique_file_location); version = be32toh(version); write_to_file((char *)&attachment_count, 4, unique_file_location); attachment_count = be32toh(attachment_count); write_to_file((char *)&log_length, 8, unique_file_location); log_length = be64toh(log_length); write_to_file((char *)&message_length, 8, unique_file_location); message_length = be64toh(message_length); #ifdef DEBUG printf("Writing mail to %s\n", unique_file_location); printf("Log length = %ld\n", log_length); printf("Version = %d\n", version); printf("Attachment count = %d\n", attachment_count); printf("Message length = %ld\n", message_length); #endif /*DEBUG*/ write_to_file(dest_account_buffer, dest_account_length, unique_file_location); #ifdef DEBUG printf("dest_account_length = %d\n", dest_account_length); #endif /*DEBUG*/ if ((dest_domain_length=read_until(socket, (unsigned char *)dest_domain_buffer, sizeof(dest_domain_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading dest_domain_buffer", LOG_ERR); return -1; } write_to_file(dest_domain_buffer, dest_domain_length, unique_file_location); #ifdef DEBUG printf("dest_domain_length = %d\n", dest_domain_length); #endif /*DEBUG*/ //Check if this is the destination if((strcmp(dest_domain_buffer, home_domain)!=0)&&(forward==0)) { //Send delivery failure, close connection, clean up and return. unsigned char signature_of_DELIVERYFAILURE[crypto_sign_BYTES] = {0}; unsigned char write_buffer[sizeof(network_crypto_version)+sizeof(server_public_key)+sizeof(signature_of_DELIVERYFAILURE)+2]; crypto_sign_detached(signature_of_DELIVERYFAILURE, NULL, signature_of_DELIVERYFAILURE, sizeof(signature_of_DELIVERYFAILURE), server_private_key); memcpy(write_buffer, &network_crypto_version, sizeof(network_crypto_version)); memcpy(write_buffer+sizeof(network_crypto_version), cmtp_reply_DELIVERYFAILURE, sizeof(cmtp_reply_DELIVERYFAILURE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_DELIVERYFAILURE), &signature_of_DELIVERYFAILURE, sizeof(signature_of_DELIVERYFAILURE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_DELIVERYFAILURE)+sizeof(signature_of_DELIVERYFAILURE), &termination_char, sizeof(termination_char)); write(socket, write_buffer, sizeof(write_buffer)); } if ((source_account_length=read_until(socket, (unsigned char *)source_account_buffer, sizeof(source_account_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading source_account_buffer", LOG_ERR); return -1; } write_to_file(source_account_buffer, source_account_length, unique_file_location); #ifdef DEBUG printf("source_account_length = %d\n", source_account_length); #endif /*DEBUG*/ if ((source_domain_length=read_until(socket, (unsigned char *)source_domain_buffer, sizeof(source_domain_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading source_domain_buffer", LOG_ERR); return -1; } write_to_file(source_domain_buffer, source_domain_length, unique_file_location); #ifdef DEBUG printf("source_domain_length = %d\n", source_domain_length); #endif /*DEBUG*/ //This completes the read of the header //uint64_t numeric_message_length = be64toh(*(uint64_t*)(&(message_length[0]))); //uint64_t numeric_log_length = be64toh(*(uint64_t*)(&(log_length[0]))); char temp_byte[1] = {0}; //Read log for (uint64_t i = 0; i<log_length; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } //Read message body for (uint64_t i = 0; i<message_length; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } #ifdef DEBUG printf("Message body finished. Moving to attachment handling.\n"); #endif /*DEBUG*/ //Read for attachment //uint32_t numeric_attachment_count = be32toh(*(uint32_t*)(&(attachment_count[0]))); temp_byte[0] = 0; for (uint64_t i = 0; i<attachment_count; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } #ifdef DEBUG printf("Mail destin for %s\n", dest_domain_buffer); printf("Server domain is %s\n", home_domain); #endif /*DEBUG*/ //Destination cases if ((memcmp(dest_domain_buffer, home_domain, dest_domain_length)==0)&&(memcmp(dest_account_buffer,"",1))==0) { #ifdef DEBUG printf("Devlivered mail is for server. Begin processing.\n"); #endif /*DEBUG*/ print_to_log("Mail has arrived for the server. Processing.",LOG_INFO); //Destination is this domain and for the server } else if ((memcmp(dest_domain_buffer, home_domain, dest_domain_length)==0)) { #ifdef DEBUG printf("Devlivered mail is for a user on this domain. Store.\n"); #endif /*DEBUG*/ print_to_log("Mail has arrived for a user on this domain. Storing.",LOG_INFO); //Destination is for a user at this domain } else { #ifdef DEBUG printf("Devlivered mail is not destined for this domain. Forward to %s\n", dest_domain_buffer); #endif /*DEBUG*/ print_to_log("Mail has arrived for another domain. Forwarding.",LOG_INFO); forwardMessage(unique_file_location, dest_domain_buffer); //Destination is on the web. Forward message. } #ifdef DEBUG printf("Mail section complete. Returning to mail loop.\n"); #endif /*DEBUG*/ return 0; }