物理真机上LUKS结合TPM的测试 —— 使用随机数密钥
1. 创建磁盘空间
命令如下:
dd if=/dev/zero of=enc.disk bs=1M count=50
实际命令及结果如下:
$ dd if=/dev/zero of=enc.disk bs=1M count=50
输入了 50+0 块记录
输出了 50+0 块记录
52428800 字节 (52 MB, 50 MiB) 已复制,0.0587495 s,892 MB/s$ ls
enc.disk
2. 创建密钥
命令如下:
dd if=/dev/urandom of=disk.key bs=1 count=32
实际命令及结果如下:
$ dd if=/dev/urandom of=disk.key bs=1 count=32
输入了 32+0 块记录输出了 32+0 块记录32 字节已复制,0.00108989 s,29.4 kB/s$ ls
disk.key enc.disk
3. 将enc.disk虚拟成块设备
命令如下:
sudo losetup /dev/loop0 enc.disk
实际命令及结果如下:
$ sudo losetup /dev/loop0 enc.disk$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 50M 0 loop
nvme0n1 259:0 0 476.9G 0 disk
├─……/usr/local/opt/home/data
4. 加密enc.disk
命令如下:
sudo cryptsetup --key-file=disk.key luksFormat /dev/loop0
实际命令及结果如下:
$ sudo cryptsetup --key-file=disk.key luksFormat /dev/loop0WARNING!
========
这将覆盖 /dev/loop0 上的数据,该动作不可取消。
Are you sure? (Type 'yes' in capital letters): YES
5. 映射磁盘
命令如下:
sudo cryptsetup --key-file=disk.key open /dev/loop0 enc_volume
实际命令及结果如下:
$ ls /dev/mapper/
control enc_volume$ ls -l /dev/mapper/
总计 0
crw-rw---- 1 root root 10, 236 2月20日 11:14 control
lrwxrwxrwx 1 root root 7 2月24日 09:41 enc_volume -> ../dm-0
6. 格式化映射分区
命令如下:
sudo mkfs.ext4 -j /dev/mapper/enc_volume
实际命令及结果如下:
$ sudo mkfs.ext4 -j /dev/mapper/enc_volume
mke2fs 1.46.5 (30-Dec-2021)
创建含有 34816 个块(每块 1k)和 8720 个inode的文件系统文件系统UUID:884698f1-56e5-4f07-a2de-5d0174224280
超级块的备份存储于下列块: 8193, 24577正在分配组表: 完成
正在写入inode表: 完成
创建日志(4096 个块)完成写入超级块和文件系统账户统计信息: 已完成
7. 创建挂载点并挂载
命令如下:
mkdir mountpointsudo mount /dev/mapper/enc_volume mountpoint
实际命令及结果如下:
$ mkdir mountpoint
$ ls
disk.key enc.disk mountpoint
$ sudo mount /dev/mapper/enc_volume mountpoint$ df -h
文件系统 大小 已用 可用 已用% 挂载点/dev/nvme0n1p4 20G 13G 5.8G 69% /
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 7.7G 168M 7.5G 3% /dev/shm
tmpfs 3.1G 206M 2.9G 7% /run
tmpfs 7.7G 97M 7.6G 2% /tmp
……
tmpfs 1.6G 48K 1.6G 1% /run/user/1000
/dev/mapper/enc_volume 28M 14K 25M 1% /home/penghao/TApp/experiment3/mountpoint
8. 准备明文文件
命令如下:
sudo sh -c 'echo "This is my plain text" > mountpoint/plain.txt'
实际命令及结果如下:
$ sudo sh -c 'echo "This is my plain text" > mountpoint/plain.txt'$ cat mountpoint/plain.txt
This is my plain text
9. 卸载
命令如下:
sudo umount mountpoint
实际命令及结果如下:
$ sudo umount mountpoint
$
10. 关闭加密分区
命令如下:
sudo cryptsetup remove enc_volume
实际命令及结果如下:
$ sudo cryptsetup remove enc_volume$ ls /dev/mapper/
control
11. 卸除回环设备
命令如下:
sudo losetup -d /dev/loop0
实际命令及结果如下:
$ sudo losetup -d /dev/loop0
$
12. 创建主对象
命令如下:
tpm2_createprimary -Q --hierarchy=o --key-context=prim.ctx
命令及实际结果如下:
$ sudo /usr/local/bin/tpm2_createprimary --hierarchy=o --key-context=prim.ctx
name-alg:value: sha256raw: 0xb
attributes:value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|restricted|decryptraw: 0x30072
type:value: rsaraw: 0x1
exponent: 65537
bits: 2048
scheme:value: nullraw: 0x10
scheme-halg:value: (null)raw: 0x0
sym-alg:value: aesraw: 0x6
sym-mode:value: cfbraw: 0x43
sym-keybits: 128
rsa: b45cd070a8b71ba21a5dce69f93035671e4a32bc3758490629f21458171884171a94d1d6446aceb61b6a1d0df65a7f0c0a1cfa4fdbd221c12c69204b0cb8ab146014b9dc439c90b0ed7f538c2a9e0b8f1d16598d572f26f7ca1bcd76d2b1a4a56ee492f1bee45fc255096fb3972c3844a1191245bc2d3e8adcf694223f976a2af739ef6d6223eab4f71593b10233ead81d0d861912c600dfe97f37108fa53ec32f8307f1061689da224af65feccf510758aa8331402e341bfaea38f9203d74c21b54d9aa388351a13852613be8453f47caf6dae5c4a0af73175c40acb6df4e6e2b71b622eb6df4d084b411f4be8ba9c0240f614816e191ff4412839917d8afbb$ ls
disk.key enc.disk mountpoint prim.ctx
13. 创建对象
命令如下:
dd if=/dev/urandom bs=1 count=32 status=none | tpm2_create --hash-algorithm=sha256 --public=seal.pub --private=seal.priv --sealing-input=- --parent-context=prim.ctx
实际命令及结果如下:
$ dd if=/dev/urandom bs=1 count=32 status=none | sudo /usr/local/bin/tpm2_create --hash-algorithm=sha256 --public=seal.pub --private=seal.priv --sealing-input=- --parent-context=prim.ctx
name-alg:value: sha256raw: 0xb
attributes:value: fixedtpm|fixedparent|userwithauthraw: 0x52
type:value: keyedhashraw: 0x8
algorithm: value: nullraw: 0x10
keyedhash: b7b1416f740ffc19b9ae2da9bc4ae968612796c3849f8e0ce754a407e380e6bb$ ls
disk.key enc.disk mountpoint prim.ctx seal.priv seal.pub
14. 加载对象到TPM
命令如下:
tpm2_load -Q --parent-context=prim.ctx --public=seal.pub --private=seal.priv --name=seal.name --key-context=seal.ctx
实际命令及结果如下:
$ sudo /usr/local/bin/tpm2_load --parent-context=prim.ctx --public=seal.pub --private=seal.priv --name=seal.name --key-context=seal.ctx$ ls
disk.key enc.disk mountpoint prim.ctx seal.ctx seal.name seal.priv seal.pub
15. 将对象从易失性空间移存到非易失性空间中
命令如下:
tpm2_evictcontrol --hierarchy=o --object-context=seal.ctx 0x81010002
实际命令及结果如下:
$ sudo /usr/local/bin/tpm2_evictcontrol --hierarchy=o --object-context=seal.ctx 0x81010002
persistent-handle: 0x81010002
action: persisted
16. 用新的密钥替换旧的密钥
命令如下:
tpm2_unseal -Q --object-context=0x81010002 | sudo cryptsetup --key-file=disk.key luksChangeKey enc.disk
实际命令及结果如下:
$ sudo /usr/local/bin/tpm2_unseal --object-context=0x81010002 | sudo cryptsetup --key-file=disk.key luksChangeKey enc.disk
测试中发现此语句并不稳定,有时可以,有时会出现以下错误:
$ sudo /usr/local/bin/tpm2_unseal --object-context=0x81010002 | sudo cryptsetup --key-file=disk.key luksChangeKey enc.disk
此口令无可用的密钥。
17. 彻底清除旧密钥
命令如下:
shred disk.key
rm -f disk.key
实际命令及结果如下:
$ shred disk.key
$ ls
disk.key enc.disk mountpoint prim.ctx seal.ctx seal.name seal.priv seal.pub$ rm -f disk.key
$ ls
enc.disk mountpoint prim.ctx seal.ctx seal.name seal.priv seal.pub
18. 再次将enc.disk虚拟成块设备
命令如下:
sudo losetup /dev/loop0 enc.disk
实际命令及结果如下:
$ sudo losetup /dev/loop0 enc.disk$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 50M 0 loop
nvme0n1 259:0 0 476.9G 0 disk
……/usr/local/opt/home/data
19. 使用保存于TPM中的密钥映射磁盘
命令如下:
tpm2_unseal -Q --object-context=0x81010002 | sudo cryptsetup --key-file=- luksOpen /dev/loop0 enc_volume
实际命令及结果如下:
$ sudo /usr/local/bin/tpm2_unseal --object-context=0x81010002 | sudo cryptsetup --key-file=- luksOpen /dev/loop0 enc_volume$ ls -l /dev/mapper/
总计 0
crw-rw---- 1 root root 10, 236 2月20日 11:14 control
lrwxrwxrwx 1 root root 7 2月24日 10:36 enc_volume -> ../dm-0
20. 再次挂载
命令如下:
sudo mount /dev/mapper/enc_volume mountpoint
实际命令及结果如下:
$ sudo mount /dev/mapper/enc_volume mountpoint$ df -h
文件系统 大小 已用 可用 已用% 挂载点/dev/nvme0n1p4 20G 13G 5.8G 69% /
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 7.7G 176M 7.5G 3% /dev/shm
tmpfs 3.1G 229M 2.9G 8% /run
tmpfs 7.7G 98M 7.6G 2% /tmp
……
tmpfs 1.6G 48K 1.6G 1% /run/user/1000
/dev/mapper/enc_volume 28M 15K 25M 1% /home/penghao/TApp/experiment3/mountpoint
21. 查看挂载点中的内容
命令如下:
ls mountpoint
实际命令及结果如下:
$ ls mountpoint/
lost+found plain.txt$ cat mountpoint/plain.txt
This is my plain text
说明挂载分区已经被新的密钥解密并且其中内容可以被正确读取了。
22. 卸载
命令如下:
sudo umount mountpoint
实际命令及结果如下:
$ sudo umount mountpoint$ df -h
文件系统 大小 已用 可用 已用% 挂载点/dev/nvme0n1p4 20G 13G 5.8G 69% /
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 7.7G 168M 7.5G 3% /dev/shm
tmpfs 3.1G 229M 2.9G 8% /run
tmpfs 7.7G 98M 7.6G 2% /tmp
……
tmpfs 1.6G 48K 1.6G 1% /run/user/1000
23. 关闭加密分区
命令如下:
sudo cryptsetup remove enc_volume
实际命令及结果如下:
$ sudo cryptsetup remove enc_volume$ ls /dev/mapper/
control
24. 卸除回环设备
命令如下:
sudo losetup -d /dev/loop0
实际命令及结果如下:
$ sudo losetup -d /dev/loop0$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 476.9G 0 disk
……/usr/local/opt/home/data
25. 将对象从非易失性空间中移除
命令如下:
tpm2_evictcontrol --hierarchy=o --object-context=0x81010002
实际命令及结果如下:
$ sudo /usr/local/bin/tpm2_evictcontrol --hierarchy=o --object-context=0x81010002
persistent-handle: 0x81010002
action: evicted
完整命令集合:
dd if=/dev/zero of=enc.disk bs=1M count=50dd if=/dev/urandom of=disk.key bs=1 count=32sudo losetup /dev/loop0 enc.disksudo cryptsetup --key-file=disk.key luksFormat /dev/loop0sudo cryptsetup --key-file=disk.key open /dev/loop0 enc_volumesudo mkfs.ext4 -j /dev/mapper/enc_volumemkdir mountpointsudo mount /dev/mapper/enc_volume mountpointsudo sh -c 'echo "This is my plain text" > mountpoint/plain.txt'sudo umount mountpointsudo cryptsetup remove enc_volumesudo losetup -d /dev/loop0
sudo /usr/local/bin/tpm2_createprimary --hierarchy=o --key-context=prim.ctxdd if=/dev/urandom bs=1 count=32 status=none | sudo /usr/local/bin/tpm2_create --hash-algorithm=sha256 --public=seal.pub --private=seal.priv --sealing-input=- --parent-context=prim.ctxsudo /usr/local/bin/tpm2_load --parent-context=prim.ctx --public=seal.pub --private=seal.priv --name=seal.name --key-context=seal.ctxsudo /usr/local/bin/tpm2_evictcontrol --hierarchy=o --object-context=seal.ctx 0x81010002sudo /usr/local/bin/tpm2_unseal --object-context=0x81010002 | sudo cryptsetup --key-file=disk.key luksChangeKey enc.disk shred disk.key
rm -f disk.keysudo losetup /dev/loop0 enc.disksudo /usr/local/bin/tpm2_unseal --object-context=0x81010002 | sudo cryptsetup --key-file=- luksOpen /dev/loop0 enc_volumesudo mount /dev/mapper/enc_volume mountpointls mountpointsudo umount mountpointsudo cryptsetup remove enc_volumesudo losetup -d /dev/loop0tpm2_evictcontrol --hierarchy=o --object-context=0x81010002
相关文章:
物理真机上LUKS结合TPM的测试 —— 使用随机数密钥
1. 创建磁盘空间 命令如下: dd if/dev/zero ofenc.disk bs1M count50 实际命令及结果如下: $ dd if/dev/zero ofenc.disk bs1M count50 输入了 500 块记录 输出了 500 块记录 52428800 字节 (52 MB, 50 MiB) 已复制,0.0587495 sÿ…...
Linux USB 开发指南
文章目录Linux USB 开发指南1 前言1.1 文档简介1.2 目标读者1.3 适用范围2 模块介绍2.1 模块功能介绍2.2 相关术语介绍2.3 模块配置介绍2.3.1 Device Tree 配置说明2.3.2 board.dts 配置说明2.3.3 kernel menuconfig 配置说明2.4 源码结构介绍2.5 驱动框架介绍2.6 Gadget 配置2…...
FreeRTOS入门(03):队列、信号量、互斥量
文章目录目的队列(queue)信号量(semaphore)互斥量(mutex)互斥量递归互斥量总结目的 FreeRTOS提供给用户最核心的功能是任务(Task),实际项目中通常会有多个任务ÿ…...
Biome-BGC在模拟过程中,如何使用Linux、Python等,完成前处理和后处理工作???
在Biome-BGC模型中,对于碳的生物量积累,采用光合酶促反应机理模型计算出每天的初级生产力(GPP),将生长呼吸和维持呼吸减去后的产物分配给叶、枝条、干和根。生物体的碳每天都按一定比例以凋落方式进入凋落物碳库;对于水份输运过程…...
【unittest学习】unittest框架主要功能
1.认识unittest在 Python 中有诸多单元测试框架,如 doctest、unittest、pytest、nose 等,Python 2.1 及其以后的版本已经将 unittest 作为一个标准模块放入 Python 开发包中。2.认识单元测试不用单元测试框架能写单元测试吗?答案是肯定的。单…...
京东测开岗3+1面经+经验分享,拿到offer,月薪34k....
现在,招聘黄金时间已经来临,在网上看了很多大佬的面经,也加了很多交流群,受到了很多朋友的提点,今天终于轮到我来分享面经啦,之前面试了几家公司,最后拿到了京东测试岗的 offer,这里…...
后端接收格式为x-www-form-urlencoded的数据
1.x-www-form-urlencoded是什么? x-www-form-urlencoded纸面翻译即所谓url格式的编码,是post的默认Content-Type,其实就是一种编码格式,类似json也是一种编码传输格式。form表单中使用 form的enctype属性为编码方式࿰…...
LeetCode 707. 设计链表
LeetCode 707. 设计链表 难度:middle\color{orange}{middle}middle 题目描述 设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:valvalval 和 nextnextnext。valvalval 是当前节点的值,nextnextnext 是指向下…...
HTTP的主要作用是什么
1、客户与服务器建立连接; 2、客户向服务器提出请求; 3、服务器接受请求,并根据请求返回相应的文件作为应答; 4、客户与服务器关闭连接。 HTTP的性质: 1、HTTP是一种无状态协议,即服务器不保留与客户交…...
SpringBoot系列-- @Enable 模块驱动
Enable 模块驱动 Enable 模块驱动是以 Enable 为前缀的注解驱动编程模型。所谓 “模块” 是指具备相同领域的功能组件集合,组合所形成一个独立的单元。比如 WebMVC 模块、AspectJ 代理模块、Caching (缓存)模块、JMX (Java 管理扩…...
PHP程序员适合创业吗?
创业是一件自然而然的事,不需要人为选择。 只要你是一个努力能干主动的人,当你在一个行业深耕5年之后,就会发现人生发展的下一步就是创业。当然如果行业合适的话。 什么叫行业合适呢? 就是创业的成本并不那么高,不需…...
2023年CDGA考试-第12章-元数据(含答案)
2023年CDGA考试-第12章-元数据(含答案) 单选题 1.元数据架构的类型主要有四种下列哪项不属于分布式元数据架构的优点? A.减少了批处理 B.元数据的质量完全取决于源系统 C.最大程度的减少了实施和维护所需的工作量 D.元数据总是尽可能保持最新且有效 答案 B 2.元数据管理是…...
数据结构之顺序表篇
一、顺序表概念 二、顺序表各类接口实现 *顺序表初始化 **顺序表销毁 ***顺序表插入操作 ****顺序表删除操作 *****顺序表查找操作 ******顺序表实现打印操作 三、顺序表整体实现源码 *SeqList.h **SeqList.c ***test.c 一、顺序表概念 讲顺序表之前先引入线性表概念ÿ…...
ZBC通证月内已翻倍,Nautilus Chain 上线前夕的“开门红”
近日,Zebec Protocol生态通证ZBC迎来了大涨,据悉该通证月内最高涨幅接近了100%,为一众投资者、社区用户、Zepoch节点等带来了可观的回报,并为生态发展注入了十足的信心。我们看到,Zebec Protocol生态在近期宣布了“销毁…...
人工智能练习题:激活函数需要满足的条件、提高CNN的泛化能力、CNN输出特征图大小计算
文章目录1.激活函数需要满足的条件2.提高CNN泛化能力的方法3.CNN输出特征图大小计算第一次用ChatGPT,不得不说在处理大学生作业上,ChatGPT比国内的作业软件好用多了(感叹)。 1.激活函数需要满足的条件 通常情况下,激活…...
KingbaseES Json 系列三:Json数据操作函数一
KingbaseES Json 系列三--Json数据操作函数一(JSONB_EACH,JSONB_EACH_TEXT,JSONB_OBJECT_KEYS,JSONB_EXTRACT_PATH,JSONB_EXTRACT_PATH_TEXT,JSON_EACH,JSON_EACH_TEXT,JSON_OBJECT_KEYS,JSON_EXTRACT_PATH,JSON_EXTRACT_PATH_TEXT) JSON 数据类型是用来存储 JSON(JavaScript O…...
《设计模式》单例模式
《设计模式》单例模式 单例模式是一种常用的设计模式,其主要优点有: 提供了对唯一实例的全局访问。单例模式保证了整个系统中只有一个实例,这样就可以方便地对该实例进行访问和操作,避免了多个实例之间的冲突和不一致。避免了重…...
C/C++每日一练(20230224)
目录 1. 字符串排序 2. Excel表列名称 3. 颠倒二进制位 附录: 位移运算符 左移运算符<< 1.无符号 2.有符号 右移运算符>> 1.无符号 2.有符号 程序测试 1. 字符串排序 编写程序,输入若干个字符串。 要求: (1&#x…...
基于YOLO的酸枣病虫害检测识别实践
在我前面的博文中对于农作物病虫害的检测识别已经做过了,不过那个主要是针对水稻的,文章如下:《基于yolov5的轻量级水稻虫害目标检测项目实践》感兴趣的话可以自行移步阅读。这里主要是针对酸枣常见的几种病虫害检测检测识别,首先…...
WAF:ModSecurity on Nginx(15)
预备知识 Nginx概述 Nginx ("engine x") 是一个高性能的HTTP和 反向代理 服务器,也是一个 IMAP/POP3/SMTP服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代…...
【仅限头部车企工控厂商内部流通】C++27静态反射安全合规包:覆盖MISRA C++:2023 Annex A.12及AUTOSAR C++14兼容性桥接层
第一章:C27 静态反射工业应用案例C27 将正式引入标准化的静态反射(Static Reflection)核心特性,基于 std::reflexpr 和反射元对象模型(ROM),使编译期类型结构可被直接查询与遍历,无需…...
OpenClaw开发环境配置:千问3.5-9B辅助的IDE插件管理
OpenClaw开发环境配置:千问3.5-9B辅助的IDE插件管理 1. 为什么需要AI辅助的IDE管理 作为一个长期在多个项目间切换的全栈开发者,我深受开发环境配置问题的困扰。每次换新电脑或者重装系统,光是配置VSCode插件和项目依赖就要耗费大半天时间。…...
wUU代码混淆实战指南:使用Obfuscar构建坚不可摧的安全防线
在当今数字化时代,保护.NET应用程序的源代码安全变得尤为重要。你是否担心自己的知识产权被轻易窃取?是否希望防止竞争对手通过反编译分析你的核心业务逻辑?今天,我将为你详细介绍一款强大的开源混淆工具——Obfuscar,…...
74HC595移位寄存器驱动原理与CrazyHC595库深度解析
1. CrazyHC595库概述:面向嵌入式工程师的74HC595移位寄存器驱动深度解析74HC595是工业界最经典、应用最广泛的8位串行输入/并行输出移位寄存器芯片之一。其核心价值在于以3根GPIO线(数据、时钟、锁存)扩展出8个可独立控制的数字输出通道&…...
PLC课程设计 - 基于智能立体4层停车库的设计
题目:PLC课程设计-基于智能立体4层停车库的设计 仿真软件博图18 资料包括:博图软件仿真流程图开题ppt课设报告参考 实现功能: 立体车库,有四层,可以实现对应位置的存车及取车功能 当存车的时候,首先需要判断…...
不止System.Memory!OpenCVSharp依赖的这几个DLL报错,一个方法全搞定
深度解析OpenCVSharp依赖冲突:从System.Memory到通用解决方案 当你兴致勃勃地准备运行一个基于OpenCVSharp的计算机视觉项目时,突然弹出的"DLL加载失败"或"版本不匹配"错误信息就像一盆冷水浇灭了热情。System.Memory只是众多潜在问…...
Windows10下PaddleOCR与Python3.8.5的完美搭配:从安装到实战OCR识别
Windows10下PaddleOCR与Python3.8.5的深度实践指南 在数字化办公和自动化流程日益普及的今天,光学字符识别(OCR)技术已经成为从图像中提取文本信息的重要工具。PaddleOCR作为百度开源的OCR工具库,凭借其出色的识别准确率和易用性…...
实战应用:定制专属labelimg,快速生成YOLO格式车辆检测数据集
实战应用:定制专属labelimg,快速生成YOLO格式车辆检测数据集 在计算机视觉项目中,数据标注是模型训练的基础环节。最近我在做一个车辆检测项目时,发现通用的标注工具往往无法完全满足特定需求。比如我需要同时生成PASCAL VOC和YO…...
2 轻量设备鸿蒙应用开发极简流程 | 鸿蒙开发筑基实战
轻量设备鸿蒙应用开发极简流程 | 鸿蒙开发筑基实战 作者:杨建宾(华夏之光永存) 摘要 本文面向鸿蒙轻量设备(HiSpark系列、穿戴设备、IoT终端)开发者,拆解从工程创建到上线的全流程。聚焦轻量设备硬件资源有…...
安防弱电智能化VISIO图例实战指南:从入门到精通的设计技巧
1. VISIO在安防弱电设计中的核心价值 第一次接触安防弱电智能化设计时,我被各种复杂的系统连接关系搞得头晕眼花。直到发现VISIO这个神器,才真正体会到什么叫"一图胜千言"。不同于普通CAD软件,VISIO最大的优势在于它专为系统图设计…...
