#Security Design of SecureGAppProxy
目的
本文的目的是文档化SecureGAppProxy 0.3 beta的安全设计,以便评估其安全性。
设置密码阶段
- 密码验证:为了保证一定的密码熵。
- 密码组合规则
- 7位及以上
- 包括字母、数字
- 去除重复的长度大于等于3的子串后,密码长度仍然大于4。(如:123123ab将被处理成ab)
- 密码字典检查:将密码和密码字典中的密码比较相似度
- 编辑距离 > 3
- 密码长度 - 最长公共子串长度 > 4
- 哈希计算
- 密码会被转换成哈希值,然后再参与后面的密钥协商。
- 计算过程使用PKCS#5的PBKDF1,参数如下:
- 哈希函数:SHA256
- 迭代次数:2^19
- salt: your-appspot-id.appspot.com
- 密码部署
- uploader负责将哈希值部署到服务端上。
- 具体方法是直接建立一个password.py的程序文件,然后把哈希写进去,然后和其他程序一块上传部署。
登录阶段
- 登录阶段基于IEEE Std. 1363.2 BPKAS-PAK方案。它源于论文Provably Secure Password-Authenticated Key Exchange Using Diffie-Hellman
- 256位的椭圆曲线群secp256r1,参看SEC 2: Recommended Elliptic Curve Domain Parameters
- REDP函数用的是ECREDP1
- 需要用哈希函数的地方全部用的是sha256
- BPKAS-PAK中最后一轮客户端向服务器的密钥确认是可选的,但是SecureGAppProxy没有省略。
- 协议使用的是之前计算的哈希值,哈希值将直接存储在Google App Engine上。请注意,如果攻击者获取了这个哈希值,则不需要知道密码,就能登录SecureGAppProxy。因为密码本身和登录没太大关系。计算哈希的目的只是不想让攻击者能看到原始密码,因为密码经常隐含用户的一些隐私信息。
- 使用BPKAS-PAK可达到以下目的
- 双方都能确认对方持有密码。
- 为后续通信准备会话密钥。一个是加密密钥、一个是鉴别密钥。
- 提供前向安全性。(如果密码泄露了,虽然之后的通讯不再安全,但是已经发生的通讯数据仍然是安全的)
- 抵抗离线字典攻击。(即便攻击者截获了整个通讯过程,无法仅通过拦截下的数据就用密码字典攻击。)
- 密钥派生
- 完成密钥协商后,就可以派生出加密和鉴别密钥,为之后的通讯作准备。
- 加密密钥 = KDF1("Encrypt")
- 鉴别密钥 = KDF1("Authenticate")
- 抵御在线词典攻击
- 服务器维护一个计数,记录当前在进行的或失败的登录尝试。计数每24小时清零。
- 如果计数超过5,则登录时会给出一个链接,要求验证用户是否是人类。
- 该链接由reCAPTCHA MailHide生成。原本是用来保护电子邮件地址被spammer的爬虫抓到,这里借用来保护一串数字。然后客户端向服务端提交这串数字表明屏幕前的是个人类……
- MailHide服务需要API Key,目前SecureGAppProxy会自己去申请一个Key,不用用户干预。
- MailHide链接生成方法,请参考这里。
- 记住密码
- 0.3beta后允许在本机上保存密码,自动登录。
- 密码的哈希值会保存在proxy.conf中。
- 一旦包含哈希值的proxy.conf泄露,应该停止使用旧密码登录SecureGAppProxy,因为此时安全性已经无法保证。并应该立即设置新的密码。
加密通信
- 加密为CBC模式的AES,密钥长度256位。
- 消息鉴别码用的是SHA256的HMAC,鉴别密钥的长度是256位。
- 消息格式:IV | Encrypt( Compress( MSG_ID | MESSAGE ) ) | HMAC
- IV,128位的初始向量。
- MSG_ID,128位的消息编号。
- MSG_ID由两部分组成,前64位是一个时间戳,后64位是随机数。
- MSG_ID有效时间为15分钟。只要还没有过期,服务器和客户端会保存所有收到的MSG_ID。如果收到的MSG_ID重复,或者过期,则认为发现了重放攻击。
- 使用Encrypt then Authenticate
- 时钟同步
- 由于用了时间戳,要求客户端和服务端之间时钟同步(虽然精度要求很低)。因此,本地客户端启动后会同步时钟。
- 具体方法
- 向一组知名Web网站发起GET请求。
- 取得HTTP应答中的Date字段。
- 收集所有结果,取中位数。
- 同步后,就得到了一个相对本地时钟的偏移。
一些问题
Q:使用SecureGAppProxy浏览https安全吗?
A: 安全,整个过程能看到明文内容的只有客户端和GAE。假定GAE是安全的话,那就是安全的。
Q: 使用SecureGAppProxy浏览http安全吗?
A: 线路1上的嗅探者什么也不会得到,但线路2上的通信仍然是明文的。不过在这点上,VPN也是这样的情况。
Q: 浏览时匿名吗?
A: 如果单纯依靠IP来判断浏览的来源,是匿名的。但是,GAE用urlfetch请求时,会告知服务器your-appspot-id.appspot.com。Web服务器和线路2上的攻击者能知道这个信息。如果攻击者还能控制线路1,从appspot-id追查使用者ip恐怕是不难的。
访问 HTTPS 不一定安全的. GAE 的 urlfetch 在HTTPS中使用的 CA 列表和客户端的 CA 可能不一致 也就是说GAE认可的 HTTPS 在客户端未必被认可 这点是无解的(至少在GAE提供目标主机的证书之前是无法解决的)
@Lyricco...@gmail.com,
Hi,以前是没办法确认服务器证书的,但是GAE某次更新后有这个功能了,把validate_certificate设成True就可以了。
http://code.google.com/appengine/docs/python/urlfetch/fetchfunction.html
validate_certificate A value of True instructs the application to send a request to the server only if the certificate is valid and signed by a trusted CA, and also includes a hostname that matches the certificate. A value of False instructs the application to perform no certificate validation. A value of None defaults to the underlying implementation of URL Fetch. The underlying implementation currently defaults to False, but will default to True in the near future.
有的网站使用的证书不是正式CA签发的,这些网站SecureGAppProxy会拒绝访问的。
就是說線路一上絕對安全?
@Kaishek1...@gmail.com
我是这么认为的~而且设计目标是这个。
我觉得很不错了.想咨询一下开发者我正在学习密码学,求指导书籍
Diffie-Hellman密码体制是用并非基于密钥的利用质数的幂的同余约定密钥的.那么一开始的密码是为了什么呢?为了验证?传递了MD5?或是将约定密钥所需的传递信息用AES加密以防止中间人攻击?
@moonlightedge1
主要是为了身份验证,防止中间人攻击。
详细的可以看那篇论文里的The PAK Protocol部分。 实现起来还蛮简单的,先把用户密码映射成有限群的元素w,然后密钥协商时,发送gx·w。所以如果不知道w是无法知道公钥g^x 的。
@Cickumqt
我也只是会用一些,太理论的我也不懂。指导书籍的话,Bruce Schneier的Applied Cryptography还是不错的。
先把用户密码映射成有限群的元素w>>这里的有限群是指椭圆曲线群还是指其他的什么?抱歉啊,我只是个机电专业的工科生,数论方面,近世代数方面,都比较模糊.只是看过一些数论的欧拉定理什么的,对椭圆曲线群不是很懂.
另有一个不解之处,这个项目以及一个相近项目(http://code.google.com/p/encrypted-gappproxy/ ) 在AES时明明为了16字节倍数填充补足了字节,为何通过这个应用下载的文件还是字节数一致呢?各种HASH函数本来就是填充的,如果填充方式一致,本来就该相等,倒是可以理解,就是字节数不理解
最近感觉gfw对g.cn的ip干扰很严重,能否增加dns mapping功能
感觉似乎那种padding方案有很小的概率会出现错误,也许以下的方案是不错的选择 def encrypted (string):
def decrypted (string):