Express full series of tutorials: cookie encryption

Keywords: SHA1 Mac Attribute

I. On cookie encryption

Cookie encryption is the value cookie plaintext information which is not available to client users, and it is an important part of data security. Generally, we can encrypt cookie information when we save cookies, or set the sign attribute of option object to true in res.cookie.

2. Encryption of cookie s by signed attributes

The following code:

const express = require("express");

const cookieParser = require("cookie-parser");

var app = express();

app.use(cookieParser('secret'));

app.get("/",function(req,res){

    res.send("homepage");

});

//Get cookie

app.use(function(req,res,next){

    console.log(req.signedCookies.name);

    next();

});

//Set cookie

app.use(function(req,res,next){

    console.log(res.cookie("name","zhangsan",{httpOnly: true,maxAge:     200000,signed: true}));

    res.end("cookie For:"+req.signedCookies.name);

});

app.listen(8080);

   

Signature principle

Express is used to sign cookies, while cookie-parser is used to parse signatures. Essentially, the value set by cookie and cookie Parser ('secret'); the secret in the cookie is encrypted by hmac, and then stitched together with the cookie value by adding ".".

When signed in option is set to true, the underlying layer will encrypt the cookie value with "secret" hmac.

if(opts.signed){

    sign(cookieVal, secret);

}

function sign (cookieVal, secret) {

    return cookieVal + '.' + hmac(cookieVal, secret);

}


How to parse

The cookie-parser middleware does two things when parsing signature cookies:

1. Extract the original value corresponding to the signature cookie

2. Verify the validity of signature cookie s

The following code:

//Pass in the signed cooki e and key secret key

function signedCookie (str, secret) {

      if (typeof str !== 'string') {

            return undefined

      }

//Verify that cookie s start with "s:"

  if (str.substr(0, 2) !== 's:') {

       return str

  }

//Verify that the value of the signature is valid and return true or false

  var secrets = !secret || Array.isArray(secret) ? (secret || []) : [secret]


  for (var i = 0; i < secrets.length; i++) {

    var val = signature.unsign(str.slice(2), secrets[i])

        if (val !== false) {

              return val

        }

  }

  return false

}

The unsign method of self-signature module is introduced above. The original value is re-signed by the same signature, and then compared with the previous signature value. If the result is the same, the legitimacy of the signature can be judged. The signature.unsign code is as follows:

exports.unsign = function(val, secret){

  if ('string' != typeof val) throw new TypeError("Signed cookie string must be provided.");

  if ('string' != typeof secret) throw new TypeError("Secret string must be provided.");

  var str = val.slice(0, val.lastIndexOf('.'))

    , mac = exports.sign(str, secret);


  return sha1(mac) == sha1(val) ? str : false;

};


3. Encryption of cookie value directly

node provides us with a core security module "crypto", which provides many security-related functions, such as digest operation, encryption, electronic signature and so on.

This is how we can easily encapsulate an encryption module:

const crypto=require('crypto');

module.exports={

//MD5 encapsulation

MD5_SUFFIX:'s5w84&&d4d473885s2025s5*4s2',

md5:function(str){

var obj=crypto.createHash('md5');

obj.update(str);

return obj.digest('hex');

}

}

After that, only the corresponding import is needed:

const common=require('./MD5');

var str='123456';

var str=common.md5(str+'s5w84&&d4d473885s2025s5*4s2');

console.log(str);

Set the cookie code as follows:

const express=require("express");

const cookieParser=require("cookie-parser");

var cry = require('./md5');

var app=express();

var str='hello-123';

var str=cry.md5(str+'s5w84&&d4d473885s2025s5*4s2');

//Setting up Middleware

app.use(cookieParser());

//Get an encrypted cookie

app.use(function(req,res,next){

    console.log(req.cookies.userName);

    next();

});

//Setting and encrypting cookie s

app.use(function(req,res,next){

    res.cookie("userName", str, {maxAge: 5*60*1000, httpOnly: true});

    res.end("set ok");

});

app.listen(8080);

If the login is judged, the correct account can be known by comparing the same encryption operation of the user's input account.

crypto involves many ways of encryption. It is recommended that everyone write module references, which is more convenient for later maintenance.

Posted by mbhcool on Mon, 22 Apr 2019 18:21:34 -0700