Skip to content

Commit

Permalink
去除国密化,如果想实现国密化可参考之前commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rongliangtang committed Oct 18, 2023
1 parent 1147795 commit 05d0676
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 178 deletions.
104 changes: 23 additions & 81 deletions sources/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include <cryptopp/osrng.h>
#include <cryptopp/scrypt.h>
#include <cryptopp/secblock.h>
#include <cryptopp/sm3.h>
#include <fuse.h>
#include <json/json.h>
#include <tclap/CmdLine.h>
Expand Down Expand Up @@ -47,13 +46,11 @@ const char* const CONFIG_FILE_NAME = ".securefs.json";
const unsigned MIN_ITERATIONS = 20000;
const unsigned MIN_DERIVE_SECONDS = 1;
// size_t(size_type)可以提高代码的可移植性、有效性、可读性,表示取值范围是目标平台下最大的可能范围。不同位数的os上定义不一样,但都为无符号整数。
// 加密master_key用
const size_t CONFIG_IV_LENGTH = 32, CONFIG_MAC_LENGTH = 16;

const char* const PBKDF_ALGO_PKCS5 = "pkcs5-pbkdf2-hmac-sha256";
const char* const PBKDF_ALGO_SCRYPT = "scrypt";
const char* const PBKDF_ALGO_ARGON2ID = "argon2id";
const char* const HKDF_WITH_SM3 = "hkdf-with-sm3";

const char* const EMPTY_PASSWORD_WHEN_KEY_FILE_IS_USED = " ";

Expand Down Expand Up @@ -320,35 +317,6 @@ void hmac_sha256(const securefs::key_type& base_key,
hmac.TruncatedFinal(out_key.data(), out_key.size());
}

// 利用sm3实现hmac,用于key_file功能
void hmac_sm3(const securefs::key_type& base_key,
StringRef maybe_key_file_path,
securefs::key_type& out_key)
{
// 如果没有用keyfile文件,则salt_effective = salt
if (maybe_key_file_path.empty())
{
out_key = base_key;
return;
}
// 如果用了keyfile文件,会利用keyfile文件里面的信息和hmac-sha256算法来生成salt_effective
auto file_stream = OSService::get_default().open_file_stream(maybe_key_file_path, O_RDONLY, 0);
byte buffer[4096];
CryptoPP::HMAC<CryptoPP::SM3> hmac(base_key.data(), base_key.size());
while (true)
{
auto sz = file_stream->sequential_read(buffer, sizeof(buffer));
if (sz <= 0)
{
break;
}
hmac.Update(buffer, sz);
}
hmac.TruncatedFinal(out_key.data(), out_key.size());
}



