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

Error while parsing PFX/PKCS12 files #87

Closed
RST-J opened this issue Jan 27, 2017 · 17 comments
Closed

Error while parsing PFX/PKCS12 files #87

RST-J opened this issue Jan 27, 2017 · 17 comments

Comments

@RST-J
Copy link

RST-J commented Jan 27, 2017

I just started using PKI.js and want to use that for client-side decryption of enveloped data.
For that purpose I also need a private key supplied by the user to decrypt the content encryption keys, which I want to retrieve from a PKCS12 file the user has to chose and supply the password for.

I'm following the PKCS12 simple example and managed to get to the point at which the internal values get parsed (i.e. should get parsed), but I get an error which I couldn't resolve yet.

The PKCS12 file I'm using for this was made by the following OpenSSL command:

openssl pkcs12 -export -aes256 -out certificate_aes.pfx -inkey private_key.pem -in pub_cert.pem -certfile ../ca/ca_root_cert.pem

My code looks like this:

pkcs12 = new window.pkijs.PFX(schema: certificate_asn1.result)
pkcs12.parseInternalValues(password: pass, checkIntegrity: false)
pkcs12.parsedValue.authenticatedSafe.parseInternalValues(
  safeContents: [{password: pass}, {password: pass}]
)

The unlocking in the second line works, for the third line I get the following error:

uncaught exception: Unknown "contentEncryptionAlgorithm": 1.2.840.113549.1.12.1.6

I looked to OID up and it says that this is pbewithSHAAnd40BitRC2-CBC which I'd consider prehistoric and inadequate and hence rightly not supported (although I'd say, decryption should be possible, but not encryption - whatever).

Now, my question is: Am I doing something wrong? Is there something more I have to consider when generating the PKCS12 file or even before with the keys and certificates?

Any more details required? Or hints what to do?

Finally, thanks for this library, otherwise the project I'm currently doing would have been rather dead or infinitely delayed as there (for good) is no access to the browser keystore from JS.

@YuryStrozhevsky
Copy link
Collaborator

Probably this issue will give you more info. Since PKCS#12 support in PKI.js has a lot of questions I will create a separate README for this topic. Comming soon.

Feel free to ask a question is the link I mentioned will not clafiry all things.

@RST-J
Copy link
Author

RST-J commented Jan 30, 2017

@YuryStrozhevsky Thanks for your quick help (sorry if the Thumbsup mislead you to close this, I just wanted to say thanks for the quick reply).

I now tried a PKCS12 file generated with the command from the issue you linked (i.e. using the parameters to set the algorithms) and tried the same code with that.
I now get a new error message:

uncaught exception: Incorrect OID for HMAC hash algorithm

This means the problem now is in the 2nd line (already), not the third.

I set the debugger at the respective line and tried to investigate the environment, but I have not enough detail and context knowledge to get anywhere. I could provide you the values of the environment, if you tell me which are of interest (I thought of JSON.stringifying some vlaues, e.g. pbkdf2Params but turns out that some properties are missing, in this case e.g. "prf").

Any ideas or hints?

@YuryStrozhevsky
Copy link
Collaborator

Did you try the live PKCS#12 example to parse the PKCS#12 bundle you have now?

@YuryStrozhevsky
Copy link
Collaborator

Also please aware that you are using PKI.js incorrectly. The root cause of the problem is that almost all PKI.js methods return Promise. So, your code does not aware about any results of Promises. Correct code must be something like:

pkcs12 = new window.pkijs.PFX(schema: certificate_asn1.result)
pkcs12.parseInternalValues(password: pass, checkIntegrity: false).then(() =>
pkcs12.parsedValue.authenticatedSafe.parseInternalValues(
  safeContents: [{password: pass}, {password: pass}]
))

But anyway please check first your PKCS#12 bundle with live PKI.js example I early mentioned.

@RST-J
Copy link
Author

RST-J commented Jan 31, 2017

Good point (too obvious for me). For the file I'm trying now, the sample page raises an error because it does not provide a password parameter in the first safeContent-Parameters here:

uncaught exception: Absent mandatory parameter "password" in "parameters.safeContents[j]"

I downloaded the sample and edited the code to pass a password in there, too and left everything else as it was: The sample page now runs into the same error as my code.

Thanks for pointing that async stuff out - seemed not to be a problem here (everything inline and fast) - but could have become an unnecessary struggle later on.

So, this narrows the problem down to the parsing process of the first safeContent. This is how it looks like in the console:

pkcs12.parsedValue.authenticatedSafe.safeContents[0]
  > Object { contentType: "1.2.840.113549.1.7.6", content: Object }

Is there something about the content object, which could give further insight? I started investigating it, but there is/seems to be a lot of low level detail stuff that one need to know in order to draw conclusions by them.

@YuryStrozhevsky
Copy link
Collaborator

If you still have a problem then the only way forward is sending me the PKCS#12 bundle you have via e-mail yury@strozhevsky.com

Or post BASE64 encoded bundle here,but this is less secure.

@RST-J
Copy link
Author

RST-J commented Feb 1, 2017

@YuryStrozhevsky can you show me how to get a private key buffer and a certificate object from an unlocked PKCS12 bundle?

So, today I played around to create a PKCS12 bundle analogous to the given example and it worked.
I can also take that bundle and unlock it. So I guess I am very close to my goal. There are only two lines left for which I hope you save me another day cavemaning around.

