int32_t cmtp_hash(uint32_t version, char * buffer_to_hash, uint32_t buffer_to_hash_length, unsigned char * salt, unsigned char * return_buffer, uint32_t return_buffer_length) { if (version==1) { if (return_buffer_length!=32) { perror("return_buffer_length of incorrect size"); print_to_log("return_buffer_length of incorrect size in cmtp_hash", LOG_ERR); return -1; } //do version 1 hash unsigned char * hash = calloc(1, 32); if (crypto_pwhash_scryptsalsa208sha256(hash, 32, buffer_to_hash, buffer_to_hash_length, salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { perror("crypto_pwhash_scryptsalsa208sha256 error in cmtp_hash"); print_to_log("crypto_pwhash_scryptsalsa208sha256 error in cmtp_hash", LOG_ERR); free(hash); return -1; } memcpy(return_buffer, hash, 32); free(hash); return 0; } //Incorrect version. Fail. return -1; }
/* Same as above, except with use the given salt for deterministic key derivation. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error) { if (!salt || !out_key || (!passphrase && pplength != 0)) { SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); return 0; } uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); uint8_t key[CRYPTO_SHARED_KEY_SIZE]; /* Derive a key from the password */ /* http://doc.libsodium.org/key_derivation/README.html */ /* note that, according to the documentation, a generic pwhash interface will be created * once the pwhash competition (https://password-hashing.net/) is over */ if (crypto_pwhash_scryptsalsa208sha256( key, sizeof(key), (char *)passkey, sizeof(passkey), salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE); SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); return 1; }
/* * Function: generate_key_nonce * ---------------------------- * Attempt to generate a key and nonce using the passphrase and the static salt * values. If there are any errors then return -1 otherwise return 0. */ result generate_key_nonce(unsigned char *key, unsigned char *nonce, char *passphrase) { char *key_salt = "wJDNGf7/Jrce41GTllX+Z4I0eHdva+IXFsYiD5Sg50M"; size_t r; r = crypto_pwhash_scryptsalsa208sha256( key, KEYBYTES, passphrase, strlen(passphrase), (unsigned char *)key_salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE); if (r != 0) { fprintf(stderr, "Unable to generate key from passprase.\n"); return FAIL; } randombytes_buf(nonce, NONCEBYTES); return SUCCESS; }
static void tv2(void) { static struct { const char *passwd_hex; size_t passwdlen; const char *salt_hex; size_t outlen; unsigned long long opslimit; size_t memlimit; } tests[] = { { "a347ae92bce9f80f6f595a4480fc9c2fe7e7d7148d371e9487d75f5c23008ffae0" "65577a928febd9b1973a5a95073acdbeb6a030cfc0d79caa2dc5cd011cef02c08d" "a232d76d52dfbca38ca8dcbd665b17d1665f7cf5fe59772ec909733b24de97d6f5" "8d220b20c60d7c07ec1fd93c52c31020300c6c1facd77937a597c7a6", 127, "5541fbc995d5c197ba290346d2c559dedf405cf97e5f95482143202f9e74f5c2", 155, 64, 1397645 }, { "a347ae92bce9f80f6f595a4480fc9c2fe7e7d7148d371e9487d75f5c23008ffae0" "65577a928febd9b1973a5a95073acdbeb6a030cfc0d79caa2dc5cd011cef02c08d" "a232d76d52dfbca38ca8dcbd665b17d1665f7cf5fe59772ec909733b24de97d6f5" "8d220b20c60d7c07ec1fd93c52c31020300c6c1facd77937a597c7a6", 127, "5541fbc995d5c197ba290346d2c559dedf405cf97e5f95482143202f9e74f5c2", 155, 32768, 1397645 }, }; char passwd[256]; unsigned char salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; unsigned char out[256]; char out_hex[256 * 2 + 1]; size_t i = 0U; do { sodium_hex2bin((unsigned char *)passwd, sizeof passwd, tests[i].passwd_hex, strlen(tests[i].passwd_hex), NULL, NULL, NULL); sodium_hex2bin(salt, sizeof salt, tests[i].salt_hex, strlen(tests[i].salt_hex), NULL, NULL, NULL); if (crypto_pwhash_scryptsalsa208sha256( out, (unsigned long long) tests[i].outlen, passwd, tests[i].passwdlen, (const unsigned char *) salt, tests[i].opslimit, tests[i].memlimit) != 0) { printf("pwhash failure\n"); } sodium_bin2hex(out_hex, sizeof out_hex, out, tests[i].outlen); printf("%s\n", out_hex); } while (++i < (sizeof tests) / (sizeof tests[0])); }
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; } }
static int generate(const char *pk_file, const char *sk_file, const char *comment) { char *pwd = xsodium_malloc(PASSWORDMAXBYTES); char *pwd2 = xsodium_malloc(PASSWORDMAXBYTES); SeckeyStruct *seckey_struct = xsodium_malloc(sizeof(SeckeyStruct)); PubkeyStruct *pubkey_struct = xsodium_malloc(sizeof(PubkeyStruct)); unsigned char *stream ; FILE *fp; randombytes_buf(seckey_struct->keynum_sk.keynum, sizeof seckey_struct->keynum_sk.keynum); crypto_sign_keypair(pubkey_struct->keynum_pk.pk, seckey_struct->keynum_sk.sk); memcpy(seckey_struct->sig_alg, SIGALG, sizeof seckey_struct->sig_alg); memcpy(seckey_struct->kdf_alg, KDFALG, sizeof seckey_struct->kdf_alg); memcpy(seckey_struct->chk_alg, CHKALG, sizeof seckey_struct->chk_alg); randombytes_buf(seckey_struct->kdf_salt, sizeof seckey_struct->kdf_salt); le64_store(seckey_struct->kdf_opslimit_le, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE); le64_store(seckey_struct->kdf_memlimit_le, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE); seckey_chk(seckey_struct->keynum_sk.chk, seckey_struct); memcpy(pubkey_struct->keynum_pk.keynum, seckey_struct->keynum_sk.keynum, sizeof pubkey_struct->keynum_pk.keynum); memcpy(pubkey_struct->sig_alg, SIGALG, sizeof pubkey_struct->sig_alg); puts("Please enter a password to protect the secret key.\n"); if (get_password(pwd, PASSWORDMAXBYTES, "Password: "******"Password (one more time): ") != 0) { exit_msg("get_password()"); } if (strcmp(pwd, pwd2) != 0) { exit_msg("Passwords don't match"); } printf("Deriving a key from the password in order to encrypt the secret key... "); fflush(stdout); stream = xsodium_malloc(sizeof seckey_struct->keynum_sk); if (crypto_pwhash_scryptsalsa208sha256 (stream, sizeof seckey_struct->keynum_sk, pwd, strlen(pwd), seckey_struct->kdf_salt, le64_load(seckey_struct->kdf_opslimit_le), le64_load(seckey_struct->kdf_memlimit_le)) != 0) { abort(); } sodium_free(pwd); sodium_free(pwd2); xor_buf((unsigned char *) (void *) &seckey_struct->keynum_sk, stream, sizeof seckey_struct->keynum_sk); sodium_free(stream); puts("done\n"); if ((fp = fopen_create_useronly(sk_file)) == NULL) { exit_err(sk_file); } xfprintf(fp, "%s%s\n", COMMENT_PREFIX, comment); xfput_b64(fp, (unsigned char *) (void *) seckey_struct, sizeof *seckey_struct); xfclose(fp); sodium_free(seckey_struct); if ((fp = fopen(pk_file, "w")) == NULL) { exit_err(pk_file); } xfprintf(fp, COMMENT_PREFIX "minisign public key %" PRIX64 "\n", le64_load(pubkey_struct->keynum_pk.keynum)); xfput_b64(fp, (unsigned char *) (void *) pubkey_struct, sizeof *pubkey_struct); xfclose(fp); printf("The secret key was saved as %s - Keep it secret!\n", sk_file); printf("The public key was saved as %s - That one can be public.\n\n", pk_file); puts("Files signed using this key pair can be verified with the following command:\n"); printf("minisign -Vm <file> -P "); xfput_b64(stdout, (unsigned char *) (void *) pubkey_struct, sizeof *pubkey_struct); puts(""); sodium_free(pubkey_struct); return 0; }
static SeckeyStruct * seckey_load(const char *sk_file) { char sk_comment[COMMENTMAXBYTES]; unsigned char chk[crypto_generichash_BYTES]; SeckeyStruct *seckey_struct; FILE *fp; char *pwd = xsodium_malloc(PASSWORDMAXBYTES); char *seckey_s; unsigned char *stream; size_t seckey_s_size; size_t seckey_struct_len; if ((fp = fopen(sk_file, "r")) == NULL) { exit_err(sk_file); } if (fgets(sk_comment, (int) sizeof sk_comment, fp) == NULL) { exit_err(sk_file); } sodium_memzero(sk_comment, sizeof sk_comment); seckey_s_size = B64_MAX_LEN_FROM_BIN_LEN(sizeof *seckey_struct) + 2U; seckey_s = xsodium_malloc(seckey_s_size); seckey_struct = xsodium_malloc(sizeof *seckey_struct); if (fgets(seckey_s, (int) seckey_s_size, fp) == NULL) { exit_err(sk_file); } trim(seckey_s); xfclose(fp); if (b64_to_bin((unsigned char *) (void *) seckey_struct, seckey_s, sizeof *seckey_struct, strlen(seckey_s), &seckey_struct_len) == NULL || seckey_struct_len != sizeof *seckey_struct) { exit_msg("base64 conversion failed"); } sodium_free(seckey_s); if (memcmp(seckey_struct->sig_alg, SIGALG, sizeof seckey_struct->sig_alg) != 0) { exit_msg("Unsupported signature algorithm"); } if (memcmp(seckey_struct->kdf_alg, KDFALG, sizeof seckey_struct->kdf_alg) != 0) { exit_msg("Unsupported key derivation function"); } if (memcmp(seckey_struct->chk_alg, CHKALG, sizeof seckey_struct->chk_alg) != 0) { exit_msg("Unsupported checksum function"); } if (get_password(pwd, PASSWORDMAXBYTES, "Password: "******"get_password()"); } printf("Deriving a key from the password and decrypting the secret key... "); fflush(stdout); stream = xsodium_malloc(sizeof seckey_struct->keynum_sk); if (crypto_pwhash_scryptsalsa208sha256 (stream, sizeof seckey_struct->keynum_sk, pwd, strlen(pwd), seckey_struct->kdf_salt, le64_load(seckey_struct->kdf_opslimit_le), le64_load(seckey_struct->kdf_memlimit_le)) != 0) { abort(); } sodium_free(pwd); xor_buf((unsigned char *) (void *) &seckey_struct->keynum_sk, stream, sizeof seckey_struct->keynum_sk); sodium_free(stream); puts("done\n"); seckey_chk(chk, seckey_struct); if (memcmp(chk, seckey_struct->keynum_sk.chk, sizeof chk) != 0) { exit_msg("Wrong password for that key"); } sodium_memzero(chk, sizeof chk); return seckey_struct; }
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; }
BOOL SodiumEncryptFile(LPTSTR password) { ULONG numread; BOOL bErrorFlag; HLOCAL hFileBuffer = NULL; HLOCAL hCipherBuffer = NULL; int nFilesz; // Retrieve file size if ((nFilesz = GetFileSize(hFileIn , 0)) == 0) { MessageBox(NULL, L"Cannot get filesize", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } hFileBuffer = LocalAlloc(LPTR, nFilesz * sizeof(BYTE)); if (!hFileBuffer) { MessageBox(NULL, L"Cannot allocate memory", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } // Read entire file into memory if (!ReadFile(hFileIn, hFileBuffer, nFilesz, &numread, NULL)) { MessageBox(NULL, L"Cannot read file into memory", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } // For now read byes must equal filesize assert(nFilesz == numread); // Wide password to multibyte password SIZE_T nConvChars; CHAR c_szPassword[100]; // This might not be enough wcstombs_s(&nConvChars, c_szPassword, password, wcslen(password) + 1); // DERIVE KEY BYTE salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; BYTE key[crypto_secretbox_KEYBYTES]; randombytes_buf(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); if (crypto_pwhash_scryptsalsa208sha256(key, crypto_secretbox_KEYBYTES, c_szPassword, strlen(c_szPassword), salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { MessageBox(NULL, L"Operation takes too much system resources", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } // ENC int nCiphersz = crypto_secretbox_MACBYTES + nFilesz; hCipherBuffer = LocalAlloc(LPTR, nCiphersz * sizeof(BYTE)); if (!hCipherBuffer) { MessageBox(NULL, L"Cannot allocate memory", L"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } BYTE nonce[crypto_secretbox_NONCEBYTES]; randombytes_buf(nonce, sizeof(nonce)); crypto_secretbox_easy((LPBYTE)hCipherBuffer, (LPBYTE)hFileBuffer, nFilesz, nonce, key); YENCFILE encFileStrct; memcpy(encFileStrct.cbSignature, pszSignature, MAX_SIGNATURE); memcpy(encFileStrct.cbNonce, nonce, crypto_secretbox_NONCEBYTES); memcpy(encFileStrct.cbPasswordSalt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); encFileStrct.rawSize = nFilesz; encFileStrct.algorithm = YC_SCRYPT_SALSA_POLY; encFileStrct.dwOps = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; encFileStrct.dwMemory = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; wcscat_s(szFile, MAX_PATH, L".yc"); // WRITE HANDLE hFileOut = CreateFile( szFile, // 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"Encryption error", MB_ICONERROR); bErrorFlag = FALSE; goto enc_exit_on_failure; } bErrorFlag = WriteFile( hFileOut, // Open file handle &encFileStrct, // Start of data to write sizeof(YENCFILE), // Number of bytes to write &numread, // Number of bytes that were written NULL); // No overlapped structure' if (!bErrorFlag) { MessageBox(NULL, L"Cannot write to file", L"Encryption error", MB_ICONERROR); goto enc_exit_on_failure; } bErrorFlag = WriteFile( hFileOut, // Open file handle hCipherBuffer, // Start of data to write nCiphersz, // Number of bytes to write &numread, // Number of bytes that were written NULL); // No overlapped structure if (!bErrorFlag) { MessageBox(NULL, L"Cannot write to file", L"Encryption error", MB_ICONERROR); goto enc_exit_on_failure; } CloseHandle(hFileOut); enc_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; }
static void tv(void) { static struct { const char *passwd_hex; size_t passwdlen; const char *salt_hex; size_t outlen; unsigned long long opslimit; size_t memlimit; } tests[] = { { "a347ae92bce9f80f6f595a4480fc9c2fe7e7d7148d371e9487d75f5c23008ffae0" "65577a928febd9b1973a5a95073acdbeb6a030cfc0d79caa2dc5cd011cef02c08d" "a232d76d52dfbca38ca8dcbd665b17d1665f7cf5fe59772ec909733b24de97d6f5" "8d220b20c60d7c07ec1fd93c52c31020300c6c1facd77937a597c7a6", 127, "5541fbc995d5c197ba290346d2c559dedf405cf97e5f95482143202f9e74f5c2", 155, 481326, 7256678 }, { "e125cee61c8cb7778d9e5ad0a6f5d978ce9f84de213a8556d9ffe202020ab4a6ed" "9074a4eb3416f9b168f137510f3a30b70b96cbfa219ff99f6c6eaffb15c06b60e0" "0cc2890277f0fd3c622115772f7048adaebed86e", 86, "f1192dd5dc2368b9cd421338b22433455ee0a3699f9379a08b9650ea2c126f0d", 250, 535778, 7849083 }, { "92263cbf6ac376499f68a4289d3bb59e5a22335eba63a32e6410249155b956b6a3" "b48d4a44906b18b897127300b375b8f834f1ceffc70880a885f47c33876717e392" "be57f7da3ae58da4fd1f43daa7e44bb82d3717af4319349c24cd31e46d295856b0" "441b6b289992a11ced1cc3bf3011604590244a3eb737ff221129215e4e4347f491" "5d41292b5173d196eb9add693be5319fdadc242906178bb6c0286c9b6ca6012746" "711f58c8c392016b2fdfc09c64f0f6b6ab7b", 183, "3b840e20e9555e9fb031c4ba1f1747ce25cc1d0ff664be676b9b4a90641ff194", 249, 311757, 7994791 }, { "027b6d8e8c8c474e9b69c7d9ed4f9971e8e1ce2f6ba95048414c3970f0f09b70e3" "b6c5ae05872b3d8678705b7d381829c351a5a9c88c233569b35d6b0b809df44b64" "51a9c273f1150e2ef8a0b5437eb701e373474cd44b97ef0248ebce2ca0400e1b53" "f3d86221eca3f18eb45b702b9172440f774a82cbf1f6f525df30a6e293c873cce6" "9bb078ed1f0d31e7f9b8062409f37f19f8550aae", 152, "eb2a3056a09ad2d7d7f975bcd707598f24cd32518cde3069f2e403b34bfee8a5", 5, 643464, 1397645 }, { "4a857e2ee8aa9b6056f2424e84d24a72473378906ee04a46cb05311502d5250b82" "ad86b83c8f20a23dbb74f6da60b0b6ecffd67134d45946ac8ebfb3064294bc097d" "43ced68642bfb8bbbdd0f50b30118f5e", 82, "39d82eef32010b8b79cc5ba88ed539fbaba741100f2edbeca7cc171ffeabf258", 190, 758010, 5432947 }, { "1845e375479537e9dd4f4486d5c91ac72775d66605eeb11a787b78a7745f1fd005" "2d526c67235dbae1b2a4d575a74cb551c8e9096c593a497aee74ba3047d911358e" "de57bc27c9ea1829824348daaab606217cc931dcb6627787bd6e4e5854f0e8", 97, "3ee91a805aa62cfbe8dce29a2d9a44373a5006f4a4ce24022aca9cecb29d1473", 212, 233177, 13101817 }, { "c7b09aec680e7b42fedd7fc792e78b2f6c1bea8f4a884320b648f81e8cf515e8ba" "9dcfb11d43c4aae114c1734aa69ca82d44998365db9c93744fa28b63fd16000e82" "61cbbe083e7e2da1e5f696bde0834fe53146d7e0e35e7de9920d041f5a5621aabe" "02da3e2b09b405b77937efef3197bd5772e41fdb73fb5294478e45208063b5f58e" "089dbeb6d6342a909c1307b3fff5fe2cf4da56bdae50848f", 156, "039c056d933b475032777edbaffac50f143f64c123329ed9cf59e3b65d3f43b6", 178, 234753, 4886999 }, { "8f3a06e2fd8711350a517bb12e31f3d3423e8dc0bb14aac8240fca0995938d59bb" "37bd0a7dfc9c9cc0705684b46612e8c8b1d6655fb0f9887562bb9899791a0250d1" "320f945eda48cdc20c233f40a5bb0a7e3ac5ad7250ce684f68fc0b8c9633bfd75a" "ad116525af7bdcdbbdb4e00ab163fd4df08f243f12557e", 122, "90631f686a8c3dbc0703ffa353bc1fdf35774568ac62406f98a13ed8f47595fd", 55, 695191, 15738350 }, { "b540beb016a5366524d4605156493f9874514a5aa58818cd0c6dfffaa9e90205f1" "7b", 34, "44071f6d181561670bda728d43fb79b443bb805afdebaf98622b5165e01b15fb", 231, 78652, 6631659 }, { "a14975c26c088755a8b715ff2528d647cd343987fcf4aa25e7194a8417fb2b4b3f" "7268da9f3182b4cfb22d138b2749d673a47ecc7525dd15a0a3c66046971784bb63" "d7eae24cc84f2631712075a10e10a96b0e0ee67c43e01c423cb9c44e5371017e9c" "496956b632158da3fe12addecb88912e6759bc37f9af2f45af72c5cae3b179ffb6" "76a697de6ebe45cd4c16d4a9d642d29ddc0186a0a48cb6cd62bfc3dd229d313b30" "1560971e740e2cf1f99a9a090a5b283f35475057e96d7064e2e0fc81984591068d" "55a3b4169f22cccb0745a2689407ea1901a0a766eb99", 220, "3d968b2752b8838431165059319f3ff8910b7b8ecb54ea01d3f54769e9d98daf", 167, 717248, 10784179 }, }; char passwd[256]; unsigned char salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; unsigned char out[256]; char out_hex[256 * 2 + 1]; size_t i = 0U; do { sodium_hex2bin((unsigned char *) passwd, sizeof passwd, tests[i].passwd_hex, strlen(tests[i].passwd_hex), NULL, NULL, NULL); sodium_hex2bin(salt, sizeof salt, tests[i].salt_hex, strlen(tests[i].salt_hex), NULL, NULL, NULL); if (crypto_pwhash_scryptsalsa208sha256( out, (unsigned long long) tests[i].outlen, passwd, tests[i].passwdlen, (const unsigned char *) salt, tests[i].opslimit, tests[i].memlimit) != 0) { printf("pwhash failure\n"); } sodium_bin2hex(out_hex, sizeof out_hex, out, tests[i].outlen); printf("%s\n", out_hex); } while (++i < (sizeof tests) / (sizeof tests[0])); }
int _tmain(int argc, _TCHAR* argv[]) { if (sodium_init() == -1) { _tprintf(_T("Could not initialize cryptography subsystem!\n")); return 1; } if (argc < 3) { _tprintf(_T("usage: cryptfile [-d] [-o <outfile>] <password> <file>\n")); _tprintf(_T("where\n")); _tprintf(_T("\t-o <outfile> filename for non inplace encryption\n")); _tprintf(_T("\t-d decrypt file\n")); return 1; } bool bDecrypt = false; bool bUseTempFile = true; TCHAR szSourceFile[MAX_PATH]; TCHAR szTargetFile[MAX_PATH]; for (int i = 1; i < argc - 2; i++) { if (_tcscmp(_T("-d"), argv[i]) == 0) bDecrypt = true; if (_tcscmp(_T("-o"), argv[i]) == 0) { _tcscpy_s(szTargetFile, MAX_PATH, argv[i + 1]); bUseTempFile = false; } } if (bUseTempFile) { _tcscpy_s(szTargetFile, MAX_PATH, argv[argc - 1]); _tcscpy_s(szSourceFile, MAX_PATH, argv[argc - 1]); _tcscat_s(szSourceFile, MAX_PATH, _T(".tmp")); if (!::MoveFile(szTargetFile, szSourceFile)) { _tprintf(_T("File access denied: %s\n"), szTargetFile); return 1; } } else { _tcscpy_s(szSourceFile, MAX_PATH, argv[argc - 1]); } unsigned char pKey[crypto_stream_KEYBYTES]; unsigned char pNonce[crypto_stream_NONCEBYTES]; unsigned char pSalt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; // generate simple password salt (unique for this application) for (size_t i = 2; i < crypto_pwhash_scryptsalsa208sha256_SALTBYTES; i++) pSalt[i] = (i * 2) & 0xFF; pSalt[0] = 'C'; pSalt[1] = 'S'; // generate key (derived from password) crypto_pwhash_scryptsalsa208sha256( pKey, sizeof(pKey), reinterpret_cast<const char*>(argv[argc - 2]), _tcslen(argv[argc - 2]) * sizeof(TCHAR), pSalt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE); HANDLE hSourceFile = ::CreateFile(szSourceFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSourceFile == INVALID_HANDLE_VALUE) { _tprintf(_T("File access denied: %s\n"), szSourceFile); return 1; } HANDLE hTargetFile = ::CreateFile(szTargetFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hTargetFile == INVALID_HANDLE_VALUE) { ::CloseHandle(hSourceFile); _tprintf(_T("File access denied: %s\n"), szTargetFile); return 1; } BYTE *pData = new BYTE[CHUNK_SIZE]; DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; if (bDecrypt) { // load file unique number for decryption ::ReadFile(hSourceFile, pNonce, sizeof(pNonce), &dwBytesRead, NULL); } else { // generate number to used once (unique for each file) randombytes_buf(pNonce, sizeof(pNonce)); ::WriteFile(hTargetFile, pNonce, sizeof(pNonce), &dwBytesWritten, NULL); } while (::ReadFile(hSourceFile, pData, CHUNK_SIZE, &dwBytesRead, NULL) && dwBytesRead > 0) { crypto_stream_xor(pData, pData, dwBytesRead, pNonce, pKey); // inplace ::WriteFile(hTargetFile, pData, dwBytesRead, &dwBytesWritten, NULL); } delete[] pData; ::CloseHandle(hTargetFile); ::CloseHandle(hSourceFile); if (bUseTempFile) ::DeleteFile(szSourceFile); #ifdef _DEBUG _tsystem(_T("pause")); #endif return 0; }