Когда я изучал uPort, который известен своей платформой самосуверенной идентификации на Ethereum, я изо всех сил пытался создать JWT (uPort обеспечивает идентификацию вне сети с помощью JWT). Итак, отмечу свой опыт для будущего ученика.

Рабочий пример кода на Gist: jwt-secp256k1-secp256r1.js

Произошла ошибка

Мы можем использовать пару открытого / закрытого ключей ECDSA, чтобы подписать JWT как официальный сайт. Итак, я написал сценарий следующим образом. Обратите внимание, что я указываю "secp256k1" как кривую ECDSA.

const JWT = require('jsonwebtoken');
const Elliptic = require('elliptic').ec;
const EC = new Elliptic('secp256k1');// Use 'secp256k1'
// Payload
const payload = {
  sub: 'Subject',
  iss: 'Issuer',
  exp: 1639248876
}
// Generate private key
const privateKey = EC.genKeyPair().getPrivate().toString(16);
// Create token
const token = JWT.sign(payload, privateKey, { algorithm: 'ES256'});

Ожидаемый результат - следующая ошибка.

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Sign.sign (crypto.js:331:26)
    at sign (/work/node_modules/jwa/index.js:76:45)
    at Object.sign (/work/node_modules/jwa/index.js:96:27)
    at Object.jwsSign [as sign] (/work/node_modules/jws/lib/sign-stream.js:32:24)
    at Object.module.exports [as sign] (/work/node_modules/jsonwebtoken/sign.js:188:21)
    at Object.<anonymous> (/work/jwt.js:24:13)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)

Причина: secp256k1.

У меня были проблемы с решением этой ошибки, но меня спасла эта опубликованная проблема.

Спецификация JWA определяет ES256 как ECDSA с использованием P-256 и SHA-256, где P-256 - другое имя для secp256r1.

Я понял, что для JWT доступен только secp256r1. На всякий случай подтвердил RFC и нашел следующие слова.

ECDSA с использованием кривой P-256

P-256 определяется как secp256r1.

Правильный способ создания JWT

Я показываю правильный рабочий образец для создания JWT для информации. Укажите "secp256r1" в качестве кривой ECDSA.

const JWT = require('jsonwebtoken');
const ECDSA = require('ecdsa-secp256r1');// Use 'secp256r1'
// Payload
const payload = {
  sub: 'Subject',
  iss: 'Issuer',
  exp: 1639248876
}
// Genarate private key
const privateKey = ECDSA.generateKey();
// Retrive public key
const publicKey = privateKey.asPublic();
// Create token
const token = JWT.sign(payload, privateKey.toPEM(), { algorithm: 'ES256'});
// Verify token
const decoded = JWT.verify(token, publicKey.toPEM());
console.log({ 
  privateKey: privateKey.toPEM(), 
  publicKey: publicKey.toPEM(), 
  token, 
  decoded 
});

Получайте лучшие предложения по программному обеспечению прямо в свой почтовый ящик