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

Uncaught Crypto error with malformed key (support password-protected private keys) #233

Open
cburatto opened this issue Sep 11, 2017 · 8 comments

Comments

@cburatto
Copy link

cburatto commented Sep 11, 2017

Using Node 6.11.1 + Sails 1.0

crypto.js:286
  var ret = this._handle.sign(toBuf(key), null, passphrase);
                         ^

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Error (native)
    at Sign.sign (crypto.js:286:26)
    at SAML.signRequest (...\node_modules\passport-saml\lib\passport-saml\saml.js:135:34)
    at requestToUrlHelper (.../node_modules\passport-saml\lib\passport-saml\saml.js:308:12)
    at DeflateRaw.onEnd (zlib.js:227:5)
    at emitNone (events.js:91:20)
    at DeflateRaw.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)

This happens if you provide the just the base64 privateCert not enclosed in -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----

This probably also happens if you try to validate the IDP signature later on. (I haven't got there yet)

Maybe add an error handling for this case or a key check (and update documentation)?

@cburatto
Copy link
Author

cburatto commented Sep 14, 2017

Correction: -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- are not necessary. The issue with malformed key error continues. However, there is already a pull request for error handling so this error doesn't crash the server:

#230

@markstos
Copy link
Contributor

For future reference, if you are having trouble figuring out the correct private key format, you can use this little script to test:

  "use strict";                                                                                                      
  var fs = require("fs")                                                                                                                                                                                                         
                                                                                                                                                                                                                                 
  var SAML = require("passport-saml").SAML;                                                                                                                                                                                      
                                                                                                                                                                                                                                 
  var saml = new SAML({                                                                                                                                                                                                          
      privateCert : fs.readFileSync("./tmp.pem")                                                                                                                                                                                 
  })                                                                                                                                                                                                                             
                                                                                                                                                                                                                            
  var message = { SAMLResponse: "BOOM" };                                                                                                                                                                                        
  saml.signRequest(message)                                                                                                                                                                                                      
console.log(message.Signature)    

Using that, I determined that the private key must start with -----BEGIN PRIVATE KEY----- on it's own line. (And -----END PRIVATE KEY----- on it's own line at the end for good measure.)

It doesn't work to put BEGIN PRIVATE KEY on the same line as the rest of the cert, and didn't work to omit it and didn't work to use BEGIN CERTIFICATE instead.

The certificate itself can be on a single line, or presumably will also work with linebreaks.

This behavior is inconsistent with other parts of passport-saml which accept certs on a single line without the header/footer. The need for the headers here is not currently documented-- I'll work on that.

It also be nice if passport-saml validated the cert formats as soon as they were loaded for faster feedback that something is wrong.

@whatch
Copy link

whatch commented Sep 19, 2018

If my private key is password protected, sha256, I get a different header and footer:
-----BEGIN ENCRYPTED PRIVATE KEY-----
-----END ENCRYPTED PRIVATE KEY-----
If I change this to BEGIN PRIVATE KEY, it fails. I'm setting the privateCert using an object, with key and passphrase properties, and the key is set using the fs.read.... typical approach. Is using a password with a key not supported? If so, how do you work around this header issue?

@markstos
Copy link
Contributor

@whatch How do you enter the password? Do you have server prompt you to enter the password when it boots up? What if the server reboots in the middle of the night while you are in vacation? Passwords are typically not used for SSL certificates and similar things, but it's not practical to have the right person enter the password when it's needed, potentially resulting in downtime.

@christiaanwesterbeek
Copy link

christiaanwesterbeek commented Dec 16, 2018

@markstos

How do you enter the password?

We don't, but keep it in a .env file.

Passwords are typically not used for SSL certificates and similar things

It's default practice for me when I use samlify: https://github.com/tngan/samlify/blob/71660123524daedecb7c15d648a7ad09c0d75e5c/test/flow.ts#L74

It also seems reasonable to me to protect even the private key with a password.

@whatch Have you find a way to use an encrypted private key?

@markstos
Copy link
Contributor

password-protecting the private key is supported by the SAML spec, so we should support it here too, regardless of my opinion of the practice.

A pull request with code/test/docs to address this is welcome.

@markstos markstos reopened this Dec 18, 2018
@markstos markstos changed the title Uncaught Crypto error with malformed key Uncaught Crypto error with malformed key (support password-protected private keys) Dec 18, 2018
@laxine
Copy link

laxine commented Mar 20, 2019

When you generate private key using openssl if creates in PEM encoded PKCS#1 format.
Try converting PEM to PKCS#8, it worked for me.

openssl pkcs8 -in <pem_in_PKCS#1> -topk8 -nocrypt -out <pem_in_PKCS#2>

PEM encoded PKCS#1 format private key begins with
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

PEM encoded PKCS#8 format private key begins with
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

If you have encrypted private key (-----BEGIN ENCRYPTED PRIVATE KEY-----) convert to (-----BEGIN RSA PRIVATE KEY-----) which is PKCS#1 and then to PKCS#8 (-----BEGIN PRIVATE KEY-----).

@ricardosaracino
Copy link

just dropping here to help someone .. this formats certs

https://www.samltool.com/format_x509cert.php

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

No branches or pull requests

6 participants