auth0 / node-jsonwebtoken

JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
MIT License
17.68k stars 1.23k forks source link

RS256 Broken #400

Closed dtwardus closed 6 years ago

dtwardus commented 7 years ago

If you try to use this to generate a RS256 signature it just returns an error.

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line at Sign.sign in core crypto.js — line 329 at Object.sign in jwa/index.js — line 55 at Object.jwsSign (as sign) in jws/lib/sign-stream.js — line 23 at module.exports (as sign) in jsonwebtoken/sign.js — line 178 in this notebook — line 5 at Generator.next in core — line 0 at Generator.next in core — line 0

var jsonwebtoken = require("jsonwebtoken")

var cert = "testing";

var token = jsonwebtoken.sign({ foo: 'bar' }, cert, { algorithm: 'RS256'});

console.log(token);

Using their own code from documentation. Switch the R for an H in the algorith section and watch it work.

kjvalencik commented 7 years ago

This looks like an error in OpenSSL due to an invalid certificate. Switch to H, (e.g., HS256) is a completely different algorithm (HMAC). It doesn't use a certificate and is using it as a secret instead.

dtwardus commented 7 years ago

Yeah I was just trying to highlight in the simplest way that RS256 wasn't working using their code. Unfortunately Google's OAuth2 requires RSA256 so I'm stuck waiting.

kjvalencik commented 7 years ago

This looks like an issue with the certificate (either invalid or being fed to the library wrong). I can confirm that RSA is working in jsonwebtoken since I am using it in production in several places. I don't think the issue is in the library.

Can you provide the public key and some of the code that is failing for you? I can try to help debug.

mellodev commented 6 years ago

I was having the same error show up when I was attempting to .verify() an RS256 token. The solution for me was to ensure the "secret" value (signing certificate) included proper newlines. Hope this tip helps anyone else googling PEM_read_bio.

Example:

let secret = [ '-----BEGIN CERTIFICATE-----', 'MIIDHTCCAgWgAwIBAgIJMQd2wjokT/M4MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV', '...snip...', 'iNSEkEX8oV39Y8So20V+ogLub9dJLg3EG7AeLFa6EXp6', '-----END CERTIFICATE-----' ].join('\n');`

ziluvatar commented 6 years ago

Be sure you use the private key to sign and public key to verify.

We have some example in tests, just in case the format is incorrect or not well loaded: https://github.com/auth0/node-jsonwebtoken/blob/master/test/rsa-public-key.tests.js You can also check the keys in the test folder.

peterver commented 6 years ago

Can confirm that this works. If you are not reading from a file but are using a string, make sure the string is

1) encoded as utf-8 with the original linebreaks preserved 2) as @ziluvatar mentioned (public for verify, private for signing)

In our case we have the following setup :

For base64 encoding the pem private/public keys we devised the following command :

openssl base64 -in mykey.pem -out mykey_encoded.pem && echo $(<mykey_encoded.pem) | tr -d ' ' > mykey_encoded.pem
lachesis commented 6 years ago

I am also experiencing this issue against 8.3.0. It seems to have something to do with whitespace at the beginning or end of the public key.

Minimal repro case:

var jwt = require('jsonwebtoken')

var PUB = `
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh/YHlmq0l2jniPJkix84v6N5PxBs
7ixY5QC0mRL2gQntE9EfWAYDukN5ImK/t1FzGF/ui3rRtc+Xh7GpnHGT9A==
-----END PUBLIC KEY-----
`

var PRIV = `
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMRaaakPRULvTA29+gMddkT3q3AbLVpr986wIlacGpzaoAoGCCqGSM49
AwEHoUQDQgAEh/YHlmq0l2jniPJkix84v6N5PxBs7ixY5QC0mRL2gQntE9EfWAYD
ukN5ImK/t1FzGF/ui3rRtc+Xh7GpnHGT9A==
-----END EC PRIVATE KEY-----
`

var data = {"foo": "bar"}

var tok = jwt.sign({d: data}, PRIV, {algorithm: 'ES256'})
console.log(tok)
var decoded = jwt.verify(tok, PUB, {algorithms:['ES256']})
console.log(decoded)

Error:

/srv/node_modules/jsonwebtoken/verify.js:27
      if (err) throw err;
               ^

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Verify.verify (internal/crypto/sig.js:150:23)
    at verify (/srv/node_modules/jwa/index.js:89:21)
    at Object.verify (/srv/node_modules/jwa/index.js:106:18)
    at Object.jwsVerify [as verify] (/srv/node_modules/jws/lib/verify-stream.js:54:15)
    at /srv/node_modules/jsonwebtoken/verify.js:116:19
    at getSecret (/srv/node_modules/jsonwebtoken/verify.js:76:14)
    at Object.module.exports [as verify] (/srv/node_modules/jsonwebtoken/verify.js:80:10)
    at Object.<anonymous> (/srv/test.js:25:19)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)

Keys were generated like this:

openssl ecparam -name secp256r1 -genkey -out private.pem                                                                                                                                                                                    
openssl ec -in private.pem -pubout -out public.pem   

This can be worked around by:

var decoded = jwt.verify(tok, PUB.trim(), {algorithms:['ES256']})
manicho commented 5 years ago

Can confirm that this works. If you are not reading from a file but are using a string, make sure the string is

1. encoded as utf-8 with the original linebreaks preserved

2. as @ziluvatar mentioned (public for verify, private for signing)

In our case we have the following setup :

* Public key is passed into environment in a base64 encoded way.

* Decoded using : `new Buffer(process.env.MY_PUBLIC_KEY, 'base64').toString('utf-8')`

* JWT verification in this way : `jwt.verify(my_token, my_decoded_public_ky, { algorithms: ['RS256']), (err, payload) => { ... });`

For base64 encoding the pem private/public keys we devised the following command :

openssl base64 -in mykey.pem -out mykey_encoded.pem && echo $(<mykey_encoded.pem) | tr -d ' ' > mykey_encoded.pem

Thank you, this is exactly what i needed.

w995928555 commented 4 years ago

使用OpenSSL生成 RSA公钥与私钥可以解决

mgligoric commented 4 years ago

To generate private and public key use:

ssh-keygen -t rsa -b 4096 -m PEM -f private.key openssl rsa -in jwtRS256.key -pubout -outform PEM -out public.key.pub

Then to read jwtRS256.key file : const privateKey = fs.readFileSync('private.key') :)

Don't forget to git ignore those files! 👯