区块链浏览器登录验证之----js/go实现SRP6a详解

发布时间:2019年02月25日 价值:20000.00 / 共识:31

一、SRP6a简介

  1. SRP is the newest addition to a new class of strong authentication protocols that resist all the well-known passive and active attacks over the network. SRP borrows some elements from other key-exchange and identification protcols and adds some subtle modifications and refinements. The result is a protocol that preserves the strength and efficiency of the EKE family protocols while fixing some of their shortcomings.
  2. SRP协议是由斯坦福大学计算机科学系的Thomas wu等开发的,英文全称是Security Remote Password(远程密码安全),经过严密的数学论证,SRP被证明是一种非常安全的算法。客户端与服务器端通过SRP6a认证过程只需要客户端向服务器端传输用户id,公开的随机数字A, 客户端验证结果M1;服务器端只需要向客户端发送大素数NN = 2q + 1 q 是一个素数,下面所有的取模运算都和这个 N 有关),N模生成器所得数g 2 个巨大的素数乘得来),用户的Salt,公开的随机数字B, 客户端验证结果M2。客户端与服务器端通信不需要传输密码即可完成验证,协商出公共密钥,作为加密传输的密钥。本文主要参考熊家贵老师go版本的SRP6a实现。

二、js实现SRP6a详解
①、项目地址:https://github.com/ying2025/Spr6a。
②、详解
1、创建srp6a.js和srp6aFunction.js. 一个用来实现srp6a算法,一个用来存公共函数。如下图1所示

图1
2、下载big-integer和hash运算的包。下载链接地址分别为:https://www.npmjs.com/package/big-integerhttps://www.npmjs.com/package/hash.js
其中有一些简单的说明,可根据自己的需要去下载。

3、在引入rp6a.js中引入hash, bigInt,commonFun

  1. var hash = require('hash.js'); // 引入Hash
  2. var bigInterger = require("big-integer"); // 引入大整型
  3. var commonFun = require('./srp6aInterface.js'); // 引入公共函数部分

4、定义全局变量

  1. var bigInt = bigInterger(0);//初始化一个大整型
  2. var randomSize = 512/2/8; // 随机数
  3. var MinSaltSize = 16; // salt的最小
  4. var nil = ""; // err为空
  5. var arrnil = []; //数组为空
  6. var srv = {}; // Server
  7. var cli = {}; // client

5、构造一个Server和Client的公共变量的字面量,如下图2所示:其中关于这些变量的具体含义参考:http://www.cppblog.com/Jedimaster/archive/2006/10/14/13674.aspx和http://www.aichengxu.com/os/1659958.htm。

图2
6、定义Server和Client共有的一些方法,例如生成随机数、设置hash方式、初始化参数、数组与数组之间的拷贝(其中拷贝时要采用大端对齐方式。将前面的填充)、设置参数(b,g,N,bits,计算出K)、生成Salt等。如下图3,4,5所示

图3

图4

图5
先填充A和B使其长度为bufLen,然后用公式u = H(A, B),计算U,如下图6所示:

图6
先填充A、B、S使其长度为byteLen,利用公式 M[1] = H(A, B, K),计算M1,如下图7所示:

图7
先填充A、B、M1使其长度为byteLen,M[2] = H(A, M[1], K),M1验证通过后计算M2,如下图8所示:

图8
7、定义Server的字面量,然后将srp6aBase和Srp6aServer拷贝给对象srv,然后为srv设置hash的方式和初始化参数。其中iv: bigInterger(0),这样初始化目的是为了判断iv是不是为0。如下图9所示:

图9
用b派生出B,b为16进制的字符串,所以bigInterger(b, 16)可以直接这样用。commonFun.bigisZero(i3)就是判断i3的value是否为0的。

  1. srv._B = new Array(srv.byteLen);
  2. var b_iN = bigInterger(i3).toString(16);
  3. var v_iN = commonFun.Str2Bytes(b_iN);
  4. padCopy(srv._B, v_iN);

上面一部分代码主要是讲bigInt类型的i3转为数组,然后copy给srv._B。如下图10所示:

图10
随机生成B,如下图11所示:

图11
计算S,其中var iu = bigInterger.fromArray(srv._u, 256); 官方文档给的是10进制和2进制,这里需要用到256进制的,所以第二个参数是256。如下图12和13所示:

图12

图13
8、Client字面量定义和初始化,以及设置User’s salt

图14
9、计算x以及V。注意hash的运算。这一点吃了很大的亏哦。SHA1(identity | “:” | pass)相当于identity 、:、pass拼接后做hash运算。SHA1(salt | SHA1(identity | “:” | pass))相当于salt和
SHA1(identity | “:” | pass)做hash运算。这一点一定要理解哦。如下图15所示:

图15
10、设置Client的a,B,如下图16所示:

图16
生成随机数A,如下图17所示:

图17
11、Client计算S,如下图18所示:

图18
12、Srp6a验证流程如下图19所示:

图19
13、测试部分数据

  1. var N = "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" +
  2. "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" +
  3. "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" +
  4. "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" +
  5. "FD5138FE8376435B9FC61D2FC0EB06E3";
  6. var hexSalt = "BEB25379D1A8581EB5A727673A2441EE";
  7. var a = "60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393";
  8. var b = "E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20";
  9. // console.log('aaa', a)
  10. var id = "alice";
  11. var pass = "password123";
  12. var salt =commonFun.Str2Bytes(hexSalt);// // console.log(hash.utils.toArray(hexn));
  13. // console.log("salt", salt);
  14. // N = commonFun.Str2Bytes(hexn);
  15. // commonFun.SetBytes(srv,N)
  16. // console.log(commonFun.SetBytes(srv,N));
  17. var sServer = NewServer(2, N, 1024,"SHA1");
  18. var s = NewClient(2,N,1024,"SHA1");
  19. // console.log(cli);
  20. SetIdentity(id, pass); // 设置cli的id,pass
  21. SetSalt(salt); // 设置cli的salt
  22. var v= ComputeV(); // 计算cli的_v
  23. // console.log(cli._v)
  24. SetV(v); // src设置iv
  25. var A = set_a(a) // cli设置a
  26. SetA(A); // srv设置A;
  27. var B = set_b(b); // srv设置b
  28. SetB(B); // cli设置B
  29. // console.log(B)
  30. var S1 = ClientComputeS(); // 计算cli的S
  31. var S2 = ServerComputeS(); // 计算cli的S
  32. // bigInterger(S1).compare(S2);
  33. // console.log(S1.toString(16))
  34. // console.log("------------------")
  35. // console.log(S2.toString(16))
  36. // var M1 = ComputeM1(cli);
  37. // console.log(M1)
  38. ComputeM2(srv);
  39. // console.log(M1)

三、go实现SRP6a详解
——更新中——-

  • 分享 收藏
0 条评论
  • 这篇文章暂无评论,赶紧评论一下吧~