上篇最后想法不合适
不能做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加密文件是怎么解密的,从而实现解密。