加密锁简单方案(续)
上篇最后想法不合适
不能做base64, base64没有锁也可以做。
做base64和直接写明文没有区别,谁都可以做, 谁都可以解。如果是使用base64加密, 那加密锁起的作用仅仅是一个存储介质,相当于是一个移动优盘, 存储加密后的用户信息, 这样就没起到加密锁加密的作用。
其实制作的加密锁的方案合适不合适有一种检测方案:无论知道用户名密码,还是不知道用户名密码,不使用锁,看能不能登陆系统。难就难在要实现知道用户名密码,不使用加密锁,就无法登陆。
base64加密,如果不使用锁, 将用户信息加密后将加密结果存储到硬盘中, 把硬盘给用户, 或者是存储到内存中, 这样在用户登陆的时候, 从硬盘中读出加密后的用户信息, 再使用base64解密,同样可以获取到用户的信息实现登陆。
必须使用锁内算法
加密锁和硬盘的区别是, 我们可以将私钥放到锁里。 这样的话, 将用户信息使用公钥加密,将加密结果写到锁里。验证的时候, 只能通过锁里的私钥去解密, 如果没有这个锁, 根本解密不了。 也就是, 如果没有锁, 根本无法知道加密前用户的信息。也就无法将加密前的用户信息传给后台去与数据库比对。当然, 如果你事现就知道加密前的用户信息, 同样也可以不使用加密锁,通过调试代码进入系统。
再次明确目的
不管是用户本身也好, 还是不小心泄露了也好, 在知道用户名密码的情况下, 如果没有加密锁同样不能登陆系统。 必须得经过用户名密码和加密锁双重验证, 同时成立才能登陆。
再次整理思路
基本
要想实现使用用户名密码和加密锁的双重验证, 必须要客户端和服务器公共合作。
-
用户锁只存一份私钥文件。服务器产生随机数,将这个随机数返回个客户端。 客户端通过用户锁的私钥加密,将加密结果传递给服务器, 服务器使用公钥解密, 将解密后的结果与最开始生成的随机数比对。通过这种方式来实现必须使用加密锁。
-
登陆页面留两个输入框, 输入用户名密码。将用户名密码传入到后台验证,从而实现必须使用用户名和密码的验证。
首先, 看当前设备是否插入了加密锁。 以前的想法时通过XXX公司给的API去枚举锁, 看能不能找到锁信息。如果能找到就说明插入了用户锁, 这样不行。不行的原因是调试浏览器代码可以修改判定条件,比如response为1时证明有锁, 为其他值时证明没有。 我可以在浏览器调试代码, 使得这个值恒为1。但如果实现了第1点, 我需要锁里的私钥去对后台传过来的数据加密, 如果没有锁根本无法加密。 当然可以说随便使用一种算法加密, 但是服务器存有该私钥对应的公钥, 会对该私钥加密的随机数进行解密, 如果解密后与最开始生成的随机数不同, 就算没有使用key。
其次, 对用户名密码验证。就是正常系统的登陆, 将用户名密码传入到后台, 然后跟数据库比对。
最后要说明的是:锁里没有存关于用户的信息, 随机数必须从后台发起。
完善1
做到上面两点基本功能算是完成了。但是多数情况下, 我们还需要将key与用户绑定, 也就是说, 每个用户有他自己的key, 别人使用他的key登陆不上, 他使用别人的key也登陆不上。
目前实现将用户与锁绑定的方式, 是在锁里存放用户的标识, 比如用户账号。发送验证请求的时候, 将锁里的账号发送到后台, 与用户输入的账号比对, 看是否一致。
不过这样不是很好。 假如说我的加密锁里存放的账号是xxm, 我拿着账号为zds的加密锁。这样表面上,我输入的和用户锁里的账号是不一致的是不能通过的。但是在对比的过程中可以调试浏览器代码。如果在客户端比对, 可以通过调试,使得比对结果恒为true。 如果将锁里的账号传到后台比对, 可以通过调试,在获取到锁里的账号后向后台传送时, 将zds改为xxm。
如果在向锁里存用户账号的时候, 使用锁里的私钥, 对用户账号加密,将加密结果写入到锁内。在后台使用公钥去解密感觉也可以。但实际是不行的。同样是调试代码, 在调试代码时编写代码, 增添使用锁内私钥加密功能。这样向后台发送锁里加密后的用户账号的时候, 不再发送锁里存放的, 而是发送添加的对自己账号加密的密文。
所以说, 目前这种实现方式是有漏洞的。对于这种usbkey登陆认证, 加密明文的发起一定要是服务器端, 类似于随机数加密, 后台产生随机数发送给客户端, 客户端去加密,然后将密文传给后台, 后台解密与原来的验证。如果明文的发起是客户端, 那就相当于自己验证自己, 是有漏洞的。
完善2
还有一点没有考虑到,假如我知道zds的账号和密码, 但是我没有该用户的加密锁。 这种情况我可以自己制作一个加密锁。无非就是往锁里生成一对密钥文件,然后再把zds的账号信息写到锁里。这样我就制作成了一把和zds账号对应账户一摸一样的锁。
解决方式1:额外使用一把锁,暂时称之为管理员锁。 生成密钥对文件, 将私钥写入到管理员锁, 公钥放到后台程序中。利用管理员锁的私钥对用户账号加密, 将密文传给服务器,服务器使用公钥解密验证。这样用户锁就不能随便制作了。
解决方式2:不用准备锁, 签发用户锁的时候, 向每个用户锁类写入相同的私钥。 这个私钥文件一定要管理员保存好。因为这个私钥文件是用来制备用户锁的。谁拿到都可以制备。这样和上面的流程一样, 后台返回随机数, 这个私钥加密,密文传给后台解密比对。 如果没有私钥文件,那制备的加密锁对随机数加密后台就解不了了。
小误区
后台进行解密的时候, 因为服务器没有锁,与锁就没有任何关系了, 也就不用调用XXX公司给的解密接口。 知道公钥, 知道密文,可以上网查询关于RSA加密文件是怎么解密的,从而实现解密。