// 产生配置信息函数,返回JSON格式的数据
Json::Value generate_config(unsigned int version,
const std::string& pbkdf_algorithm,
Expand All @@ -363,8 +331,7 @@ Json::Value generate_config(unsigned int version,
unsigned rounds)
{
securefs::key_type effective_salt;

hmac_sm3(salt, maybe_key_file_path, effective_salt);
hmac_sha256(salt, maybe_key_file_path, effective_salt);

Json::Value config;
config["version"] = version;
Expand Down Expand Up @@ -429,16 +396,6 @@ Json::Value generate_config(unsigned int version,
throw_runtime_error("Argon2 hashing failed with status code " + std::to_string(rc));
}
}
else if (pbkdf_algorithm == HKDF_WITH_SM3)
{
hkdf_with_sm3(password,
pass_len,
effective_salt.data(),
effective_salt.size(),
password_derived_key.data(),
password_derived_key.size()
);
}
else
{
throw_runtime_error("Unknown pbkdf algorithm " + pbkdf_algorithm);
Expand All @@ -453,7 +410,7 @@ Json::Value generate_config(unsigned int version,
generate_random(iv, array_length(iv));

// 利用password_derived_key来加密master_key获得e_key,得到用户看得见的.securefs.json里的数据
CryptoPP::GCM<CryptoPP::SM4>::Encryption encryptor;
CryptoPP::GCM<CryptoPP::AES>::Encryption encryptor;
encryptor.SetKeyWithIV(
password_derived_key.data(), password_derived_key.size(), iv, array_length(iv));
encryptor.EncryptAndAuthenticate(encrypted_master_key.data(),
Expand All @@ -475,7 +432,6 @@ Json::Value generate_config(unsigned int version,
config["encrypted_key"] = std::move(encrypted_key);

// 如果format_version!=1,则block_size和iv_size是可变的,放到json中
// 这里的iv_size是文件分块中每一块的iv的size
if (version >= 2)
{
config["block_size"] = block_size;
Expand All @@ -489,19 +445,18 @@ Json::Value generate_config(unsigned int version,
return config;
}

// 根据password和config来计算password_derived_key
void compute_password_derived_key(const Json::Value& config,
const void* password,
size_t pass_len,
key_type& salt,
key_type& password_derived_key)
{
unsigned iterations = config["iterations"].asUInt();
std::string pbkdf_algorithm = config.get("pbkdf", PBKDF_ALGO_PKCS5).asString();
VERBOSE_LOG("Setting the password key derivation function to %s", pbkdf_algorithm.c_str());

if (pbkdf_algorithm == PBKDF_ALGO_PKCS5)
{
unsigned iterations = config["iterations"].asUInt();
pbkdf_hmac_sha256(password,
pass_len,
salt.data(),
Expand All @@ -513,7 +468,6 @@ void compute_password_derived_key(const Json::Value& config,
}
else if (pbkdf_algorithm == PBKDF_ALGO_SCRYPT)
{
unsigned iterations = config["iterations"].asUInt();
auto r = config["scrypt_r"].asUInt();
auto p = config["scrypt_p"].asUInt();
CryptoPP::Scrypt scrypt;
Expand All @@ -529,7 +483,6 @@ void compute_password_derived_key(const Json::Value& config,
}
else if (pbkdf_algorithm == PBKDF_ALGO_ARGON2ID)
{
unsigned iterations = config["iterations"].asUInt();
auto m_cost = config["argon2_m_cost"].asUInt();
auto p = config["argon2_p"].asUInt();
int rc = argon2id_hash_raw(iterations,
Expand All @@ -546,16 +499,6 @@ void compute_password_derived_key(const Json::Value& config,
throw_runtime_error("Argon2 hashing failed with status code " + std::to_string(rc));
}
}
else if (pbkdf_algorithm == HKDF_WITH_SM3)
{
hkdf_with_sm3(password,
pass_len,
salt.data(),
salt.size(),
password_derived_key.data(),
password_derived_key.size()
);
}
else
{
throw_runtime_error("Unknown pbkdf algorithm " + pbkdf_algorithm);
Expand Down Expand Up @@ -618,7 +561,7 @@ bool parse_config(const Json::Value& config,
auto decrypt_and_verify = [&](const securefs::key_type& wrapping_key)
{
// 定义一个解密器
CryptoPP::GCM<CryptoPP::SM4>::Decryption decryptor;
CryptoPP::GCM<CryptoPP::AES>::Decryption decryptor;
decryptor.SetKeyWithIV(wrapping_key.data(), wrapping_key.size(), iv, array_length(iv));
// 利用解密器进行解密和验证,返回bool类型
return decryptor.DecryptAndVerify(
Expand All @@ -641,10 +584,9 @@ bool parse_config(const Json::Value& config,
{
// 利用key_file获取new_salt
securefs::key_type new_salt;
hmac_sm3(salt, maybe_key_file_path, new_salt);
hmac_sha256(salt, maybe_key_file_path, new_salt);

securefs::key_type password_derived_key;
// 使用hmac_sm3计算获得的password_derived_key有误?
compute_password_derived_key(config, password, pass_len, new_salt, password_derived_key);
if (decrypt_and_verify(password_derived_key))
{
Expand All @@ -660,7 +602,7 @@ bool parse_config(const Json::Value& config,
securefs::key_type password_derived_key;
compute_password_derived_key(config, password, pass_len, salt, password_derived_key);
// 利用key_file获取new_password_derived_key
hmac_sm3(password_derived_key, maybe_key_file_path, wrapping_key);
hmac_sha256(password_derived_key, maybe_key_file_path, wrapping_key);
return decrypt_and_verify(wrapping_key);
}
}
Expand All @@ -686,7 +628,7 @@ FSConfig CommandBase::read_config(FileStream* stream,
{
// 配置文件对应的结构体
FSConfig result;

// 读取配置文件到一个JSON数据结构中
std::vector<char> str;
// 预留4000的vector大小,预留足够的大小,省得没有连续空间移来移去,这种写法能节省开销(空间换时间)
Expand Down Expand Up @@ -903,9 +845,9 @@ class CreateCommand : public _SinglePasswordCommandBase
"",
"store_time",
"alias for \"--format 3\", enables the extension where timestamp are stored and encrypted"};
// pbkdf表示使用何种pbkdf算法,默认是argon2id(改为国密后默认为hkdf-with-sm3)
// pbkdf表示使用何种pbkdf算法,默认是argon2id
TCLAP::ValueArg<std::string> pbkdf{
"", "pbkdf", message_for_setting_pbkdf, false, HKDF_WITH_SM3, "string"};
"", "pbkdf", message_for_setting_pbkdf, false, PBKDF_ALGO_ARGON2ID, "string"};
// max-padding表示填充到所有文件的最大数量,每个block进行随机填充,作用是混淆文件的大小,开启这个功能会产生巨大的性能消耗
TCLAP::ValueArg<unsigned> max_padding{
"",
Expand Down Expand Up @@ -965,7 +907,7 @@ class CreateCommand : public _SinglePasswordCommandBase

// 创建配置文件的结构体(master_key等数据)注意.securefs.json中存放的是master_key加密后的密文
FSConfig config;
// 调整类型为CryptoPP::AlignedSecByteBlock的config.master_key的大小,format=4时为4*KEY_LENGTH字节,format<4时为KEY_LENGTH字节
// 调整类型为CryptoPP::AlignedSecByteBlock的config.master_key的大小,format=4时为4*32字节,format<4时为32字节
// 每个CryptoPP::AlignedSecByteBlock类型变量中data以byte字节为单位
config.master_key.resize(format_version < 4 ? KEY_LENGTH : 4 * KEY_LENGTH);
// 使用CryptoPP::OS_GenerateRandomBlock函数,随机生成master_key
Expand Down Expand Up @@ -1058,9 +1000,9 @@ class ChangePasswordCommand : public _DataDirCommandBase
false,
0,
"integer"};
// pbkdf表示使用何种pbkdf算法,默认是argon2id(改为国密后默认为hkdf-with-sm3)
// pbkdf表示使用何种pbkdf算法,默认是argon2id
TCLAP::ValueArg<std::string> pbkdf{
"", "pbkdf", message_for_setting_pbkdf, false, HKDF_WITH_SM3, "string"};
"", "pbkdf", message_for_setting_pbkdf, false, PBKDF_ALGO_ARGON2ID, "string"};
// 旧的keyfile路径
TCLAP::ValueArg<std::string> old_key_file{
"", "oldkeyfile", "Path to original key file", false, "", "path"};
Expand Down Expand Up @@ -1135,7 +1077,7 @@ class ChangePasswordCommand : public _DataDirCommandBase
{
assign(EMPTY_PASSWORD_WHEN_KEY_FILE_IS_USED, old_password);
}

// 如果命令中设置了newpass,则将其值放到new_password中
if (newpass.isSet())
{
Expand Down Expand Up @@ -1252,7 +1194,7 @@ class MountCommand : public _SinglePasswordCommandBase
"Disables the usage of file locking. Needed on some network "
"filesystems. May cause data loss, so use it at your own risk!",
false};
// 文件名规范化模式,合法值:none, casefold, nfc, casefold+nfc,在mac上默认是nfc,其他平台默认none
// 文件名规范化模式,合法值:none, casefold, nfc, casefold+nfc,在mac上默认是nfc,其他平台默认none
TCLAP::ValueArg<std::string> normalization{"",
"normalization",
"Mode of filename normalization. Valid values: "
Expand All @@ -1272,7 +1214,7 @@ class MountCommand : public _SinglePasswordCommandBase
false,
30,
"int"};

private:
// 将args从std::vector<std::string>转为std::vector<const char*>格式
// 因为有些c库函数参数类型为char*
Expand Down Expand Up @@ -1323,7 +1265,7 @@ class MountCommand : public _SinglePasswordCommandBase
// 解析命令函数
void parse_cmdline(int argc, const char* const* argv) override
{

TCLAP::CmdLine cmdline(help_message());

#ifdef __APPLE__
Expand Down Expand Up @@ -1591,8 +1533,8 @@ class MountCommand : public _SinglePasswordCommandBase
// TODO:这里的代码应该没有写全把
if (!network_mount)
#endif
// 把挂载点的路径加入到fuse_args中
fuse_args.emplace_back(mount_point.getValue());
// 把挂载点的路径加入到fuse_args中
fuse_args.emplace_back(mount_point.getValue());
// 打印 VERBOSE_LOG,输出文件系统的一些信息到终端
VERBOSE_LOG("Filesystem parameters: format version %d, block size %u (bytes), iv size %u "
"(bytes)",
Expand Down Expand Up @@ -1704,7 +1646,7 @@ class MountCommand : public _SinglePasswordCommandBase
// 如果xattr开启了
if (native_xattr)
{
// fsopt.root是一个类指针,所以访问类中的成员要用 ->
// fsopt.root是一个类指针,所以访问类中的成员要用 ->
// listxattr返回当前目录下的扩展属性的大小,有的话就>0
// 这里用listxattr的作用主要是判断有没有扩展属性支持
// .表示当前目录
Expand Down Expand Up @@ -1829,7 +1771,7 @@ class FixCommand : public _SinglePasswordCommandBase
fsopt.version = config.version;
fsopt.master_key = config.master_key;
fsopt.flags = config.version != 3 ? 0 : kOptionStoreTime;

// 创建FileSystemContext文件系统上下文对象
operations::FileSystemContext fs(fsopt);
// 利用data_dir路径和FileSystemContext对象进行修复
Expand Down Expand Up @@ -2062,14 +2004,14 @@ int commands_main(int argc, const char* const* argv)
// 如果程序后面没有跟参数的话,调用print_usage()输出提示信息就结束程序
if (argc < 2)
return print_usage();

// 把第一个参数(程序路径去掉)
argc--;
argv++;

// 遍历unique_ptr数组,获得数组里面的每个元素(因为是unique_ptr,必须要带&,才能获取到引用,可以修改元素的值)
for (std::unique_ptr<CommandBase>& command : cmds)
{
{
// 匹配命令
if (strcmp(argv[0], command->long_name()) == 0
|| (argv[0] != nullptr && argv[0][0] == command->short_name() && argv[0][1] == 0))
Expand Down Expand Up @@ -2102,4 +2044,4 @@ int commands_main(int argc, const char* const* argv)
return 2;
}
}
} // namespace securefs
} // namespace securefs
32 changes: 3 additions & 29 deletions sources/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <cryptopp/pwdbased.h>
#include <cryptopp/rng.h>
#include <cryptopp/sha.h>
#include <cryptopp/sm3.h>

/*这个文件放了利用cryptopp实现的一些方法*/

Expand Down Expand Up @@ -63,12 +62,9 @@ static void aes256_siv_dbl(byte* block)
}

// 又一个key来初始化m_cmac和m_ctr
// TODO: 将KEY_LENGTH从32改为16后,key_type的size为16,而cmac_sm4和ctr_sm4的密钥要求为16,这里暂时令它们使用同样的密钥而不对半分
AES_SIV::AES_SIV(const void* key, size_t size)
// : m_cmac(static_cast<const byte*>(key), size / 2)
// , m_ctr(static_cast<const byte*>(key) + size / 2, size / 2, aes256_siv_zero_block)
: m_cmac(static_cast<const byte*>(key), size)
, m_ctr(static_cast<const byte*>(key), size, aes256_siv_zero_block)
: m_cmac(static_cast<const byte*>(key), size / 2)
, m_ctr(static_cast<const byte*>(key) + size / 2, size / 2, aes256_siv_zero_block)
{
}

Expand Down Expand Up @@ -186,7 +182,6 @@ bool hmac_sha256_verify(const void* message,
return hmac.TruncatedVerify(static_cast<const byte*>(mac), mac_len);
}

// crypto++官方不建议使用这个早期的KDF,建议使用HKDF
unsigned int pbkdf_hmac_sha256(const void* password,
size_t pass_len,
const void* salt,
Expand All @@ -208,27 +203,6 @@ unsigned int pbkdf_hmac_sha256(const void* password,
min_seconds);
}

// 利用crypto++中提供的HKDF来实现KDF,将sha哈希算法换为SM3
unsigned int hkdf_with_sm3(const void* password,
size_t pass_len,
const void* salt,
size_t salt_len,
void* derived,
size_t derive_len)
{
CryptoPP::HKDF<CryptoPP::SM3> kdf;
// 暂时把info写死
byte *info = (byte*)"hkdf_with_sm3";
return kdf.DeriveKey(static_cast<byte*>(derived),
derive_len,
static_cast<const byte*>(password),
pass_len,
static_cast<const byte*>(salt),
salt_len,
info,
13);
}

static void hkdf_expand(const void* distilled_key,
size_t dis_len,
const void* info,
Expand Down Expand Up @@ -280,4 +254,4 @@ void hkdf(const void* key,
hkdf_expand(key, key_len, info, info_len, output, out_len);
}
}
} // namespace securefs
} // namespace securefs
Loading

0 comments on commit 05d0676

Please sign in to comment.