基于布隆过滤器的跨平台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

相关文章

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

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

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

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

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

如何选择SDR无线图传方案

在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传输。OpenHD项目提供了一个完整的工具链,包括发射器和接收器的硬件设计以及相应的软件。 2. **USRP(Universal Software Radio Periphera

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u

Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题 缓存穿透是指查询一个一定不存在的数据,由于缓存中没有命中,会去数据库中查询,而数据库中也没有该数据,并且每次查询都不会命中缓存,从而每次请求都直接打到了数据库上,这会给数据库带来巨大压力。 二、布隆过滤器原理 布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用多个不同的哈希函数将一个元素映射到一个位数组中的多个位置,并将这些位置的值置

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

布隆过滤器的详解与应用

一、什么是Bloom Filter Bloom Filter是一种空间效率很高的随机数据结构,它的原理是,当一个元素被加入集合时,通过K个Hash函数将这个元素映射成一个位阵列(Bit array)中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检索元素一定不在;如果都是1,则被检索元素很可能在。这就是布隆过滤器的基本思