基于布隆过滤器的跨平台USB存储设备管控方案

2024-02-10 18:12

本文主要是介绍基于布隆过滤器的跨平台USB存储设备管控方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、前言

U盘作为移动存储设备之一,是我们日常生活中接触最多和最常用的存储介质。正因如此,针对U盘内容的管理也因为使用场景的多样和复杂性,变得难以实现。
我们的设计思路是先通过某些手段对U盘进行病毒,并在查杀完成后对U盘进行认证。在后续使用过程检测认证U盘是否被篡改以保证U盘的安全性。

2、设计

本方案的设计主要包含两个部分:U盘认证和U盘检测。

2.1 认证
  1. 检测当前设备是否USB存储设备
  2. 根据U盘内容创建合适的布隆过滤器
  3. 遍历U盘文件,以文件名 + 时间戳 + 文件大小的方式生成标志字符串,添加到布隆过滤器中
  4. 保存布隆过滤器
  5. 保存布隆过滤器的时间戳
2.2 检测
  1. 检测当前设备是否USB存储设备
  2. 根据布隆过滤器的时间戳,计算当前系统的时间偏差
  3. 加载布隆过滤器
  4. 遍历U盘文件,以文件名 + 时间戳 + 文件大小的方式生成标志字符串,检测是否命中

3、实现

