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

Signature not verified when signing using an OpenPGP card #2688

Closed
dingwen07 opened this issue Apr 9, 2021 · 17 comments
Closed

Signature not verified when signing using an OpenPGP card #2688

dingwen07 opened this issue Apr 9, 2021 · 17 comments

Comments

@dingwen07
Copy link

When using FairEmail or K-9 Mail to create a signed (signed and encrypted or signed only) e-mail, the signature of the e-mail cannot be verified on the mail clients using OpenPGP.js (Thunderbird 78, ProtonMail, Mailvelop tested). This is not a problem with OpenPGP.js, because signed emails sent via GpgOL can be verified on OpenPGP.js. Moreover, if the OpenPGP card is not used when signing, the problem will not arise.

Expected Behavior

The signature is verified on all clients

Current Behavior

Signature created using OpenPGP card is not verified on OpenPGP.js based clients

Steps to Reproduce (for bugs)

  1. Generate a PGP key pair
  2. Import it into an OpenPGP card
  3. Send a signed e-mail from FairEmail or K-9 Mail using the key on the OpenPGP card
  4. Open Thunderbird to receive the message, the signature could not be verified, with the error message "Invalid Digital Signature"
  5. Import the private key of the PGP key into OpenKeychain
  6. Send a signed e-mail from FairEmail or K-9 Mail again, this time with private key stored in OpenKeychain
  7. Open Thunderbird to receive the message, the signature could be verified

Context

Your Environment

  • Android Version: 11
  • Device Model: SM-G9750, Xiaomi M2007J3SC
  • OpenKeychain Version: 5.7.3
  • From Google Play or F-Droid?: Google Play
@stelian42
Copy link
Contributor

I see this here as well (step 1 to 4), running latest git version on Android 9.

Didn't try steps 5 to 7 though.

@dschuermann
Copy link
Member

Is this issue also happening without external hardware?

@stelian42
Copy link
Contributor

If I understand correctly the OP steps 5 to 7, I'd say no.

@dingwen07
Copy link
Author

Is this issue also happening without external hardware?

No, only with hardware token for my tests.

@stelian42
Copy link
Contributor

I've just discovered that the signature is verified correctly in mutt , even when generated by a key on a hardware token. This means that the contents of the signature is ok, it must be some formatting issue somewhere which disturbs Thunderbird.

@dingwen07
Copy link
Author

I've just discovered that the signature is verified correctly in mutt , even when generated by a key on a hardware token. This means that the contents of the signature is ok, it must be some formatting issue somewhere which disturbs Thunderbird.

The signature is indeed valid, I can also use gnupg to verify for signed and encrypted messages, they also worked on mailbox.org. The issue is that when the signature is created with a smart card, it cannot be verified on Thunderbird, ProtonMail, Mailvelope, which all uses OpenPGP.js for PGP.

@stelian42
Copy link
Contributor

Could this be related somehow to bug #2333 ? I mean, it would be the same issue, which was worked around in GPG, but which causes issues on Thunderbird ?

@stelian42
Copy link
Contributor

stelian42 commented Apr 20, 2021

After further debugging, I'm pretty sure this is it.

A signature generated from a "local" key in OpenKeychain will be like this:

