Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RS256 Broken #400

Closed
dtwardus opened this issue Sep 20, 2017 · 10 comments
Closed

RS256 Broken #400

dtwardus opened this issue Sep 20, 2017 · 10 comments

Comments

@dtwardus
Copy link

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

mellodev commented Oct 25, 2017

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
Copy link
Contributor

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
Copy link

peterver commented Mar 30, 2018

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

@lachesis
Copy link

lachesis commented Jun 15, 2018

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
Copy link

manicho commented Sep 13, 2019

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
Copy link

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

@mgligoric
Copy link

mgligoric commented Apr 16, 2020

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! 👯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants