std::string BCryptHashFunction::compute(const std::string& msg, const std::string& salt) const { //#ifdef __APPLE__ char setting[32]; char c_salt[16]; std::strncpy(c_salt, salt.c_str(), 16); if (salt.length() < 16) std::memset(c_salt + salt.length(), 'A', 16 - salt.length()); if (!crypt_gensalt_rn("$2y$", count_, c_salt, 16, setting, 32)) { std::perror("crypt_gen_salt_rn"); throw std::runtime_error("bcrypt() gensalt internal error"); } else { char result[64]; std::cout<<"setting "<<setting<<std::endl; if (!crypt_rn(msg.c_str(), setting, result, 64)) { std::perror("crypt_rn"); throw std::runtime_error("bcrypt() internal error"); } return result; } //#else // std::string md5Salt = "$1$" + salt; // return crypt(msg.c_str(), md5Salt.c_str()); //#endif }
static bool test_one_setting (const char *label, const char *setting, struct crypt_data *cd, bool expected_to_succeed) { bool ok = true; const char *retval; int cdsize = (int) sizeof (struct crypt_data); #ifdef VERBOSE printf ("%s: testing %s (expect: %s)\n", label, setting, expected_to_succeed ? "succeed" : "fail"); #endif retval = crypt (phrase, setting); if (!check_crypt (label, "crypt", retval, setting, expected_to_succeed)) ok = false; retval = crypt_r (phrase, setting, cd); if (!check_crypt (label, "crypt_r", retval, setting, expected_to_succeed)) ok = false; retval = crypt_rn (phrase, setting, cd, cdsize); if (!check_crypt_rn (label, "crypt_rn", retval, cd->output, setting, expected_to_succeed)) ok = false; retval = crypt_ra (phrase, setting, (void **)&cd, &cdsize); if (!check_crypt_rn (label, "crypt_ra", retval, cd->output, setting, expected_to_succeed)) ok = false; return ok; }
static PyObject * _py_crypt_rn(PyObject *self, PyObject *args) { char *rc; const char *key; const char *setting; char output[61]; memset(output, 0, sizeof(output)); if (!PyArg_ParseTuple(args, "ss", &key, &setting)) { return NULL; } Py_BEGIN_ALLOW_THREADS; /* key, setting, output, size */ rc = crypt_rn(key, setting, output, sizeof(output)); Py_END_ALLOW_THREADS; if (rc == NULL) { Py_RETURN_NONE; } output[sizeof(output) - 1] = '\0'; return Py_BuildValue("s", output); }
static void validate(RedisModuleCtx *ctx, RedisModuleCallReply *reply, RedisModuleString *password) { const char *reply_str; size_t reply_len; const char *pass; size_t pass_len; const char *crypt_pass; size_t crypt_pass_len; char crypt_buf[64]; if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_NULL) { RedisModule_ReplyWithLongLong(ctx, 0); return; } if (RedisModule_CallReplyType(reply) != REDISMODULE_REPLY_STRING) { RedisModule_ReplyWithError(ctx, "WRONGTYPE Operation against a key holding the wrong kind of value"); return; } reply_str = RedisModule_CallReplyStringPtr(reply, &reply_len); pass = RedisModule_StringPtrLen(password, &pass_len); crypt_pass = crypt_rn(pass, reply_str, crypt_buf, sizeof(crypt_buf)); if (!crypt_pass) { RedisModule_ReplyWithError(ctx, "ERR hash error"); return; } crypt_pass_len = strlen(crypt_pass); if (crypt_pass_len == reply_len && !memcmp(reply_str, crypt_pass, crypt_pass_len)) { RedisModule_ReplyWithLongLong(ctx, 1); } else { RedisModule_ReplyWithLongLong(ctx, 0); } }
char *crypt(const char *key, const char *setting) { static char output[CRYPT_OUTPUT_SIZE]; return _crypt_retval_magic( crypt_rn(key, setting, output, sizeof(output)), setting, output, sizeof(output)); }
std::string compute_hash(const std::string &password, const std::string &salt) { char hash[64]; if (!crypt_rn(password.c_str(), salt.c_str(), hash, 64)) return ""; return hash; }
char *ftsi_bc_hash(const char *s, const char *salt) { char *hash = calloc(BC_HASHSIZE + 1, sizeof(char)); char *r = crypt_rn(s, salt, hash, BC_HASHSIZE); if (r == NULL) { free(hash); return NULL; } return hash; }
bool BCryptHashFunction::verify(const std::string& msg, const std::string& salt, const std::string& hash) const { char result[64]; if (!crypt_rn(msg.c_str(), hash.c_str(), result, 64)) { std::perror("crypt_rn"); throw std::runtime_error("bcrypt() internal error"); } return result == hash; }
long long bcrypt_check(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *err) { int ret; char *aux; char chk_hash[BCRYPT_HASHSIZE]; char pass[PASS_MAXLEN+1]; char hash[BCRYPT_HASHSIZE]; /* password */ if (!args->args[0]) { *is_null = 1; return 0; } else { if ((ret = my_str_to_c_str(pass, sizeof(pass), args->args[0], args->lengths[0])) != 0) { *is_null = 1; return 0; } } /* hash */ if (!args->args[1]) { *is_null = 1; return 0; } else { if ((ret = my_str_to_c_str(hash, sizeof(hash), args->args[1], args->lengths[1])) != 0) { *is_null = 1; return 0; } } /* compute password hash */ if ((aux = crypt_rn(pass, hash, chk_hash, BCRYPT_HASHSIZE)) == NULL) { *is_null = 1; return 0; } ret = timing_safe_strcmp(hash, chk_hash); if (ret == 0) { return 1; } else if (ret > 0) { return 0; } else { *is_null = 1; return 0; } }
int ftsi_bc_verify(const char *pass, const char *hash) { char h[BC_HASHSIZE + 1]; strncpy(h, hash, BC_HASHSIZE + 1); // since strncpy pads with nulls char hh[BC_HASHSIZE + 1]; memset(hh, 0, BC_HASHSIZE + 1); crypt_rn(pass, h, hh, BC_HASHSIZE); int r = 1; for (size_t i = 0; i < BC_HASHSIZE; ++i) { r = (h[i] == hh[i]) ? r : 0; } return r; }
static char *do_crypt(const char *password, char *output, int output_len) { char salt[16]; char tmp[64]; char *setting; FILE *fp = fopen("/dev/urandom","r"); if (!fp) return NULL; if (fread(salt, sizeof(salt), 1, fp) != 1) { fclose(fp); return NULL; } fclose(fp); memset(tmp, 0, sizeof(tmp)); if (!(setting = crypt_gensalt_rn("$2y$", 0, salt, sizeof(salt), tmp, sizeof(tmp)))) return NULL; memset(output, 0, output_len); return crypt_rn(password, setting, output, output_len); }
std::string BCryptHashFunction::compute(const std::string& msg, const std::string& salt) const { char setting[32]; char c_salt[16]; std::strncpy(c_salt, salt.c_str(), 16); if (salt.length() < 16) std::memset(c_salt + salt.length(), 'A', 16 - salt.length()); if (!crypt_gensalt_rn("$2y$", count_, c_salt, 16, setting, 32)) { std::perror("crypt_gen_salt_rn"); throw std::runtime_error("bcrypt() gensalt internal error"); } else { char result[64]; if (!crypt_rn(msg.c_str(), setting, result, 64)) { std::perror("crypt_rn"); throw std::runtime_error("bcrypt() internal error"); } return result; } }
bool BCryptHashFunction::verify(const std::string& msg, const std::string& hash, const std::string& salt) const { //#ifdef __APPLE__ char result[64]; if (!crypt_rn(msg.c_str(), hash.c_str(), result, 64)) { std::perror("crypt_rn"); throw std::runtime_error("bcrypt() internal error"); } std::cout<<"msg "<<msg<<" hash "<<hash<<" salt "<<salt<<std::endl; std::cout<<"crypt "<<result<<std::endl; std::cout<<compute(msg,salt)<<std::endl; return result == hash; //#else //std::cout<<"msg "<<msg<<" hash "<<hash<<" salt "<<salt<<std::endl; //std::cout<<"crypt "<<crypt(msg.c_str(), salt.c_str())<<std::endl; //std::cout<<"crypt "<<crypt(msg.c_str(), hash.c_str())<<std::endl; //return crypt(msg.c_str(), std::string("$2y$"+salt).c_str()) == hash; //#endif }
/* * This function expects a password to be hashed, a salt to hash the password * with and a char array to leave the result. Both the salt and the hash * parameters should have room for BCRYPT_HASHSIZE characters at least. * * It can also be used to verify a hashed password. In that case, provide the * expected hash in the salt parameter and verify the output hash is the same * as the input hash. However, to avoid timing attacks, it's better to use * bcrypt_checkpw when verifying a password. * * The return value is zero if the password could be hashed and nonzero * otherwise. */ int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) { char *aux; aux = crypt_rn(passwd, salt, hash, BCRYPT_HASHSIZE); return (aux == nullptr)?1:0; }
char *crypt_r(__CONST char *key, __CONST char *setting, void *data) { return _crypt_retval_magic( crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE), setting, (char *)data); }
static bool test_one_case (const struct testcase *t, char *page, size_t pagesize, struct crypt_data *cd) { memset (page, 'a', pagesize); size_t l_setting = strlen (t->setting); assert (l_setting <= pagesize); if (t->label[0] == '*') { /* Hashing with this setting is expected to fail already. We still want to verify that we do not read past the end of the string. */ char *p = page + pagesize - (l_setting + 1); memcpy (p, t->setting, l_setting + 1); if (!test_one_setting (t->label + 1, p, cd, false)) return false; printf ("PASS: %s\n", t->label + 1); return true; } else { /* Hashing with this setting is expected to succeed. */ char goodhash[CRYPT_OUTPUT_SIZE]; char *result = crypt_rn (phrase, t->setting, cd, sizeof (struct crypt_data)); if (!result) { printf ("FAIL: %s: initial hash returned NULL/%s (%s)\n", t->label, cd->output, strerror (errno)); return false; } size_t l_hash = strlen (result); assert (l_hash + 1 <= CRYPT_OUTPUT_SIZE); memcpy (goodhash, result, l_hash + 1); char *p = page + pagesize - (l_hash + 1); memcpy (p, goodhash, l_hash + 1); /* Rechecking the hash with the full output should succeed. */ if (!test_one_setting (t->label, p, cd, true)) return false; /* Recomputing the hash with its own prefix should produce a hash with the same prefix. */ p = page + pagesize - (t->plen + 1); memcpy (p, goodhash, t->plen); p[t->plen] = '\0'; if (!test_one_setting (t->label, p, cd, true)) return false; /* An invalid character after the prefix should not affect the result of the hash computation. */ p = page + pagesize - (t->plen + 2); memcpy (p, goodhash, t->plen); p[t->plen] = '*'; p[t->plen+1] = '\0'; if (!test_one_setting (t->label, p, cd, true)) return false; /* However, an invalid character anywhere within the prefix should cause hashing to fail. */ size_t plen = t->plen; /* des_big only values the first two characters of the setting, but needs strlen(setting) >= 14. */ const char *des_big_label = "DES (bigcrypt)"; if (!strcmp (t->label, des_big_label)) { plen = 2; } for (size_t i = 1; i < plen; i++) { p = page + pagesize - (plen + 2 - i); memcpy (p, goodhash, plen - i); if (!test_one_setting (t->label, p, cd, false)) return false; } printf ("PASS: %s\n", t->label); return true; } }
char *bcrypt_hash(UDF_INIT *initid, UDF_ARGS *args, char *res, unsigned long *len, char *is_null, char *err) { int ret, fd; char *aux; char randb[RANDBYTES]; char pass[PASS_MAXLEN+1]; char salt[BCRYPT_HASHSIZE]; long long workfactor; /* password */ if (!args->args[0]) { *is_null = 1; return 0; } else { if ((ret = my_str_to_c_str(pass, sizeof(pass), args->args[0], args->lengths[0])) != 0) { *is_null = 1; return 0; } } /* work factor */ if (args->args[1]) { workfactor = *(long long*) args->args[1]; } else { workfactor = WORKFACTOR_DEFAULT; } if (workfactor < WORKFACTOR_MIN) { workfactor = WORKFACTOR_MIN; } else if (workfactor > WORKFACTOR_MAX) { workfactor = WORKFACTOR_MAX; } /* start salt generation */ if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { *is_null = 1; return 0; } if (try_read(fd, randb, RANDBYTES) != 0) { try_close(fd); *is_null = 1; return 0; } if (try_close(fd) != 0) { *is_null = 1; return 0; } if ((aux = crypt_gensalt_rn("$2b$", workfactor, randb, RANDBYTES, salt, BCRYPT_HASHSIZE)) == NULL) { *is_null = 1; return 0; } /* end salt generation */ /* compute password hash */ if ((aux = crypt_rn(pass, salt, res, BCRYPT_HASHSIZE)) == NULL) { *is_null = 1; return 0; } *len = strlen(res); return res; }