3.1 设备检测
#ifdef _WIN32if (driver_[0] != 'A' && driver_[0] != 'B' &&// 判断设备是否可移动介质GetDriveTypeA(driver_.c_str()) == DRIVE_REMOVABLE) {// 判断设备是否加载if (GetVolumeInformationA(driver_.c_str(), NULL, NULL, NULL, NULL, NULL,NULL, 0)) {return true;}}
#elsestd::ifstream mounts("/proc/mounts");if (mounts.is_open()) {std::string line;while (std::getline(mounts, line)) {std::stringstream ss(line);std::string device, mount_point;ss >> device >> mount_point;if (driver_.substr(0, driver_.length() - 1) == mount_point) {if (0 == strncmp("/dev/sd", device.c_str(), 7)) {ss.str("");ss << "/sys/block/";// 获取块设备for (size_t i = 5; i <= device.length(); ++i) {  //if ('0' <= device[i] && '9' >= device[i]) {break;}ss << device[i];}std::error_code err;std::string dev_pci_name =fs::read_symlink(ss.str(), err).generic_string();// 检测pci总线中是否包含"usb"标识if (dev_pci_name.find("usb") != std::string::npos) {return true;}}return false;}}}
#endifreturn false;
3.2 文件遍历
  std::stringstream ss;try {for (fs::recursive_directory_iterator it(driver_path);it != fs::recursive_directory_iterator(); it++) {std::string path = it->path().generic_u8string().substr(driver_path.size(), std::string::npos);// 跳过认证文件if (strcmp(kBloomFilterPath, path.c_str()) == 0 ||strcmp(kTimeMarkPath, path.c_str()) == 0 ||strcmp(kUsbAuthDir, path.c_str()) == 0)continue;if (!fs::is_directory(it->path()) && !fs::is_regular_file(it->path()))continue;ss.str("");ss << path;// 获取文件的filetimeauto time = tm_::duration_cast<tm_::seconds>(it->last_write_time().time_since_epoch()).count();ss << (time - elapse);size_t file_size = 0x1000;if (fs::is_regular_file(it->path())) {file_size = it->file_size();}ss << file_size;if (!bf_.BloomAdd(ss.str())) {return error_code::kIOFailure;}}} catch (fs::filesystem_error &e) {return error_code::kIOFailure;}
3.3 布隆过滤器
  // Hash算法:Fnv1a_64 uint64_t hash = 0xcbf29ce484222325ull;const uint8_t *bytes = static_cast<const uint8_t *>(data);for (size_t i = 0; i < numBytes; ++i) {hash ^= bytes[i];hash *= 0x100000001b3ull;}uint8_t seed_arr[32] = {0};
#ifdef _WIN32numBytes = sprintf_s((char *)seed_arr, sizeof(seed_arr) - 1, "%d", seed);
#elsenumBytes = snprintf((char *)seed_arr, sizeof(seed_arr) - 1, "%d", seed);
#endiffor (size_t i = 0; i < numBytes; ++i) {hash ^= seed_arr[i];hash *= 0x100000001b3ull;}return hash;

4、难点记录

4.1 时间戳获取

C++17标准中提供的std::filesystem::last_write_time()函数返回的类型为std::filesystem::file_time_type
查阅官方文档可知,file_time_type在C++17中的实现是基于平台的,不支持跨平台。
在MSVC的代码中可以发现,Windows平台提供的file_time_type是基于FileTime实现的。即在Windows C++中,FileTime的计算方式是从1601年1月1日开始的100纳秒为单位的时间。
因此当我们需要将std::filesystem::last_write_time()转换为UTC时间戳时,首先需要使用duration_cast将单位转换为秒。

auto time = tm_::duration_cast<tm_::seconds>(it->last_write_time().time_since_epoch()).count();

通过上一步,我们取得了从1601年1月1日开始的秒为单位的时间戳。下一步,我们需要减去FileTime和UTC时间之前的差值。

从C++文档中我们可以查到std::chrono::system_clock使用的正是1970年开始的UTC时间,因此可以通过以下手段获取秒为单位的差值。

auto elapse = tm_::duration_cast<tm_::seconds>(fs::file_time_type::clock::now().time_since_epoch() - tm_::system_clock::now().time_since_epoch()).count();

最后,通过以上两个数据,我们计算出文件修改时间的UTC时间戳。

auto mtime = time - elapse
4.2 时间戳不一致

在实际测试中发现,即同一个文件在Windows和Linux系统中获取的时间戳在某些情况会出现不一致的问题。
经过调查发现,是由于Windows 与 Linux 看待硬件时间的方式不同。
Windows 把电脑的硬件时钟(RTC)看成是本地时间,即 RTC = Local Time,Windows 会直接显示硬件时间;
而 Linux 则是把电脑的硬件时钟看成 UTC 时间,即 RTC = UTC,那么 Linux 显示的时间就是硬件时间加上时区。
针对这个问题,和团队成员讨论后最终决定了一个方案。通过在认证阶段生成一个标识时间戳,在检测阶段计算和标识时间戳的差值来重新对齐时间。

// 生成标识时间
auto time = tm_::duration_cast<tm_::seconds>(fs::last_write_time(bf_path).time_since_epoch()).count();
struct {uint64_t magic;time_t base_time;
} bin = {kTmMagic, time - elapse};// 获取标识时间, 计算差值
auto time = tm_::duration_cast<tm_::seconds>(fs::last_write_time(bf_path, err).time_since_epoch()).count();
auto time_diff = bin.base_time - (time - elapse);  // Get System Time Diff between auth and scan

完整项目代码

这篇关于基于布隆过滤器的跨平台USB存储设备管控方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/697764

相关文章

Redis 多规则限流和防重复提交方案实现小结

《Redis多规则限流和防重复提交方案实现小结》本文主要介绍了Redis多规则限流和防重复提交方案实现小结,包括使用String结构和Zset结构来记录用户IP的访问次数,具有一定的参考价值,感兴趣... 目录一:使用 String 结构记录固定时间段内某用户 IP 访问某接口的次数二:使用 Zset 进行

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

Redis KEYS查询大批量数据替代方案

《RedisKEYS查询大批量数据替代方案》在使用Redis时,KEYS命令虽然简单直接,但其全表扫描的特性在处理大规模数据时会导致性能问题,甚至可能阻塞Redis服务,本文将介绍SCAN命令、有序... 目录前言KEYS命令问题背景替代方案1.使用 SCAN 命令2. 使用有序集合(Sorted Set)

MyBatis延迟加载的处理方案

《MyBatis延迟加载的处理方案》MyBatis支持延迟加载(LazyLoading),允许在需要数据时才从数据库加载,而不是在查询结果第一次返回时就立即加载所有数据,延迟加载的核心思想是,将关联对... 目录MyBATis如何处理延迟加载?延迟加载的原理1. 开启延迟加载2. 延迟加载的配置2.1 使用

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了