node.js jws 基于HS265加密算法的源码注释

194 阅读1分钟

1.使用示例

let jws = require("jws");

let secret =  "jh5#h1gfhk#%Tgh6hJMqR$es@dD^&sds2iy)*24";
let expWeek = 14400;

let token = jws.sign({
    header: {alg: 'HS256'},
    payload: {
        a:1,
        b:"asd"
    },
    secret: secret
});

console.log(token);
let tokenInfo = jws.decode(token);

console.log(tokenInfo);
console.log(jws.verify(token, tokenInfo['header']['alg'], secret));

2.使用示例 rs256实现

// This...
jws.createSign({
  header: { alg'RS256' },
  privateKey: privateKeyStream,
  payload: payloadStream,
}).on('done', function(signature) {
  // ...
});
 
// is equivalent to this:
const signer = jws.createSign({
  header: { alg'RS256' },
});
privateKeyStream.pipe(signer.privateKey);
payloadStream.pipe(signer.payload);
signer.on('done', function(signature) {
  // ...
});
jws.createVerify({
  publicKey: pubKeyStream,
  signature: sigStream,
}).on('done'function(verified, obj) {
  // ...
});
 
// is equivilant to this:
const verifier = jws.createVerify();
pubKeyStream.pipe(verifier.publicKey);
sigStream.pipe(verifier.signature);
verifier.on('done'function(verified, obj) {
  // ...
});

3.加密过程解析

function jwsSign(opts) {
  var header = opts.header;
  var payload = opts.payload;
  var secretOrKey = opts.secret || opts.privateKey;
  var encoding = opts.encoding;
  //根据header的加密算法 比如 hs256获得加密函数①
  var algo = jwa(header.alg);  
  var securedInput = jwsSecuredInput(header, payload, encoding);
  //根据header, payload经过base64后的 和secretOrKey 进行加密操作
  var signature = algo.sign(securedInput, secretOrKey);
  //最后返回拼接jwsSecuredInput base64过的header头和payload.signature
  return util.format('%s.%s', securedInput, signature);  
}

①根据header的加密算法 获得加密函数①

module.exports = function jwa(algorithm) {
  var signerFactories = {
    hs: createHmacSigner,
    rs: createKeySigner,
    ps: createPSSKeySigner,
    es: createECDSASigner,
    none: createNoneSigner,
  }
  var verifierFactories = {
    hs: createHmacVerifier,
    rs: createKeyVerifier,
    ps: createPSSKeyVerifier,
    es: createECDSAVerifer,
    none: createNoneVerifier,
  }
  //正则表达式提取出 加密算法和加密位数
  /**
    match =  [
      "HS256",
      "HS",
      "256",
      null
    ]
*/
  var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/);
  if (!match)
    throw typeError(MSG_INVALID_ALGORITHM, algorithm);
  var algo = (match[1] || match[3]).toLowerCase();
  var bits = match[2];

  return {
    sign: signerFactories[algo](bits),   ②
    verify: verifierFactories[algo](bits),
  }
};

②具体加密函数

function createHmacSigner(bits) {
  return function sign(thing, secret) {
    checkIsSecretKey(secret);
    thing = normalizeInput(thing);
    //以hs256为例这个是进行256位加 secret盐的散列函数
    var hmac = crypto.createHmac('sha' + bits, secret);
    var sig = (hmac.update(thing), hmac.digest('base64'))
    return fromBase64(sig);
  }
}

4.结论 ①hs256加密算法,其实是带有 SHA-256 的 加密出来的signature其实是加了secret盐的256位散列值. 有的文章说这种算法是对称加密是不对的,因为这是一种hash算法不存在解密操作,只是单向加密操作,解不了密.验证签名用的. 常见加对称加密密算法包括 AES (Advanced Encryption Standard) 和 DES (Data Encryption Standard)。 ②header和body 只是被base64过了,是明文传输