For the following everything is there, the CMS message and the unlocked PKCS12 bundle. But how can I obtain the private key and the certificate from there (the private key is in the first bag/contents, the certificate in the second):

pkcs12.parseInternalValues({password: pass, checkIntegrity: true}).then ->
  pkcs12.parsedValue.authenticatedSafe.parseInternalValues(safeContents: [{password: pass}]).then ->
    cms_asn1 = asn1js.fromBER(cms_buffer)
    cms_content_simpl = new pkijs.ContentInfo({ schema: cms_asn1.result })
    cms_enveloped_simp = new pkijs.EnvelopedData({ schema: cms_content_simpl.content })

    private_key_buffer = Magic.let_there_be_a_private_key_buffer(pkcs12)
    cert_simpel = Magic.let_there_be_a_cert(pkcs12)

    return cms_enveloped_simp.decrypt(0,
      recipientCertificate: cert_simpl,
      recipientPrivateKey: private_key_buffer
    ).then(
      result => result,
      error => Promise.reject("ERROR DURING DECRYPTION PROCESS")
    )

@YuryStrozhevsky
Copy link
Collaborator

Seems you did not check example code: main function plus parsing function.

@YuryStrozhevsky
Copy link
Collaborator

YuryStrozhevsky commented Mar 27, 2018

I decided to update the issue with some new information. So, not so long ago I found that PKIjs was having incorrect algorithm for MacData processing. That is why all had the problems with Mac verify error. The error fixed already, btw. As for Windows The password you entered is incorrect - this example could produce PKCS#12 files which could be successfully parsed by Windows. The example is running on Node only - Windows is using old 3DES and RC2 algorithms and we do not have them in browser evironment.

@rkrier85233
Copy link

rkrier85233 commented Nov 20, 2019

I'm having the same problem. I'm trying to port a certificate management system writing in Java to Typescript using PKI.js. We have customers who have P12 certs that import in our system with their passwords. We must be able to parse out the certificate, get metadata such as key algorithm, validity dates, extensions, etc. Attached is a simple p12 cert I generated. It's password is pass. Don't worry it is a bogus cert so I don't have any security concerns sharing it here.

I've tried parsing this on your live example and my code that I pulled PKCS Simple Example and both give me the same error:

'Unknown "contentEncryptionAlgorithm": 1.2.840.113549.1.12.1.6'

Live example shows when I inspect the page:
[Error] Unhandled Promise Rejection: Unknown "contentEncryptionAlgorithm": 1.2.840.113549.1.12.1.6 (anonymous function) promiseReactionJob

Attached is my P12 file. Zipped so I can upload it.

bob.p12.zip

I should note, I've tried many other P12s I have.

@rmhrisk
Copy link
Contributor

rmhrisk commented Nov 20, 2019

Bob have you looked at the PKCS12 samples?

Please file a bug for your specific issue.

@YuryStrozhevsky
Copy link
Collaborator

@rkrier85233 You have not the same error as in the issue. In your case you just using incorrect example. The deal is that PKIjs uses WebCrypto API and the API has a strict set of algorithms. In your PFX you are using 3DES which is not supported by WebCrypto API. But you could use this example for working with this kind of PFXs. So, as a conclusion: PKIjs in browser cannot handle such PFXs, PKIjs in Node can.

@rkrier85233
Copy link

rkrier85233 commented Nov 21, 2019

Ok I will file a bug report. Regardless, as I mentioned above, I did try PKCS12 Samples. If I can contribute to this project I will. The only thing is I'm not an entire expert. My 15+ years of experiences with public and private key certs is data encryption/decryption, signing/verification and SSL/TLS. ASN.1 I'm somewhat familiar with.

My background is Java with IAIk and BouncyCastle JCE which I've had many years of exposure off and on through my career.

I humbly suggest you try what I've attached through your own app, PKCS12 samples and tell me what you think.

Hope we can work together on this.

Bob

@rkrier85233
Copy link

rkrier85233 commented Nov 21, 2019

Hi Yury,

Thanks for responding. I looked at the examples. I'm running in Node JS. It is a backend, REST application. Okay, WebCrypto cannot handle, I'll try something else. I've looked at the example you sight, but didn't seem to ring a bell.

I'll study the examples more and see if I can determine anything new. I'll let you know good or bad or please guide me.

Again, thanks all for the help and responding.

Bob

Follow up: I got it working. NodeEngine.js and NodeEngineNodeSpecific.js from your example was the key. Thanks so much for the help and guidance. Any thoughts of putting those two files in the base product?

@rmhrisk
Copy link
Contributor

rmhrisk commented Nov 22, 2019

The node samples are in the main project. We do not ship crypto algorithms in PKIjs and use webcrypto instead. You can use webcrypto-liner (https://github.com/PeculiarVentures/webcrypto-liner/blob/master/README.md) to get these algorithms in the browser and adapt the node samples to fit your need in the browser if you need.

@rmhrisk
Copy link
Contributor

rmhrisk commented Nov 22, 2019

You should also read: https://unmitigatedrisk.com/?p=543

@rkrier85233
Copy link

Thanks, I understand. This isn't going to run in a browser, but a REST service running in AWS lambda.

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

4 participants