Closed Bug 403909 Opened 17 years ago Closed 9 years ago

Provide a JS signing function that works with self-signed certificates

Categories

(Core :: Security: PSM, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: zdenek.hrib, Unassigned)

References

Details

Attachments

(4 files, 1 obsolete file)

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9
Build Identifier: Firefox 2.0.0.9

using window.crypto.signText on and signing with certificate from the SW store returns without exception but returned string is "error:InternalError"

Reproducible: Always

Steps to Reproduce:
1. open attached html in Firefox
2. click on the "Sign Data" button
3. see the error text
Actual Results:  
using window.crypto.signText on and signing with certificate from the SW store returns without exception but returned string is "error:InternalError"

Expected Results:  
using window.crypto.signText on and signing with certificate from the SW store returns without exception and returned string contains the strign representation of digital signature

same error if used with certificate stored on RSA SecurID usb token.
Attached file testcase
Did this work in the past with these certs? That is, did a recent Firefox release break something, or is it possible these just aren't the sort of certs Firefox likes to use for signing?

Capturing a more detailed error log would help us know what's going on

http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn2.html
Assignee: dveditz → kengert
Component: Security → Security: PSM
QA Contact: toolkit → psm
Your testcase works for me with my Thawte Freemail cert.
Hi

I've had a go at modifying the signText method to use the new NSS_CMS* methods rather than the old and busted SEC_PKCS7* ones.

This enables signing with certificates that wouldn't work before, without having to explicitly trust them.

Regards
Stephen
We need to make sure the functionality will not regress.

Unfortunately we don't have any automated tests for this functionality yet, as far as I know. It would be preferred to add such tests at the same time with your changes, so you (and we) can make sure there are no regressions.

https://developer.mozilla.org/en/Mochitest
Status: UNCONFIRMED → NEW
Ever confirmed: true
Attached file testcase (obsolete) —
initial test case
self-signed certificate needed for test case. Goes in build\pgo\certs
Attached file updated testcase
updated testcase
Attachment #409624 - Attachment is obsolete: true
What's the next step for getting this patch included?
Self signed certificates are easy to make and will become more and more common, due to the emergence of WebIds and the foaf+ssl protocol.

http://esw.w3.org/topic/foaf%2Bssl

So fixing this bug could be very valuable.
(In reply to comment #9)
> What's the next step for getting this patch included?

I guess you have to request review for the patch from kaie
Attachment #409090 - Flags: review?(kaie)
(In reply to comment #5)
> We need to make sure the functionality will not regress.
>... so you (and we) can make sure there are no regressions.
> 

I understood Kai want not to regress this. I knew this issue was made by  Buffer overflow in crypto.signText() http://www.mozilla.org/security/announce/2006/mfsa2006-38.html.

If it is, how about resolving as a wontfix?
This bug should be clarified. You should more clearly explain what the bug is, under which circumstances you see the bug, and what approach you suggest to fix it, and why you think it's better.

If your environment (profile) is configured to trust your own cert, then signing will work.

I tried a crypto.signText() test page, http://kuix.de/misc/test41/ 
and it works for me when I use a cert for signing, which can be verified.

Why is it a problem for you to trust your own certs?
If you use your own CA, you should import that CA and assign trust flags, and the cert issued by that CA should work with signText().

The output format of crypto.signText() must remain stable, we must not break existing applications.

I have not checked myself, but I suspect your patch will change the output format. The existing code uses a simple hash and encodes it, but your patch changes it to use CMS, and I believe the binary/ascii representation of the result will have a different structure. Am I right?

If I'm right, then I have to reject your patch.

If you believe that an additional implementation, say crypto.signTextCMS(), is necessary, then you could file a bug where you propose this new function.

You should explain why you believe it's necessary, and what benefits it has in addition to the existing function.

In particular, I would like to understand why "support to use untrusted personal certs for signing" is important for you, in particular, why you can't simply change your environment (trust).

If you have good arguments why signing-with-untrusted certs is important, we might try to relax this current constraint.
(In reply to comment #13)
> This bug should be clarified. You should more clearly explain what the bug is,
> under which circumstances you see the bug, and what approach you suggest to fix
> it, and why you think it's better.

The bug is that using an untrusted certificate to sign the text always results in a internal error.

> If your environment (profile) is configured to trust your own cert, then
> signing will work.

Self-signed certificates aren't trusted.
 
> I tried a crypto.signText() test page, http://kuix.de/misc/test41/ 
> and it works for me when I use a cert for signing, which can be verified.

With the release version of Firefox, only my StartSSL cert will work on that page, all my other certs fail.
 
> Why is it a problem for you to trust your own certs?

How would I go about trusting a self-signed certificate that was generated with the keygen tag?
Also, why would I need to trust a certificate I have the private key for? It's only the person checking the signature that would need to trust my certificate.

> If you use your own CA, you should import that CA and assign trust flags, and
> the cert issued by that CA should work with signText().

While this would work, that's a lot of work just to use self-signed certs for signing.

> The output format of crypto.signText() must remain stable, we must not break
> existing applications.
> 
> I have not checked myself, but I suspect your patch will change the output
> format. The existing code uses a simple hash and encodes it, but your patch
> changes it to use CMS, and I believe the binary/ascii representation of the
> result will have a different structure. Am I right?
> 
> If I'm right, then I have to reject your patch.

The outputted ASN.1 structure is the same. There ends up being some differences at the byte level due to the CMS code adding a length value onto the root element and some padding bytes at the end. However they are both valid PKCS #7 Signed Data structures.

I used your page above to produce a comparison.

http://elfarto.com/before.txt
http://elfarto.com/after.txt

Obviously in this example the timestamp, and therefore the signature is different, but the structure is the same.

> If you believe that an additional implementation, say crypto.signTextCMS(), is
> necessary, then you could file a bug where you propose this new function.

I don't.

> You should explain why you believe it's necessary, and what benefits it has in
> addition to the existing function.
> 
> In particular, I would like to understand why "support to use untrusted
> personal certs for signing" is important for you, in particular, why you can't
> simply change your environment (trust).
> 
> If you have good arguments why signing-with-untrusted certs is important, we
> might try to relax this current constraint.

From what I can understand the current restriction arises from a stray call to CERT_VerifyCert in the SEC_PKCS7 code. See comment 3 on bug 292238.

Regards
Stephen
(In reply to comment #13)
> I tried a crypto.signText() test page, http://kuix.de/misc/test41/ 
> and it works for me when I use a cert for signing, which can be verified.
> 

I also confirmed it works with my VeriSign email certificate. I guess crypto.signText is only worked in verified CA's service by Kai's comment. So it's impossible with self-signed service.
(In reply to comment #14)
> The outputted ASN.1 structure is the same. There ends up being some differences
> at the byte level due to the CMS code adding a length value onto the root
> element and some padding bytes at the end. 

I've done a bit more investigation into why these are different. The NSS_CMSEncoder_* calls SEC_ASN1EncoderSetStreaming on the stream. This causes the ASN1 encoder to omit lengths from the encoded stream. I can't see an equivalent method to the original SEC_PKCS7Encode method. 

NSS_CMSDEREncode is close, but that just calls NSS_CMSEncoder_* under the covers. To get the same output we'd need a new either a parameter to NSS_CMSEncoder_Start, or a new method that doesn't call SEC_ASN1EncoderSetStreaming.

Regards
Stephen
(In reply to comment #15)
> 
> I also confirmed it works with my VeriSign email certificate. I guess
> crypto.signText is only worked in verified CA's service by Kai's comment. So
> it's impossible with self-signed service.

It's possible to use "self-signed", but it requires multiple steps:

- create your own self signed CA cert
- import your CA cert into Mozilla and trust it
- create your personal cert, and sign it using your own CA cert
- import your personal cert

This will work.
The problem of course is with the multiple steps. The are complicated and not required. Not requiring them could really allow client certificates to take off. 

Here are a list of providers that will allow you to create a certificate that is close to self signed in a few clicks:
   http://esw.w3.org/topic/foaf+ssl/IDP

You can then log into the growing number of Relying Parties
  http://esw.w3.org/topic/foaf%2Bssl/RelyingParties

The way these certificstes are trusted is very similar to the way trust works in the real world, and how it works on Facebook: through a web of trust. As your certificate is tied to a URL (called a WebId -- see: http://esw.w3.org/topic/WebID ) people can though their foaf profiles link to you. The more relyiable people link to you the more people can trust you.

I urge you to try this out a bit. It is a bit of a conceptual shift to think of X.509 certificates as working in a web of trust way, as usually these are opposed to PGP keys. But it does in fact work very well.

As WebIds get put in place, the ability for browsers to sign documents with the infrastructure outlined here could be very very useful.  

So in my opinion this is very much worth fixing.
In my opinion, this bug should be marked as invalid.

I agree with Kai Engert: crypto.signText() works.


Kai: please, do not change crypto.signText().

Stephen: if you want, you can propose a new javascript function, but please do not ask Kai to change crypto.signText().

Thank you very much.

Jose.
Let me clarify my opinion:

> I used your page above to produce a comparison.
> http://elfarto.com/before.txt
> http://elfarto.com/after.txt
> Obviously in this example the timestamp,
> and therefore the signature is
> different, but the structure is the same.

Structure is the same, but we expect crypto.signText to raise an error when an untrusted cert is used.

crypto.signText works as it is expected to work, so there is no need for a patch. This bug should be marked as invalid.

On the other hand, Stephen can propose a new javascript function to use untrusted certs for signing. This new javascript function would be useful for signing with untrusted self-signed certs.

Sorry for my English.

Jose.
Changing subject from
"window.crypto.signText returning error:internalError"

to
"Provide a JS signing function that works with self-signed certificates"

(I believe that's what this bug asks for)


(In reply to comment #18)
> The problem of course is with the multiple steps. The are complicated and not
> required.

The multiple steps, as you describe it, are by design, based on the PKI model around X.509 certificates.
Assignee: kaie → nobody
Severity: normal → enhancement
OS: Windows XP → All
Hardware: x86 → All
Summary: window.crypto.signText returning error:internalError → Provide a JS signing function that works with self-signed certificates
Comment on attachment 409090 [details] [diff] [review]
initial attempt at improving signText

r- based on comments.

we don't want to change the behavior of the existing function.

If you want this to happen, we'd need a new, separate function.

I know Channy already works on a proposal for additional JS APIs, so you might coordinate plans with him.
Attachment #409090 - Flags: review?(kaie) → review-
Apologies if it is a mistake writing here. but i am slightly confused about where to write to ask. 
I m using firefox
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5

I have an aladdin etoken. i m trying to sign data from browser and am using window.crypto.signText("abracadabra", "ask");  for signing. The browser can access etoken, it asks the etoken password and verifies that i want to sign this data. But return error:InternalError.

I have a class 1 certificate issued by certifying authority. The certification path has one root certifying authority and an intermediate certification authority. I have imported them into corresponding key stores i.e Trusted Root and Intermediate.  Still i keep getting this error. The Key usage states Digital Signature, Non-Repudiation, Key Encipherment (e0).

I have tried accesing  http://kuix.de/misc/test41/  and it also gives me Internal Error. 

However i have been able to use the same certificate / etoken and sign data in IE using capicom.  But have been struggling with FireFox.   I would appreciate a hand here pls.
Nidhia.bhasin: Edit settings for the CA of your certificate and enable trust setting to identify mail users. Hope this helps.

Sorry for my English.

Jose.
Jose, thnx so very much. u rock!!!
Thanks much for the prompt response. Just one more query pls. 

"Edit settings for the CA of your certificate and enable trust setting to identify mail users."

I am having to do it everytime i insert the token. Is there any way at all, to do it just once, the first time only.
You have to import the CA in Firefox before inserting the token. Then you must enable trust setting to identify mail users. Then you can insert the token.

If this does not work, then I suppose that there is a bug in the driver of your token reader.

Not a bug in Firefox, anyway.

Sorry for my English.

  Jose
window.crypto.signText has been removed.
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: