开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
master
分支 (6)
master
feature/48-mysql-connection-pool
gh-pages
bugfix/52-volume-already-in-use
feature/6-simplify-deployment
async-rewrite
master
分支 (6)
master
feature/48-mysql-connection-pool
gh-pages
bugfix/52-volume-already-in-use
feature/6-simplify-deployment
async-rewrite
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
master
分支 (6)
master
feature/48-mysql-connection-pool
gh-pages
bugfix/52-volume-already-in-use
feature/6-simplify-deployment
async-rewrite
scrypt.cpp 5.80 KB
一键复制 编辑 原始数据 按行查看 历史
Ruben Perez 提交于 2023年09月26日 23:21 +08:00 . Authentication, login and account creation
//
// Copyright (c) 2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "util/scrypt.hpp"
#include <charconv>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "error.hpp"
#include "util/base64.hpp"
using namespace chat;
static result<std::uint64_t> parse_int(std::string_view from) noexcept
{
std::uint64_t value = 0;
auto res = std::from_chars(from.begin(), from.end(), value);
if (res.ec != std::errc())
CHAT_RETURN_ERROR(std::make_error_code(res.ec))
else if (res.ptr != from.data() + from.size())
CHAT_RETURN_ERROR(errc::invalid_password_hash)
else
return value;
}
static result<scrypt_params> parse_phc_params(std::string_view from)
{
// sane upper bounds
constexpr std::uint64_t max_ln = 20;
constexpr std::uint64_t max_r = 20;
scrypt_params res{};
while (true)
{
// Get a parameter
auto last = from.find(',');
auto serialized_param = from.substr(0, last);
// Split it into key/value
auto param_eq = serialized_param.find('=');
if (param_eq == std::string_view::npos)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
auto name = serialized_param.substr(0, param_eq);
auto value_str = serialized_param.substr(param_eq + 1);
// Parse it. Ignore unknown params
if (name == "ln")
{
auto value = parse_int(value_str);
if (value.has_error())
CHAT_RETURN_ERROR(errc::invalid_password_hash)
if (*value < 2 || *value > max_ln)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
res.ln = value.value();
}
else if (name == "r")
{
auto value = parse_int(value_str);
if (value.has_error())
return value.error();
if (*value < 1 || *value > max_r)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
res.r = value.value();
}
else if (name == "p")
{
auto value = parse_int(value_str);
if (value.has_error())
CHAT_RETURN_ERROR(errc::invalid_password_hash)
// p != 1 not supported (nor recommended by owasp)
if (*value != 1u)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
res.p = value.value();
}
// Go to next
if (last == std::string_view::npos)
break;
else
from = from.substr(last + 1);
}
return res;
}
result<scrypt_data> chat::scrypt_phc_parse(std::string_view from)
{
// First $ identifier
if (from.empty() || from.front() != '$')
CHAT_RETURN_ERROR(errc::invalid_password_hash)
from = from.substr(1);
// Algorithm identifier
auto count = from.find('$');
if (count == std::string_view::npos)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
auto algo_id = from.substr(0, count);
if (algo_id != "scrypt")
CHAT_RETURN_ERROR(errc::invalid_password_hash) // Algorithm we don't know
from = from.substr(count + 1);
// Params field. Spec says this is optional, but for now we require it
count = from.find('$');
if (count == std::string_view::npos)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
auto serialized_params = from.substr(0, count);
auto params_result = parse_phc_params(serialized_params);
if (params_result.has_error())
return params_result.error();
from = from.substr(count + 1);
// Salt field. Spec says this is optional, but for now we require it
count = from.find('$');
if (count == std::string_view::npos)
CHAT_RETURN_ERROR(errc::invalid_password_hash)
auto b64_salt = from.substr(0, count);
auto salt_result = base64_decode(b64_salt, false);
if (salt_result.has_error())
CHAT_RETURN_ERROR(errc::invalid_password_hash)
from = from.substr(count + 1);
// Hash field (rest of the string)
auto hash_result = base64_decode(from, false);
if (hash_result.has_error())
CHAT_RETURN_ERROR(errc::invalid_password_hash)
return scrypt_data{
params_result.value(),
std::move(salt_result).value(),
std::move(hash_result).value(),
};
}
std::string chat::scrypt_phc_serialize(
scrypt_params params,
boost::span<const unsigned char, salt_size> salt,
boost::span<const unsigned char, hash_size> hash
)
{
std::ostringstream oss;
oss << "$scrypt$ln=" << params.ln << ",r=" << params.r << ",p=" << params.p << "$"
<< base64_encode(salt, false) << "$" << base64_encode(hash, false);
return oss.str();
}
// Hashes the given password with the given salt and params
std::array<unsigned char, hash_size> chat::scrypt_generate_hash(
std::string_view passwd,
scrypt_params params,
boost::span<const unsigned char> salt
)
{
constexpr std::size_t max_memory = 32 << 20; // 32MiB
std::array<unsigned char, hash_size> res{};
int ec = EVP_PBE_scrypt(
passwd.data(),
passwd.size(),
salt.data(),
salt.size(),
1 << params.ln, // base 2 log
params.r,
params.p,
max_memory,
res.data(),
res.size()
);
if (ec <= 0)
{
char errbuff[256]{};
ERR_error_string_n(ERR_get_error(), errbuff, sizeof(errbuff));
throw std::runtime_error(errbuff);
}
return res;
}
// Compares two blobs, in a way that prevents timing attacks
bool chat::time_safe_equals(boost::span<const unsigned char> s1, boost::span<const unsigned char> s2) noexcept
{
return CRYPTO_memcmp(s1.data(), s2.data(), std::min(s1.size(), s2.size())) == 0 && s1.size() == s2.size();
}
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

简介

Web聊天室项目
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/cppprojects/servertech-chat.git
git@gitee.com:cppprojects/servertech-chat.git
cppprojects
servertech-chat
servertech-chat
master
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /