• 请不要在回答技术问题时复制粘贴 AI 生成的内容
nilai
V2EX  ›  程序员

除了 https,有什么防止网络监听的成熟方案

  •  1
     
  •   nilai · Mar 1, 2017 · 7111 views
    This topic created in 3363 days ago, the information mentioned may be changed or developed.
    最近写了个小项目, 要求不用 https (丫的,就是这么奇葩), 要求保证通信的安全, 防窃听

    浏览器 ----> 服务端 (这个倒好做, RSA 浏览器公钥加密, 服务端私钥解密。中间人没有私钥,就算窃听到数据也解密不出来)。


    服务端 ------> 浏览器 (目前仅应付一下 就是 服务端发送数据时 AES 加密, 浏览器 AES 解密, 这样明显的缺点就是中间人分析一下网页,就知道 AES 的 KEY,然后就能解密出对应的数据了,因为不管怎么着, 数据都得在浏览器正常展示出来)

    后来觉得 DH 算法应该可以, 但是实现过程略显麻烦,对 web 类的纯 HTTP 应用不是很适合,


    说了这么多, 求指教。
    Supplement 1  ·  Mar 2, 2017
    昨晚有事, 一早来看回复了这么多, 大家的回复我都看了, 首先这需求的确奇葩,这不是重点,假设就按这需求来,也不要问为什么
    首先允许中间人窃听流量(这是非常正常的事)(像什么端口镜像之类等等) (小到公司内网出口,大到运营商出口等,都会分析网络流量)
    其次是防止通过窃听流量还原出明文,不防篡改内容、证书等(敲黑板。。。。)
    (在浏览器本身,比入注入进浏览器内存获取未加密数据不在考虑范围, 通过浏览器本身的一些插件扩散等都不在考虑范围)
    (什么中间人公钥私钥替换中转也都不在此考虑范围)
    xqin 应该是明白我的意思, 你的 DEMO 代码我也看了, 我目前大概也是这样做的, 不过没有用 QQTEA 算法, 还是用标准的 AES , 跟你的方案不同的是我用了 localStorageService 把本地解密的 KEY 缓存在浏览器内存中, 另一直也在准备用 ecdh 方案来实现密钥交换
    75 replies    2017-03-02 10:27:38 +08:00
    wwqgtxx
        1
    wwqgtxx  
       Mar 1, 2017 via iPhone
    可以试试,自己用 js 实现 tls ,底层用 websockets
    nilai
        2
    nilai  
    OP
       Mar 1, 2017
    @wwqgtxx 天啦。。。。。。。。
    RqPS6rhmP3Nyn3Tm
        3
    RqPS6rhmP3Nyn3Tm  
       Mar 1, 2017 via iPhone
    http 页面不防篡改,中间人也可以给你的服务器 /浏览器返回一个假的证书啊
    wevsty
        4
    wevsty  
       Mar 1, 2017   ❤️ 1
    如果不想使用现成的 TLS ,那就只能自己在 socket 上实现一遍 TLS 了。
    nilai
        5
    nilai  
    OP
       Mar 1, 2017
    @BXIA 暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。
    nilai
        6
    nilai  
    OP
       Mar 1, 2017
    @wevsty 在 github 上看了下, 还真有人用 JS 自己生成了一个 TLS 跑在 HTTP 下。。
    kindjeff
        7
    kindjeff  
       Mar 1, 2017 via iPhone
    @nilai 给了假证书之后照样监听啊
    nilai
        8
    nilai  
    OP
       Mar 1, 2017
    @kindjeff 暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。
    chinajik
        9
    chinajik  
       Mar 1, 2017
    巧了。。 最近也是在做这个。。目前也是 https +rsa
    enenaaa
        10
    enenaaa  
       Mar 1, 2017
    每次刷新都用密码登陆
    honeycomb
        11
    honeycomb  
       Mar 1, 2017
    @nilai 给了假证书之后就可以监听了
    miao1007
        12
    miao1007  
       Mar 1, 2017 via Android
    报文 rsa 加密后 base64
    nilai
        13
    nilai  
    OP
       Mar 1, 2017
    @honeycomb 暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。
    wevsty
        14
    wevsty  
       Mar 1, 2017   ❤️ 1
    @nilai TLS 的实现是很复杂的,自己实现的安全性往往没有使用现成的套件安全,高效。除非特别需要,否则强烈不推荐自己实现这样的过程,不明白这样做的目的是什么?
    paradoxs
        15
    paradoxs  
       Mar 1, 2017   ❤️ 1
    提出这种要求的人, 能回答一下, 如果 https 被破解了, 就你做的这点加密, 能扛得住别人几分钟的攻击?
    RqPS6rhmP3Nyn3Tm
        16
    RqPS6rhmP3Nyn3Tm  
       Mar 1, 2017 via iPhone   ❤️ 1
    @nilai 都给你了假证书了,监听岂不是再简单不过的事情?
    用自己的证书解密再转发给你的服务器不就好了,这就是 MITM 在安全性被妥协的环境下的典型监听方法
    nilai
        17
    nilai  
    OP
       Mar 1, 2017
    @paradoxs 哈哈, 歪楼了
    nilai
        18
    nilai  
    OP
       Mar 1, 2017
    @BXIA 暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。 不用科普 MITM ,
    rogerchen
        19
    rogerchen  
       Mar 1, 2017   ❤️ 4
    @nilai
    什么叫浏览器到服务器简单?浏览器会用你的私有协议?还是你要自己写一个浏览器?
    RSA 是用来传 key 的, payload 也用 RSA 来传?难道你的客户都是四路 E7 配置起跳?
    拿到 AES 密文和明文就能猜出 key ? 抗 CPA 是吃翔的?


    不是我嘲讽楼主,密码学入门知识都不懂也想撸密码学基础架构,这种一般叫 troll 吧。
    LGA1150
        20
    LGA1150  
       Mar 1, 2017 via Android
    XMPP+TLS
    jybox
        21
    jybox  
       Mar 1, 2017 via iPhone
    @BXIA 发了假证书就已经是篡改行为了呀,楼主说不考虑篡改只考虑窃听
    snnn
        22
    snnn  
       Mar 1, 2017 via Android
    看来你还不知道啥是消息完整性
    liyvhg
        23
    liyvhg  
       Mar 1, 2017 via Android
    私有协议,全程 websocket
    hjc4869
        24
    hjc4869  
       Mar 1, 2017
    客户端可以,浏览器不行。
    RqPS6rhmP3Nyn3Tm
        25
    RqPS6rhmP3Nyn3Tm  
       Mar 1, 2017 via iPhone
    @jybox 我理解的篡改内容是篡改传输的内容,而非握手阶段的信报。如果是这样的话,确实算是篡改了。
    不过 aes 那段,真的没啥想说的……
    maplerecall
        26
    maplerecall  
       Mar 1, 2017 via Android
    简单的说,如果是纯浏览器环境就放弃吧
    mengzhuo
        27
    mengzhuo  
       Mar 1, 2017
    没有
    不要自欺欺人
    hst001
        28
    hst001  
       Mar 1, 2017
    简单从信息加密的角度想一下,其实从服务器发给浏览器,无论何种方法,客户端都有有一个解密的 key ,所以问题在于怎么安全的把解密的 key 交到客户端的手里,我的想法是。。。。。当!当!当!亲自上门交到客户手里!不要喷我
    wwqgtxx
        29
    wwqgtxx  
       Mar 1, 2017 via iPhone
    @rogerchen payload 就算用 rsa 加密其实也不需要 e7 那么夸张,我用过纯 python 实现的 rsa 加密,在 500k/s 下也就用了 10%的 cpu(cpython3.5+i7 4790)
    momomirage
        30
    momomirage  
       Mar 1, 2017   ❤️ 1
    线下交换公钥, 线上 PGP
    jsq2627
        31
    jsq2627  
       Mar 1, 2017
    讲道理的话,就算 https ,没有进 preload list 也谈不上多安全。

    就楼主的需求,简单的对称加密,密钥明文下发都没啥大问题。不定期换换密钥和稍微更新一下加密方式就好。
    如果楼主遇到的是强大的对抗力量(比如国家机器)的话,在现在的环境下基本是无解的。
    zjcqoo
        32
    zjcqoo  
       Mar 1, 2017
    ------- 楼歪了,我来说个方案 ------

    HTTP 下防劫持比较靠谱的方案 —— 给入口页面使用前端缓存,比如 html5 appcache 、 max-age 等等,资源使用加密传输。

    这样做的好处是,把风险缩小到首次访问。之后就算遇到不安全的网络,打开的也是缓存里的页面,不会被中间人篡改程序和界面。

    这种方案叫做 TOFU ( Trust on First Use ,信任首次使用)。
    KKKKKK
        33
    KKKKKK  
       Mar 1, 2017 via iPhone
    pjax+aes 加密
    majinjing3
        34
    majinjing3  
       Mar 1, 2017 via Android
    直接用带 tls 的 tcp 就好了,和 http 没有啥必然关系的,
    loading
        35
    loading  
       Mar 1, 2017
    vpn 拨上,链路不就加密了?
    whimsySun
        36
    whimsySun  
       Mar 1, 2017
    没有
    O3YwA1ENkb7i35XJ
        37
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    其实楼主的问题, 要解决很简单嘛, 约定一个算法.
    比如 QQTEA https://github.com/xqin/qqtea

    浏览器随机生成加密 KEY, 然后用 RSA 加密, 发给服务器,
    服务器 用同样的算法 (PHP 版的 QQTEA https://github.com/xqin/qqtea.php), 使用相同的 KEY 来进行加密,
    加密后的内容返回给浏览器, 这样 key 在传输的过程中是加密的, 且 服务器回来内容的时候只有加密后的内容.
    这个 key 只有 浏览器和服务器 俩人知道.

    所以就达到了保密的目的.
    NUT
        38
    NUT  
       Mar 1, 2017
    把序列化的后的数据(比如 protocol )的二进制数据,加自己的头,做下偏移。或者伪装成 zip 的文件等等。 说白了就是他自己拿到包也用不了。
    bdbai
        39
    bdbai  
       Mar 1, 2017 via Android
    @majinjing3 读题 纯 web
    Hardrain
        40
    Hardrain  
       Mar 1, 2017
    个人认为无法做到
    因为在没有预先建立信任体系的前提下无法对抗中间人攻击

    预先建立的信任体系 是指:
    对于 SSL/TLS 则是 PKI(公钥基础设施)
    对于 GPG 则是通信双方都信任的、能与通信双方建立可靠连接的 Key Server

    如果你有极可靠的方法(如嵌入软件中或"面对面交换")来完成 SSL/TLS 中密钥交换机制所完成的 那另当别论
    guokeke
        41
    guokeke  
       Mar 1, 2017
    @hst001 这个可以有。直接告诉使用者一个 key ,让使用者使用前手输。
    O3YwA1ENkb7i35XJ
        42
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 看清楼主的假设好吗? 只考虑监听, 不考虑篡改内容.

    基于这个假设的条件下, 服务器先下发 RSA 公钥, JS 生成一个用于加密的 KEY,
    然后对要进行提交的数据使用生成的 KEY 加密,
    使用 RSA 算法对 KEY 进行加密, 将 RSA 的结果和要传递的数据的加密结果一起传给服务器,服务器自己解 RSA 之后,用 KEY 解加密数据, 即可.
    nijux
        43
    nijux  
       Mar 1, 2017
    端到端加密
    Hardrain
        44
    Hardrain  
       Mar 1, 2017
    @xqin 我并不认为我没有看清楚楼主的假设

    中间人攻击并不<b>仅仅</b>用于篡改传输内容
    你要是用匿名(不签名)的 DH/ECDH 抑或是为签名过的 RSA 公钥进行密钥交换,窃听者完全有可能用中间人攻击的手段获取加密通讯的内容.
    likuku
        45
    likuku  
       Mar 1, 2017
    gpg 签名且加密,不走 http ,直接走 smtp + tls 互传,即 gpg 加密和签名后的消息报文。

    公私钥安全传递,自己派人用加密 U 盘人肉信使传递吧。(重要的外交文件,依然人肉信使传递)

    想想当前航空用的空地文本通讯,还是用加密的电报传输呢。
    O3YwA1ENkb7i35XJ
        46
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 允许 窃听到内容呀, 但只要能保证不被解密得到原文就可以了.
    thekll
        47
    thekll  
       Mar 1, 2017 via iPhone
    先搞清楚什么样的中间人,如果客户端拥有者同时想扮演中间人,他有很多方法截获通信内容;

    如果只是防止真正的第三人, https+浏览器+HPKP 、 HSTS ,或 https+客户端+built-in certificate pinning 就可以。

    如果还不放心,直接双向证书认证的 ipsec 够了吧。
    Hardrain
        48
    Hardrain  
       Mar 1, 2017
    @xqin 我不明白你说的"内容"是指的密文还是明文

    我表达的意思是『窃听者可以用中间人攻击的手段获取明文 明文 明文』
    明文都叫窃听者获取了还叫"防止监听"吗?
    O3YwA1ENkb7i35XJ
        49
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 我上面说的传输的内容用算法进行加密, 你完全忽略了?
    fzleee
        50
    fzleee  
       Mar 1, 2017
    大概三年前我做过一个简单的实验。大致的介绍在这里: https://ifconfiger.com/page/cryptography-on-application-layer 。现在回过头来看,感觉实现的方法还是有点不太成熟的。

    简单的流程大概是这样的:
    1.服务器和用户共享一对相同的密码。
    2. 用户在浏览器输入密码后,浏览器的 JavaScript 对密码进行 hash 获得对称密钥。
    3. JavaScript 用对称密钥对 http 请求的数据进行加密,将加密的数据使用 base64 编码发送至服务器。
    4. 服务器解密请求,生成响应的消息体,使用密钥加密消息体并传回客户端。

    以上流程我能想到的一些缺点:
    1. 一个是不能保证数据的完整性==》密钥生成的方式容易收到重放攻击。
    2. 再一个是使用了 ECB 模式加密数据==>这个倒是可以使用类似的 DH 算法协商一个 IV 。
    3. 前向安全性貌似不能保证。
    O3YwA1ENkb7i35XJ
        51
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017   ❤️ 1
    @Hardrain 还是用代码来说话吧.
    演示地址: https://xqin.net/http/
    源代码: https://github.com/xqin/http_encrypt_demo

    查看演示的时候, 可以打开控制台, 看 Network 中的请求及响应,
    请以窃听者的身份, 根据请求和响应的内容, 得到服务器返回的原始数据.
    > PS: 客户端收到的原始数据会在页面中输出, 以便你检测你自己还原出来的和服务器返回的是一样的.
    >> 再再 PS: 如果觉得演示是放在 HTTPS 的站点上有问题的话, 可以自己 clone 一下源码,然后在你本地部署一份,
    >>> 然后用 Fiddler 做为 HTTP 代理(窃听者), 根本 Fiddler 里捕获到的数据, 还原输出服务器返回的原始数据.
    czc2004211
        52
    czc2004211  
       Mar 1, 2017 via iPhone
    我倒是好奇坚持不让用 https 的原因
    bianhua
        53
    bianhua  
       Mar 1, 2017
    @jybox

    能篡改的话,想要监听也是轻而易举的把?

    TLS 之所以安全是因为通讯双方的身份都是得到过认证的。服务器向客户端发出一把锁,客户端用自己本地的 CA 记录验证服务器发来的锁是否合法,然后将数据用锁锁好发送给服务器。

    如果没有服务器和客户端验证的过程,数据加密就跟没有一样。

    就楼主需求来说,如果 Web 应用上不了 TLS ,就不要考虑加任何“加密通讯”手段了。因为都是徒劳的,只是给自己的安慰剂而已。别人真想监听,它可以注入一个 JavaScript 绑定所有 Input 的 onChange 事件发出来,这样你拦都拦不住。
    Hardrain
        54
    Hardrain  
       Mar 1, 2017
    @xqin
    https://www.zhihu.com/question/45069626
    https://program-think.blogspot.com/2016/09/https-ssl-tls-3.html

    学习一个
    你这个实现无论如何也要进行密钥协商吧?似乎没有使用 DH/ECDH
    服务器---RSA 公钥--->客户端
    那么有上一行这个过程吧?

    如果中间人有能力篡改连接内容,改了你公钥不就做成了中间人攻击?
    SSL 中你把 CSR 交给 CA 不就是给公钥签名让中间人改不了,如果改了客户端会发现吗?
    照你的神逻辑 自签名证书也有足够的安全性 OpenSSL 随便就能生成一个谁还花钱找 CA 买证书去?

    此外,你所说"传输的内容用算法进行加密",如果你用了非对称加密那不用保证『客户端获取的是服务器的公钥而不是中间人的公钥』?
    此外此外,我不明白你一直说的原始数据是指什么?我可以理解为密文吗?
    O3YwA1ENkb7i35XJ
        55
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 看清楼主要讨论的内容好吗?

    都说了 只考虑防窃听到原始数据(未加密前的内容, 上面的例子中服务器返回的 Hello Client 的那段), 不考虑篡改.
    O3YwA1ENkb7i35XJ
        56
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    楼主在上面 强调了好几次, 只考虑防窃听不考虑篡改, 可还有一堆上人, 在往 篡改数据上面扯.
    RqPS6rhmP3Nyn3Tm
        57
    RqPS6rhmP3Nyn3Tm  
       Mar 1, 2017
    @Hardrain #39 其实 PGP 的信任体系是基于指纹的,密钥服务器不可信,正确的做法是通过传统方式(电话等)核对指纹
    Hardrain
        58
    Hardrain  
       Mar 1, 2017
    @xqin 我没有说『篡改具体通信内容』
    而是强调攻击者『通过篡改 [公钥] 』来 [获取] 通信内容

    你听得懂话?
    Hardrain
        59
    Hardrain  
       Mar 1, 2017
    @BXIA 查证了一下 这点上的确我错了 可能是习惯了 Ubuntu 的 ppa 源添加后要导入 GPG 公钥

    但是 GPG 的安全性也基于『有条件以确保公钥不被篡改』 这个理解应该没有错误吧
    O3YwA1ENkb7i35XJ
        60
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 篡改公钥 不是篡改吗? 麻烦你去前面看清楼主的要求好吗?
    RqPS6rhmP3Nyn3Tm
        61
    RqPS6rhmP3Nyn3Tm  
       Mar 1, 2017 via iPhone
    @Hardrain 所以有不同等级啊,像 ppa 这种人工核对指纹肯定不现实,所以算了算了你们自己下载吧,反正也有 https 被篡改了也是证书商背锅
    你的理解是对的,这个条件就是指纹,至于公钥服务器则是任何人都可以建立的东西
    O3YwA1ENkb7i35XJ
        62
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 也不知道是谁听不懂话?
    Hardrain
        63
    Hardrain  
       Mar 1, 2017
    @xqin 可笑 都讲明白了『篡改公钥目的是为了获取明文的通信内容』
    况且楼主也没提到『中间人只有偷窥(窃听)的能力,不能做到篡改你的公钥』

    死搅蛮缠
    O3YwA1ENkb7i35XJ
        64
    O3YwA1ENkb7i35XJ  
       Mar 1, 2017
    @Hardrain 自己往上看看楼主在 #5 #8 #13 #18 楼回复的内容, 好吗?

    楼主强调了四次 <<暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。>> 好吗?

    是谁在 "死搅蛮缠" ?
    MFC
        65
    MFC  
       Mar 2, 2017
    不知 Flash 能否实现这个需求?
    pubby
        66
    pubby  
       Mar 2, 2017 via Android
    @xqin 用户最初在浏览器输入网址 http 的时候会发生什么?一开始就歪了

    其实楼主也意识到了,不事先在客户端放点可靠的东西话,剩下的都是干不成的
    O3YwA1ENkb7i35XJ
        67
    O3YwA1ENkb7i35XJ  
       Mar 2, 2017
    @pubby 没有, 楼主的本意应该只是探讨一下, 在非 HTTPS 以及不考虑 内容被篡改的情况下, 有什么好的方法
    防止被其他人监听到传输的原始内容.

    <<暂时不考虑中间人篡改内容, 只防中间人监听,解密出内容。>> 这是楼主的原话.
    fengyie007
        68
    fengyie007  
       Mar 2, 2017 via Android
    这个要求很奇葩,难道是为了省个证书的钱?
    LeeSeoung
        69
    LeeSeoung  
       Mar 2, 2017
    浏览器 ----> 服务端 (这个倒好做, RSA 浏览器公钥加密,
    这个不是在你加密之前截获数据就行了么?
    - -你要是想依靠 js , flash 完成加解密,很容易被破解,控件的话破解难度会加大,但是用户体验不好
    LeeSeoung
        70
    LeeSeoung  
       Mar 2, 2017
    @MFC flash 也可以反编译还原出加解密流程。
    janxin
        71
    janxin  
       Mar 2, 2017
    自己实现一遍 https
    wizardoz
        72
    wizardoz  
       Mar 2, 2017
    提出这要的要求果然很奇葩。不使用浏览器自带的 https ,反而在 JS 上实现一套不可能健全的 https 。
    多出来的开发费用可以买多少年证书了啊。
    nilai
        73
    nilai  
    OP
       Mar 2, 2017
    @xqin 昨晚有事, 一早来看回复了这么多, 大家的回复我都看了, 首先这需求的确奇葩,
    首先允许中间人窃听(像什么端口镜像之类等等) (小到公司内网出口,大到运营商出口等,都会分析网络流量)
    其次是防止通过窃听流量还原出明文(敲黑板。。。。)
    (在浏览器本身,比入注入进浏览器内存获取未加密数据不在考虑范围, 通过浏览器本身的一些插件扩散等都不在考虑范围)
    (什么中间人公钥私钥替换中转也都不在此考虑范围)
    xqin 应该是明白我的意思, 你的 DEMO 代码我也看了, 我目前大概也是这样做的, 不过没有用 QQTEA 算法, 还是用标准的 AES , 跟你的方案不同的是我用了 localStorageService 把本地解密的 KEY 缓存在浏览器内存中, 另一直也在准备用 ecdh 方案来实现密钥交换
    O3YwA1ENkb7i35XJ
        74
    O3YwA1ENkb7i35XJ  
       Mar 2, 2017
    @nilai 感谢你再次出来证明,我对你的需求理解是正确的.

    你最后说的打算采用 ECDH 的密钥交换, 其实与你用 RSA 加密 加密 key 再将加密结果传递给服务器,服务器从加密结果中还原出来加密 key 是一样的道理.

    ECDH 的前提也是在客户端放 服务器是公钥, 而 RSA 也是 =,=
    而且 ECDH 还需要将客户端的公钥告诉服务器类(可以想像成 RSA 加密后的结果),
    然后服务器根据客户端的公钥和自己的私钥算出来一个 共享密钥(服务器解 RSA 得到加密 key).

    套路都是一样的, 只是换了一种算法而已.
    nilai
        75
    nilai  
    OP
       Mar 2, 2017
    @xqin ^_^
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2856 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 170ms · UTC 11:40 · PVG 19:40 · LAX 04:40 · JFK 07:40
    ♥ Do have faith in what you're doing.