ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

等保三级数据传输安全:完整性与保密性的区别与落地实践

等保三级数据传输安全:完整性与保密性的区别与落地实践 写这个系列的时候我一直在跟测试环境和生产环境的同事反复确认同一件事你们验收“数据传输安全”的时候是真的把“完整性”和“保密性”当成两个独立的指标在验证还是统称为“做了加密就算过关”说实话我在等保三级整改项目里见过太多人把这两个词混在一个“我上了HTTPS”的口径里。这篇作为系列的第三篇专门把等保三级数据传输过程中的完整性与保密性拆开来讲顺便把我在真实环境里踩过的坑、沉淀下来的自查清单一起整理出来。先说明一下这里聊的是等保三级在通信传输层面经常被抽查的那部分内容不是物理层信号完整性也不是type c快充和传输切换那种硬件话题。等保三级语境下的“数据传输完整性”指的是数据从A点发到B点的过程中有没有被篡改、被插入、被重放而“保密性”指的是数据在链路上是否可见、是否会被窃取。两个问题可能同时存在但解决它们的技术手段并不完全一样这也是很多整改方案漏配置的根源。1. 先搞清楚等保三级对传输链路到底要什么每次做等保三级整改我习惯先翻一遍控制项原文。现行标准里对于“安全通信网络”和“安全计算环境”都写得很明确应采用校验技术或密码技术保证通信过程中数据的完整性应采用密码技术保证通信过程中数据的保密性。很多人看到这两句话第一反应就是“那我申请一张HTTPS证书”实际上中间漏了一条很关键的信息校验技术、密码技术、完整性、保密性这些词在标准里对应着不同的控制点和不同的实现方式。你在合规评审时如果只跟测评方说“我们用了HTTPS”通常会被继续追问HTTPS用的是哪个TLS版本握手协议里是否禁用了弱加密套件业务API在网关层解密之后内部链路是不是又变成了明文服务端返回给客户端的响应体是否能被中间人直接抓包阅读这些问题全部回答清楚才算真正把传输安全这一项做扎实。1.1 二级和三级对传输安全的要求差在哪儿经常有朋友问我们单位做过二级等保现在要升三级传输安全部分有什么不同从技术实现上讲二级也会提出保密性和完整性的要求但是没有三级那么强调“密码技术”和“强制校验”。三级在测评时更看重你是否有明确的密码应用方案、密钥管理流程、以及可验证的日志记录。也就是说二级可能你做一个简单的报文哈希校验也能解释过去但三级基本要求用密钥化的校验算法比如HMAC或数字签名而不是裸哈希。另一个容易忽略的差异是范围。三级整改涉及的不仅是用户访问业务那一段公网链路还包括内网不同安全域之间、微服务之间、运维管理通道之间的数据传输。内网不等于私密安全区我在项目里见过不止一次反例前端到网关是HTTPS网关到后端微服务就变成了明文HTTP然后中间某台服务器被横向移动拿到权限业务数据就全裸奔了。等保三级测评时测评员会特别关心加密链路是否在整个数据生命周期里存在断裂点也就是所谓“加密只做了一半”。1.2 保密性和完整性是两条不同的技术路线我经常用一个比喻来解释这两个概念保密性是把内容锁进保险柜完整性是在信封口糊上防伪封条。保险柜保证别人看不见内容但如果有权限的人打开柜子把里面的金额改了收件人并不知道封条则保证内容一旦被改动收信人立刻能发现。所以“上了加密”并不等于“能发现篡改”反过来“做了完整性校验”也不等于“内容不会被偷看”。一个很常见的反面案例是很多老系统的登录接口用户口令经过对称加密传输但是如果这个加密算法是ECB模式或者没有带MAC的CTR模式攻击者就可以在不知道密钥的情况下对密文做比特翻转把某些字段改成自己想要的值这种攻击在密码学里叫密文可操控性攻击。因此等保三级真正落地时通常要求要么用TLS/SSL这种自带完整性的安全协议要么在报文层面做“加密MAC”的组合处理而且这两个动作必须放在同一个密码方案里。现在更推荐的做法是使用AEAD加密模式比如GCM它一次性同时解决保密性和完整性后面我会单独展开。1.3 一个快速自查表先看看自己做到哪一步如果你正在整改不知道怎么判断现状可以先按下面这个表做个粗筛。这个表是结合我参与过的几个三级测评项目总结出来的不一定覆盖全部场景但能快速暴露问题检查项达标状态说明对外访问是否使用HTTPS/TLS是 / 否至少TLS1.2及以上推荐TLS1.3是否禁用了RC4、3DES、CBC等弱套件是 / 否建议使用GCM或CHACHA套件客户端是否严格校验服务端证书是 / 否尤其注意移动端和IoT设备网关解密后后端链路是否重新加密是 / 否内部链路同样需要完整性保护接口层是否对请求和响应做签名校验是 / 否至少要覆盖关键业务字段是否防重放是 / 否时间戳nonce或者序列号敏感字段是否出现在URL查询参数中是 / 否应放在请求体或加密头密钥是否明文写死在代码或配置里是 / 否应使用KMS或配置中心加密日志中是否记录完整实体数据是 / 否应脱敏后再记录证书和密钥是否有轮换与废弃流程是 / 否证书更新、私钥归档销毁我见过不少团队信心满满地填“全达标”结果测评方打开抓包工具一看响应体里明文返回用户手机号、身份证号申请单里还带签名和时间戳但签名校验逻辑只在前端做后端完全没验。这类情况先别急着写整改方案把上面这张表逐项用实际抓包结果验证一遍才知道真正的差距在哪里。2. 传输完整性的技术实现与常见误区2.1 完整性不是“加个哈希”这么简单很多开发同学最初对完整性的理解就是“给报文算一个MD5跟着报文一起发过去对方收到后再算一遍对上了就说明没被改”。这是十年前的做法放在等保三级场景里基本不合格原因有三个MD5已经被验证存在碰撞攻击SHA1也有理论攻击现在一般不建议单独使用最关键的是裸哈希无法抵御“替换攻击”。如果攻击者能把报文内容改了那他同样可以重新算一个新的哈希值填进去接收方依然校验通过。所以完整性校验必须引入“只有通信双方才知道的秘密”也就是密钥。用密钥参与的哈希算法就是HMAC全称是Keyed-Hash Message Authentication Code。HMAC不等于简单地把密钥拼在明文前面再算哈希它有标准的填充和迭代结构能防止长度扩展攻击。在等保三级整改中如果你不想引入复杂的PKI体系使用HMAC-SHA256作为接口防篡改手段是成本最低且能被测评机构接受的做法。信号完整性这个词有时候会被拉进来混淆概念。做硬件的人谈信号完整性关注的是PCB走线上的反射、串扰、眼图等保三级谈的数据传输完整性关注的是协议层和报文层的完整性保护。两码事别在评审材料里混着写测评员看到会觉得你连基本概念都没理清。2.2 用 HMAC 给 API 接口做防篡改签名我习惯给实际的API接口设计一个统一的签名算法规则不复杂但必须把所有可能影响业务结果的字段都覆盖进去。一般至少包括请求方法、请求路径、请求体摘要、时间戳、随机数然后使用共享密钥计算HMAC-SHA256。下面是一段简化版示例用的是Python换成Java、Golang也很容易对应import hmac import hashlib import time import secrets import base64 SECRET_KEY breplace-with-a-strong-random-key def build_signature(method, path, body, timestamp, nonce): body_digest hashlib.sha256(body.encode(utf-8)).hexdigest() payload |.join([ method.upper(), path, body_digest, timestamp, nonce ]) digest hmac.new(SECRET_KEY, payload.encode(utf-8), hashlib.sha256).digest() return base64.b64encode(digest).decode(utf-8)服务端收到请求后用同样的规则重新计算签名再用hmac.compare_digest做安全比较而不是直接使用。在Python里在字符串比较时可能会被侧信道攻击拿到时间差信息虽然实际攻击难度很高但等保测评会让你改掉所以从一开始就不要养成坏习惯。签名计算时还有一个细节请求体摘要之前最好先对body做规范化处理。JSON里的字段顺序、空格、空值都有可能让客户端和服务端算出来的SHA256不一致导致合法请求也验签失败。我的习惯是服务端不依赖前端传来的body原文而是把原始body字节流先存下来再拿原始字节流去算摘要。如果你用的是微服务框架还需要确保编码格式统一统一用UTF-8不要出现GBK和UTF-8混着解析的情况。2.3 我踩过的三个完整性翻车现场第一个翻车现场是只校验了请求方向没校验响应方向。测评员拿着抓包工具截获了服务端返回的一次转账成功响应把响应里的金额字段改大再发给客户端。客户端App以为是后端返回的合法数据直接给用户显示“转账20000元成功”。后端其实已经转账了1000元但用户侧展示被篡改问题出在响应体也没有签名校验。整改时要求响应体同样参与HMAC计算客户端在渲染前必须验签。第二个翻车现场是防重放做得太简单。只加了时间戳没有随机数nonce结果攻击者把同一个请求反复发送后端只要时间戳还在五分钟窗口内就会不断执行同一个操作。等保三级对重放攻击的要求是很明确的必须要有随机数或者序列号机制。时间戳只能防止“旧数据重放”不能防止“窗口期内重放”。我把nonce存到Redis里设置和签名有效期一致的过期时间比如300秒这样同一个nonce只会被接受一次。第三个翻车现场发生在对称加密模式的选型上。有些老项目还在用AES-CBC做接口加密CBC模式本身不提供完整性保护攻击者可以通过翻转密文分组里的某些比特来影响解密后的明文。正确做法是改用AEAD模式比如AES-GCM、SM4-GCM或者使用“先加密再计算MAC”的组合方式。后来我写整改方案时统一推荐GCM因为它一次处理完加密和完整性标签性能上也比“加密一次再单独算HMAC”更优。3. 传输保密性的技术路线与现实选择3.1 链路加密 vs 应用层加密 vs 消息级加密保密性不是非黑即白的问题关键看数据暴露面在哪里。我把常见方案分成三类链路加密、应用层加密、消息级加密。链路加密的代表是IPSec它把两台网络设备之间的整个IP包都封起来对网络层透明。好处是应用无感知坏处是部署复杂、密钥管理重而且只能在固定的网关或主机之间起作用。应用层加密的代表是TLS/HTTPS它保护“客户端到服务端”这一段链路是目前等保三级最主流的选择。消息级加密则是在应用层之上对单个业务报文做加密和签名即使中间链路有人能看到TCP内容也无法解析出真实业务字段。做等保三级不一定要三种都上但至少要明确自己的数据边界在哪里。如果你的业务完全运行在可控的云VPC内网里终端用户通过前端接入那“终端到网关HTTPS 微服务间mTLS”通常够用。如果业务涉及第三方系统互联大家不在一个信任域里那消息级加密和签名几乎是必须的否则你在网关处解密之后后面的数据对第三方链路上的设备就是透明的。3.2 AEAD 模式解决“又要保密又要防篡改”的问题等保三级整改里我最喜欢推荐AEAD模式也就是带关联数据的认证加密。传统做法是先AES加密得到密文再对密文计算HMAC两步操作分开做容易在实现顺序上出错而且要多维护一套密钥。AEAD把两个步骤合并底层用对称算法配合认证机制一次调用直接输出“密文认证标签”。接收方用同样的密钥和初始向量去解密同时校验认证标签标签不一致就直接返回失败不输出任何解密后的明文。GCM是AEAD里最常用的实现CTR模式加密加上GHASH做认证性能很好Intel和ARM芯片都有硬件指令加速。你在做国密改造时SM4-GCM的定位和AES-GCM完全一样它就是SM4分组密码跑在GCM工作模式下同时具备机密性和完整性。所以如果有人问“sm4-gcm具备机密性和完整性吗”答案是肯定的这也是它适合作为等保三级传输安全加密算法的原因。但要注意一点GCM的随机数IV绝对不能重复使用。AES-GCM的IV通常是96位随机数如果两个消息用了同一个IV和同一个密钥攻击者可以直接恢复出认证密钥整个安全性崩塌。所以生产环境里IV要么使用高质量的随机数生成器要么使用单调递增的计数器并且要和密钥生命周期绑定管理。3.3 国密改造中 SM4-GCM 的定位与优势很多行业在做等保三级时同时会面临国密合规的要求比如金融、政务、能源这类重点行业。国密算法体系里SM2用于非对称加签名SM3用于哈希SM4用于对称加密。SM4是128位分组密码算法密钥长度128位安全性满足当前等保三级的商用密码应用要求。早期国密改造方案里很多人习惯用SM4-CBC因为参考资料多、旧硬件支持好但CBC模式没有完整性保护整改时又额外叠加SM3做哈希两个算法加在一起既繁琐又容易出错。SM4-GCM出来后加密和完整性一次完成方案简洁测评材料也好写。从性能角度看SM4-GCM的纯软实现比AES-GCM略慢但多数业务系统瓶颈根本不在这里。我做过一次压测普通台式机上SM4-GCM每秒能跑几百MB等保三级常见的业务接口流量完全没压力。如果流量极大可以用支持国密算法硬件加速的密码机或网卡但这通常是大规模系统的选择普通自建系统不必第一时间上硬件。还有一点需要提醒国密改造不是只把算法库从AES换成SM4就完事TLS握手阶段如果用国密套件还需要服务端支持SM2证书和相应的密码套件。如果只是内部接口传输采用“SM4-GCM加密请求体 SM3摘要或HMAC”的方案比硬上国密TLS要轻量很多也更容易落地。4. 落地实操给一套自研 HTTP 接口补全传输安全4.1 场景设定假设现在有一套自研系统前端是浏览器或App后端是Java/Python服务对外暴露HTTP API接口没有商业WAF也没有专门的密码设备。这套系统需要满足等保三级对数据传输完整性和保密性的要求。基于我实际项目经验不用大动干戈改架构三步就可以达到基本合格状态第一步配置强TLS第二步给API加HMAC签名和防重放第三步把密钥和证书管理规范化。下面逐步展开。4.2 步骤一先把 HTTPS 与强加密套件配好这一步看似简单但经常有配置不完整的情况。以Nginx为例最低限度要做这几件事监听443端口并开启HTTP/2限制TLS协议版本为1.2和1.3禁用不安全的加密套件开启HSTS响应头。参考配置片段如下server { listen 443 ssl http2; server_name api.example.com; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; add_header Strict-Transport-Security max-age31536000; includeSubDomains always; }这里的ssl_prefer_server_ciphers off是为了让客户端能优先使用自己的安全套件列表避免服务端强制选择旧套件。如果你的客户端是自研App强烈建议在代码里做证书校验不要关闭证书验证。很多人为了测试方便把verifyFalse或者setHostnameVerifier(..., null)带到生产环境这在测评时会被一票否决。配置完后用下面命令检查一下实际协商结果openssl s_client -connect api.example.com:443 -tls1_2看输出里的Cipher是否为GCM类套件同时看Server Certificate是否有效期内。如果这一步都过不了后面做得再多也没用。4.3 步骤二给请求/响应报文加签名与防重放如果服务都在内网HTTP明文链路短可以先靠TLS兜底。但一旦涉及跨安全域或第三方接口就必须上消息级签名。我沿用第2节里的HMAC算法在后端增加一个验签函数import time def verify_signature(incoming_signature, method, path, body, timestamp, nonce): # 1. 时间窗校验防止旧消息重放 if abs(time.time() - int(timestamp)) 300: return False # 2. nonce 去重防止窗口内重放 if nonce in seen_nonces: return False seen_nonces.add(nonce) # 3. 重新计算签名并安全比对 expected build_signature(method, path, body, timestamp, nonce) return hmac.compare_digest(incoming_signature, expected)seen_nonces在单机场景下可以用内存集合但生产环境一般放到Redis并设置TTL比如和签名时间窗一样设为300秒。这样可以避免单点重启后nonce集合丢失导致重放。同时在响应体里也要加上签名头比如X-Response-Signature客户端渲染前必须验签。我建议把签名逻辑封装成独立SDK客户端和服务端在项目里同时引用这样规则变更时双方只要升级SDK不用逐一改接口代码。签名规则里还有一个容易被忽略的点请求头里的业务自定义字段也要纳入签名。比如有些系统用X-User-Id来标识当前用户如果这个字段不参与签名攻击者可能把别人请求头里的用户ID替换成自己的后端又只信任这个头就会发生越权。所以设计签名覆盖范围时宁可多覆盖几个固定header也不要只签请求体。4.4 步骤三密钥、证书与日志的日常管理密钥管理是等保三级测评的重点关注对象也是很多开发团队最薄弱的环节。常见的错误是前端代码里硬编码一个AES密钥用于加密请求体这个密钥只要从App逆向后端就会被攻击方一锅端。正确做法是对称加密的传输密钥不要直接分配给客户端而是通过密钥协商或动态下发机制获得。如果不想自己造轮子可以把密钥托管在云厂商KMS或自建Vault里配置中心只存取密文避免把明文密钥写进配置文件。证书轮换也必须建立自动化流程。我见过一次事故服务器证书过期后运维手动重新申请结果只更新了前端节点后端某个内网域名用的还是旧证书导致服务间调用间歇性失败。后来我在整改方案里加了证书有效期监控提前30天告警并规定所有证书必须统一存放在一个受控目录分发时必须校验证书指纹。另外私钥备份要单独加密存放销毁时要走安全擦除流程不能直接把服务器镜像留在云盘里不管。日志同样需要注意。传输安全做得太好但日志乱记也容易把数据泄露出去。请求日志里不要记录完整请求体尤其不能记录密码、手机号、身份证号这些敏感字段。如果为了排查问题必须记录那就做脱敏处理比如手机号只保留前三位后两位。测评机构检查日志时会关注“是否记录了超范围敏感信息”这既是合规要求也是安全底线。5. 常见问题与排查技巧实录5.1 抓包后依然看到明文很多人整改完HTTPS后自己用Fiddler或Wireshark一抓发现依然能看到明文于是怀疑证书配置没生效。这种情况通常不是证书问题而是客户端请求根本没走HTTPS。常见原因有三个第一前端代码里有硬编码的http://接口地址服务端虽然支持HTTPS但客户端只走HTTP第二页面里混合内容主页面是HTTPS但图片、接口请求还是HTTP第三App没有做网络安全配置Android系统允许HTTP明文流量。排查思路很直接用curl强制请求一遍HTTP看服务端是否返回301或308重定向到HTTPS检查前端代码里的接口地址是否全部为https://Android项目检查AndroidManifest.xml里是否配置了usesCleartextTraffictrue有的话要摘掉。整改完后再抓包理想状态是只能看到TLS应用数据看不到任何业务字段。5.2 完整性校验偶发失败多半是时间戳和编码在作妖接口验签时偶尔出现合法请求失败的情况很多次我们查到最后问题不在签名算法而在时间戳和编码上。时间戳问题通常由服务器时区不一致引起比如客户端服务器用的是UTC后端服务器用的是本地时间如果双方用time.time()获取的是绝对秒数还好但有人会把时间戳格式化成yyyy-MM-dd HH:mm:ss再拼接进签名两个服务的时区配置不同就直接验不过。规范做法是签名里只使用Unix时间戳秒或毫秒避免时区干扰。编码问题则常出现在JSON序列化上。客户端用的是Gson服务端用的是Jackson各自序列化后的字段顺序不同导致body摘要不一致。我曾经为这个问题折腾了一下午最后发现是后端框架在接收请求时自动把body里的转义字符重新解析了一遍和客户端发出来的原始字节流不完全一致。解决办法是在签名规则里明确“签名对象是收到时的原始字节流”不要在框架层做任何预处理如果框架一定要解析就把原始body先保存到变量里再进入业务处理。5.3 测评机构眼中的“传输安全”到底怎么测参加过几次等保三级测评后我总结了一下测评员对传输安全最常做的几项验证动作。他们不一定会写代码攻击你但一定会抓包、看配置、查文档甚至会直接翻你的代码仓库。测评动作检查目的常见扣分点用抓包工具截取登录接口流量确认是否真正使用TLS登录请求仍走HTTP用openssl检查证书链确认证书有效且受信自签名证书或者证书已过期查看TLS协议与加密套件确认未使用弱套件支持TLS1.0、CBC套件测试接口是否可重放确认有防重放机制同一请求重复发送成功查看配置文件确认密钥未硬编码配置项里有明文密码或密钥翻代码里的工具类确认摘要算法和加密模式用MD5做接口签名CBC加密无MAC读取日志输出确认敏感数据已脱敏日志里出现银行卡号、密码如果你能主动提供一份传输安全自测报告把以上几点用截图和命令输出证明给测评员看整个沟通成本会低很多。我第一次做三级项目时就是等到测评机构发现问题后才开始补材料后来改成“先自查自证”整改周期缩短了不少。5.4 梳理一个一键自查的命令集合写到最后再分享一个我日常排查用的命令集合能在半小时内覆盖大部分传输安全自查项。检查HTTPS是否生效以及响应头curl -I https://api.example.com/验证TLS版本和加密套件openssl s_client -connect api.example.com:443 -tls1_3查看证书详情与有效期openssl s_client -connect api.example.com:443 -servername api.example.com | openssl x509 -noout -dates -subject -issuer测试HTTP是否会强制跳转HTTPScurl -I http://api.example.com/查看返回头中是否包含安全性字段curl -I https://api.example.com/ | grep -iE strict-transport-security|x-content-type-options这几条命令的输出直接贴进整改凭证即可。等保三级传输安全好不好不能靠嘴说所有结论都应该能在抓包和协议协商结果里找到证据。我在实际项目里最深的体会就是测评员不是来“为难”你的他也是在找证据你的证据链条越完整、越清晰双方都轻松。
返回列表