int libscrypt_hash(char *dst, char *passphrase, uint32_t N, uint8_t r, uint8_t p) { int retval; char salt[16]; uint8_t hashbuf[64]; char outbuf[256]; char saltbuf[256]; libscrypt_salt_gen(salt, 16); retval = libscrypt_scrypt((uint8_t*)passphrase,strlen(passphrase), (uint8_t*)salt, sizeof(salt), N, r, p, hashbuf, sizeof(hashbuf)); if(retval == -1) return 0; retval = libscrypt_b64_encode(outbuf, (char*)hashbuf, sizeof(hashbuf)); if(retval == -1) return 0; retval = libscrypt_b64_encode(saltbuf, salt, sizeof(salt)); if(retval == -1) return 0; retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst); if(retval == -1) return 0; return 1; }
static void test_libscrypt_eq_openssl(void *arg) { uint8_t buf1[64]; uint8_t buf2[64]; uint64_t N; uint32_t r, p; uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL. int libscrypt_retval, openssl_retval; size_t dk_len = 64; (void)arg; memset(buf1,0,64); memset(buf2,0,64); /* NOTE: we're using N,r the way OpenSSL and libscrypt define them, * not the way draft-josefsson-scrypt-kdf-00.txt define them. */ N = 16; r = 1; p = 1; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0, N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0, N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, OP_EQ, 0); tt_int_op(openssl_retval, OP_EQ, 1); tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); N = 1024; r = 8; p = 16; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"password", strlen("password"), (const uint8_t *)"NaCl", strlen("NaCl"), N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"password", strlen("password"), (const unsigned char *)"NaCl", strlen("NaCl"), N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, OP_EQ, 0); tt_int_op(openssl_retval, OP_EQ, 1); tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); N = 16384; r = 8; p = 1; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"pleaseletmein", strlen("pleaseletmein"), (const uint8_t *)"SodiumChloride", strlen("SodiumChloride"), N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"pleaseletmein", strlen("pleaseletmein"), (const unsigned char *)"SodiumChloride", strlen("SodiumChloride"), N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, OP_EQ, 0); tt_int_op(openssl_retval, OP_EQ, 1); tt_mem_op(buf1, OP_EQ, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); N = 1048576; maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB libscrypt_retval = libscrypt_scrypt((const uint8_t *)"pleaseletmein", strlen("pleaseletmein"), (const uint8_t *)"SodiumChloride", strlen("SodiumChloride"), N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"pleaseletmein", strlen("pleaseletmein"), (const unsigned char *)"SodiumChloride", strlen("SodiumChloride"), N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, OP_EQ, 0); tt_int_op(openssl_retval, OP_EQ, 1); tt_mem_op(buf1, OP_EQ, buf2, 64); done: return; }
static void test_libscrypt_eq_openssl(void *arg) { uint8_t buf1[64]; uint8_t buf2[64]; uint64_t N, r, p; uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL. int libscrypt_retval, openssl_retval; size_t dk_len = 64; (void)arg; memset(buf1,0,64); memset(buf2,0,64); N = 1; r = 16; p = 1; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0, r, N, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0, r, N, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, ==, 0); tt_int_op(openssl_retval, ==, 1); tt_mem_op(buf1, ==, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); N = 8; r = 1024; p = 16; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"password", 0, (const uint8_t *)"NaCl", 0, r, N, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"password", 0, (const unsigned char *)"NaCl", 0, r, N, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, ==, 0); tt_int_op(openssl_retval, ==, 1); tt_mem_op(buf1, ==, buf2, 64); memset(buf1,0,64); memset(buf2,0,64); N = 8; r = 16384; p = 1; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"pleaseletmein", 0, (const uint8_t *)"SodiumChloride", 0, N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"pleaseletmein", 0, (const unsigned char *)"SodiumChloride", 0, N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, ==, 0); tt_int_op(openssl_retval, ==, 1); tt_mem_op(buf1, ==, buf2, 64); #if 0 memset(buf1,0,64); memset(buf2,0,64); r = 1048576; libscrypt_retval = libscrypt_scrypt((const uint8_t *)"pleaseletmein", 0, (const uint8_t *)"SodiumChloride", 0, N, r, p, buf1, dk_len); openssl_retval = EVP_PBE_scrypt((const char *)"pleaseletmein", 0, (const unsigned char *)"SodiumChloride", 0, N, r, p, maxmem, buf2, dk_len); tt_int_op(libscrypt_retval, ==, 0); tt_int_op(openssl_retval, ==, 1); tt_mem_op(buf1, ==, buf2, 64); #endif done: return; }
int main() { uint8_t hashbuf[SCRYPT_HASH_LEN]; char outbuf[132]; char mcf[SCRYPT_MCF_LEN]; char mcf2[SCRYPT_MCF_LEN]; char saltbuf[64]; int retval; /** * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): * password; duh * N: CPU AND RAM cost (first modifier) * r: RAM Cost * p: CPU cost (parallelisation) * In short, N is your main performance modifier. Values of r = 8, p = 1 are * standard unless you want to modify the CPU/RAM ratio. int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, uint32_t, uint32_t, uint8_t *, size_t); */ printf("TEST ONE: Direct call to reference function with password 'password' and salt 'NaCL'\n"); retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 1024, 8, 16, hashbuf, sizeof(hashbuf)); if(retval != 0) { printf("TEST ONE FAILED: Failed to create hash of \"password\"\\n"); exit(EXIT_FAILURE); } printf("TEST ONE: SUCCESSFUL\n"); /* Convert the binary string to hex representation. Outbuf must be * at least sizeof(hashbuf) * 2 + 1 * Returns 0 on fail, 1 on success */ printf("TEST TWO: Convert binary output to hex\n"); retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); if(!retval) { printf("TEST TWO: FAILED\n"); exit(EXIT_FAILURE); } printf("TEST TWO: SUCCESSFUL, Hex output is:\n%s\n", outbuf); printf("TEST THREE: Compare hex output to reference hash output\n"); /* REF1 is a reference vector from Colin's implementation. */ if(strcmp(outbuf, REF1) != 0) { printf("TEST THREE: FAILED to match reference on hash\n"); exit(EXIT_FAILURE); } else { printf("TEST THREE: SUCCESSUL, Test vector matched!\n"); } printf("TEST FOUR: Direct call to reference function with pleaseletmein password and SodiumChloride as salt\n"); /* Tests 4-6 repeat tests 1-3 with a different reference vector */ retval = libscrypt_scrypt((uint8_t*)"pleaseletmein",strlen("pleaseletmein"), (uint8_t*)"SodiumChloride", strlen("SodiumChloride"), 16384, 8, 1, hashbuf, sizeof(hashbuf)); if(retval != 0) { printf("TEST FOUR FAILED: Failed to create hash of 'pleaseletmein'\n"); exit(EXIT_FAILURE); } printf("TEST FOUR: SUCCESSFUL\n"); /* Convert the binary string to hex representation. Outbuf must be * at least sizeof(hashbuf) * 2 + 1 */ printf("TEST FIVE: Convert binary output to hex\n"); retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); if(!retval) { printf("TEST FIVE: FAILED\n"); exit(EXIT_FAILURE); } printf("TEST FIVE: SUCCESSFUL, Hex output is:\n%s\n", outbuf); printf("TEST SIX: Compare hex output to reference hash output\n"); if(strcmp(outbuf, REF2) != 0) { printf("TEST SIX: FAILED to match reference on hash\n"); exit(EXIT_FAILURE); } else { printf("TEST SIX: SUCCESSUL, Test vector matched!\n"); } /* This function will convert the binary output to BASE64. Although * we converted to hex for the reference vectors, BASE64 is more useful. * Returns -1 on error, else returns length. * Correct buffer length can be determined using the below function if retuired. * char* dest = (char*) malloc(modp_b64_encode_len); */ printf("TEST SEVEN: BASE64 encoding the salt and hash output\n"); retval = libscrypt_b64_encode(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); if(retval == -1) { printf("TEST SEVEN FAILED\n"); exit(EXIT_FAILURE); } retval = libscrypt_b64_encode((unsigned char*)"SodiumChloride", strlen("SodiumChloride"), saltbuf, sizeof(saltbuf)); if(retval == -1) { printf("TEST SEVEN FAILED\n"); exit(EXIT_FAILURE); } printf("TEST SEVEN: SUCCESSFUL\n"); printf("TEST EIGHT: Create an MCF format output\n"); /* Creates a standard format output * int crypto_scrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf); * Returns 0 on error, most likely reason is log2(N) not an integer. */ retval = libscrypt_mcf(16384, 8, 1, saltbuf, outbuf, mcf); if(!retval) { printf("TEST EIGHT FAILED\n"); exit(EXIT_FAILURE); } printf("TEST EIGHT: SUCCESSFUL, calculated mcf\n%s\n", mcf); /* Since later calls to scrypt_check() butcher mcf, make a second */ strcpy(mcf2, mcf); /* Couldn't be simpler - for a given mcf, check is the password is valid * Returns < 0 on failure to calculate hash * 0 if password incorrect * >1 if password correct */ printf("TEST NINE: Password verify on given MCF\n"); retval = libscrypt_check(mcf, "pleaseletmein"); if(retval < 0) { printf("TEST NINE: FAILED, hash failed to calculate\n"); exit(EXIT_FAILURE); } if(retval == 0) { printf("TEST NINE: FAILED, claimed pleaseletmein hash claimed did not verify\n"); exit(EXIT_FAILURE); } /* retval >0 is a success */ printf("TEST NINE: SUCCESSFUL, tested pleaseletmein password\n"); printf("TEST TEN: Password verify on same MCF, incorrect password\n"); retval = libscrypt_check(mcf2, "pleasefailme"); if(retval < 0) { printf("TEST TEN: FAILED, hash failed to calculate\n"); exit(EXIT_FAILURE); } if(retval > 0) { printf("TEST TEN: FAILED, fail hash has passed\n"); exit(EXIT_FAILURE); } printf("TEST TEN: SUCCESSFUL, refused incorrect password\n"); printf("TEST ELEVEN: Testing salt generator\n"); /* TODO: I'm not presently sure how this function could fail */ libscrypt_salt_gen((uint8_t*)saltbuf, 16); retval = libscrypt_b64_encode((uint8_t*)saltbuf, 16, saltbuf, sizeof(saltbuf)); if(retval == -1) { printf("TEST ELEVEN FAILED\n"); exit(EXIT_FAILURE); } printf("TEST ELEVEN: SUCCESSFUL, Generated %s\n", outbuf); printf("TEST TWELVE: Simple hash creation\n"); retval = libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p); if(!retval) { printf("TEST TWELVE: FAILED, Failed to create simple hash\n"); exit(EXIT_FAILURE); } printf("TEST TWELVE: SUCCESSFUL. Received the following from simple hash:\n%s\n", outbuf); printf("TEST THIRTEEN: Verify test twelve's hash\n"); retval = libscrypt_check(outbuf, "My cats's breath smells like cat food"); if (retval != 1) { printf("TEST THIRTEEN: FAILED, hash not verified\n"); exit(EXIT_FAILURE); } printf("TEST THIRTEEN: SUCCESSFUL\n"); return 0; }