最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Implementing JSON Web Encryption in Node.js - Stack Overflow

programmeradmin7浏览0评论

I'm looking for a way to use JSON Web Encryption (JWE) in a Node.js service. I have however only managed to find implementations of the related standard JWS. There are however several libraries for other languages, such as jose4j.

Did anyone successfully implement JWE in Javascript? I'm afraid I'm gonna gave to resort to implementing the spec myself using lower level primitives. Is there a better approach?

I'm looking for a way to use JSON Web Encryption (JWE) in a Node.js service. I have however only managed to find implementations of the related standard JWS. There are however several libraries for other languages, such as jose4j.

Did anyone successfully implement JWE in Javascript? I'm afraid I'm gonna gave to resort to implementing the spec myself using lower level primitives. Is there a better approach?

Share Improve this question edited Oct 7, 2021 at 7:24 CommunityBot 11 silver badge asked Mar 25, 2015 at 14:50 JHHJHH 9,31510 gold badges57 silver badges110 bronze badges 2
  • were you able to find a good JWE library? I'm now in the same boat and having trouble finding one that supports A256GCMKW – ZapRowsdower910 Commented Dec 29, 2016 at 21:58
  • Woah it's been a while. :-) I honestly can't remember what I ended up doing, but maybe you should look into Blacksonic's answer below?. Good luck. – JHH Commented Dec 29, 2016 at 22:03
Add a ment  | 

3 Answers 3

Reset to default 7

Here is a library that can be used from Node.js also https://github./cisco/node-jose. They have also a very good documentation on how to use it.

There is a library js-jose https://github./square/js-jose. But it works only for Chrome. It does not work for Internet Explorer nor for FireFox.

Using Node's crypto library, below uses a 256 bit (GCM) AES Key in a direct encryption scheme.

import { Buffer } from 'node:buffer';
import fs from "node:fs";
import url from 'node:url';
import path from "node:path";
const {createCipheriv, createDecipheriv, createSecretKey, randomFill, generateKey} = await import('node:crypto');
var aesKey;
var claims = {name:"Joe",roles:["member","admin"]};

(async function () {
  console.log("\x1b[31mInvalid Token")
  aesKey = await generateSecretKey();
  let jwe = await returnJWE(claims);
  console.log("\x1b[37mYour JWE token is: " + consoleString(jwe));
  console.log("Paste JSON Web Token In Terminal Then Press Enter.")
})();

async function decryptJWE(jwe) {
  try {
    let parts = jwe.split(".");
    let encodedJWEProtectedHeader = parts[0];
    let protectedHeaderBuffer = Buffer.from(encodedJWEProtectedHeader,'base64url');
    let cipherText = parts[3];
    let tag = parts[4];
    let tagBuffer = Buffer.from(tag,'base64url');
    let iv = Buffer.from(parts[2],'base64url');
    const decipher = createDecipheriv('aes-256-gcm', aesKey, iv);
    decipher.setAAD(protectedHeaderBuffer);
    decipher.setAuthTag(tagBuffer);
    let decrypted = decipher.update(cipherText,'base64url','utf8');
    decrypted += decipher.final('utf8');
    return JSON.parse(decrypted);
  } catch (e) {
    return "\x1b[31mInvalid Token!\x1b[37m";
  }
}

function generateInitializationVector () {
  return new Promise(function(resolve, reject) {
    let buf = Buffer.alloc(32); //makes 256 bit
    randomFill(buf, (err, buf) => {
      if (err) reject (err);
      resolve(buf);
    });
  });
}

function generateSecretKey () {
  return new Promise(function(resolve, reject) {
    generateKey('aes', { length: 256 }, (err, key) => {
      if (err) {
        reject (err);
      }
      resolve (key)
    });
  });
}

async function returnJWE(claimsObject){
  let headerObject = {"alg":"dir","enc":"A256GCM"}; 
  let headerString = JSON.stringify(headerObject);
  let iv = await generateInitializationVector();
  let claimsString = JSON.stringify(claimsObject);
  let claimsBase64URLEncoded = Buffer.from(claimsString).toString('base64url');
  let cipher = createCipheriv('aes-256-gcm', aesKey, iv);
  cipher.setAAD(Buffer.from(headerString));
  cipher.setAutoPadding();
  let encrypted = cipher.update(claimsString,'utf8','base64url');
  encrypted += cipher.final('base64url');
  let tag = cipher.getAuthTag().toString('base64url');
  let encryptedKey = "";
  let ivString = Buffer.from(iv).toString('base64url');
  let encodedJWEProtectedHeader = Buffer.from(headerString).toString('base64url');
  let result = encodedJWEProtectedHeader + "." + encryptedKey + "." + ivString + "." + encrypted + "." + tag;
  return result;
}

export default {decryptJWE, returnJWE};

process.stdin.setEncoding('utf8');
process.stdin.on('readable', async () => {
  let chunk;
  while ((chunk = process.stdin.read()) !== null) {
    console.log(await decryptJWE(chunk));
  }
});

function consoleString(token){
  let tokenParts = token.split(/(\.)/);
  let colors = ["32m","31m","33m","34m","36m"];
  let color = "\x1b[X";
  let str = ""
  //str += color
  tokenParts.forEach(function(part,index){
    if(part != "."){
      str += color.replace("X",colors.shift())
    }
    str += part;
    str += "\x1b[37m"
  })
  return str;
}
发布评论

评论列表(0)

  1. 暂无评论