$ cat LOCAL-sig |gpg --list-packets --verbose
# off=0 ctb=89 tag=2 hlen=3 plen=433
:signature packet: algo 1, keyid 0EC861FD6ED7B863
	version 4, created 1618950384, md5len 0, sigclass 0x00
	digest algo 10, begin of digest 2d 2e
	hashed subpkt 28 len 19 (signer's user ID)
	hashed subpkt 2 len 4 (sig created 2021-04-20)
	subpkt 16 len 8 (issuer key ID 0EC861FD6ED7B863)
	data: <snip>

A signature generated from a key inside a hardware token will be:

$ cat /tmp/PGP-sig | gpg --list-packets --verbose
# off=0 ctb=89 tag=2 hlen=3 plen=319
:signature packet: algo 1, keyid 4FCD58CD8379E4AE
	version 4, created 1618931341, md5len 0, sigclass 0x00
	digest algo 10, begin of digest cf 83
	hashed subpkt 28 len 33 (signer's user ID)
	hashed subpkt 2 len 4 (sig created 2021-04-20)
	subpkt 16 len 8 (issuer key ID 4FCD58CD8379E4AE)
	data: <snip>

Notice the difference in the length of the subpkt 28.

The len 19 packet contains "openpgp42@gmail.com", whereas the len 33 packet is "Stelian Pop openpgp42@gmail.com"

Everything else seem to be identical.

@stelian42
Copy link
Contributor

I was wrong. I have modified OpenKeychain to put only the email address into the Signer's User ID field, but it still fails to verify on Thunderbird.

The error is reported in the logs as:

[DEBUG] rnp-cryptoAPI.js: verifyMime()
[signature_validate() /build/thunderbird-77WqiC/thunderbird-78.7.1+build1/comm/third_party/rnp/src/lib/crypto/signatures.cpp:278] wrong lbits

@larabr
Copy link

larabr commented Apr 22, 2021

Can someone please share one signature that gives issues, and the public key? Then I can check the exact error returned by OpenPGP.js

@dingwen07
Copy link
Author

Can someone please share one signature that gives issues, and the public key? Then I can check the exact error returned by OpenPGP.js

I attach them. ZIP password is fOo_bAr1234

test_mails.zip

@larabr
Copy link

larabr commented Apr 22, 2021

Wrong ZIP password @dingwen07 :)

@dingwen07
Copy link
Author

Wrong ZIP password @dingwen07 :)

Probably because of the encryption algorithm, anyway following is an unencrypted one.

SHA1: C1A96133738481F55ADF6AF1EE541E4CB71D5BCB

test_mails.zip

@stelian42
Copy link
Contributor

I have done some extra debugging, and I think (emphasise on this, because I was wrong before...), that the problem is really in those two "lbits", which in fact are called "fingerprint" in OpenKeychain/bouncycastle terms, and which are supposed to be the first two bytes of the unsigned hash (see extern/bouncycastle/pg/src/main/java/org/bouncycastle/openpgp/PGPSignatureGenerator.java, around line 280)

I traced the low level exchanges and I can confirm that the two bytes in the final signature are NOT the first two bytes of the unsigned hash. RNP catches this, while I suspect gpg doesn't even check those two bytes, only the signed hash which is OK.

I'm trying to debug further and see why OpenKeychain generates the signature with the wrong two bytes fingerprint, but the data flow is still unclear to me (hash and signedHash are ok in SecurityTokenOperationActivity.java, but I'm not sure yet how this result is returned back and converted into the final signature).

stelian42 added a commit to stelian42/open-keychain that referenced this issue Apr 22, 2021
The previous code used java.security.MessageDigest.digest()
more than once, which is incorrect because the digest is reset
after each call.

This made OpenKeychain generate invalid signatures when
using a hardware token: the two bytes called "fingerprint",
which are supposed to be the first two bytes of the unsigned
digest, were incorrectly filled inside the signature.

Some tools do not check this fingerprint, only the signed digest,
so the signature was reported as valid. GPG is one of these tools.

But some other tools (like OpenPGP.js which uses rnp) did check it,
and reported an invalid signature, assorted with an error message
saying "wrong lbits". Thunderbird is one of the users of OpenPGP.js

This fixes bug open-keychain#2688
@stelian42
Copy link
Contributor

I was correct about the last assumptions about the digest being wrong.

See explanation and fix in PR #2695

Thunderbird does show a pretty green PGP tick now !

@stelian42
Copy link
Contributor

Fixed in current master.

@dschuermann
Copy link
Member

A fix has been released in 5.7.5

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