kazu-yamamoto / pgpdump

A PGP packet visualizer
http://www.mew.org/~kazu/proj/pgpdump/
BSD 3-Clause "New" or "Revised" License
173 stars 33 forks source link

pgpdump fails to dump OpenPGP RSA key generated using Bouncycastle #23

Closed vanitasvitae closed 6 years ago

vanitasvitae commented 6 years ago

Hi! I came across pgpdump failing to dump keys generated using bouncycastle 1.59.

Here is an example key:

-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: BCPG v1.59

lQOqBFr6hWUBCACK+EjkwiEjxEfphBNNgIitKJ40MuuyU57Ss2TE9On3wF2K5gHh
TwQr8gg4wU1lSTslIvG/GA0xY57VBM9MmVfhqC6gyz+sJQCFAD2qYeK65ePwH/I2
mpcSewuRsMKZtFpqOkDsdnaoGU2L7eC1H7PvZfpVLvKm1C16dtl6Oj7pOdMgsDt9
yLv/oMiIguvPdfSsB0F29mb7JIcAjpRz1yw+mP5GoC51P9HrNY3xe58HtIHk3VYx
H7e+vfLYZKhOuKFNVlh0vDi6drkjWFBJSs61dmsVQLu/JwP1UAm7ByMjLlUHUZGg
7v71sXRRvH94URKL3nEiagsctjNfcq/rJrCLABEBAAEAB/sHM9fJmtZquMihpHmu
NSCymV3Tay9YyKTYkgvKnlBckujT8L0dNPRoCc99tGZ8SAjbo4RdSyrll56K261Q
zBTs3sPOwqDUHWxC+Gm5xiUhEai4Jze2bhCMz3B7/VelNroYDca4WrMmXew2eeMT
WT43zct3cJ2Kxvcjlzu/28SGhAOBf/BU/5J9m4ibnyiLzYV2pttSnI8znjR5b92Z
Lj3KdnQJcWd+vFGfayVIaH09qIv+kkKfxJPGdsK32cJ10a3kKDYmFbihTU2r5fGA
QYJW5Jx0Lu6/uovusgWiuQgvj/6uZI4DbcR5e+PhM1sccQ7ObaKSQbbe/RpdSDwZ
FFhJBAC2lf8ZDXnXctBR5IcI/84DNpsFtSv0Y6rweOB9w9DC5WGINiIwbeSb+YBw
2NKk9I/XO+Vp7+lhUI0273eE/6mSg7HYZU9LYrQ0A8RLgbqjN+K4Bs9Ai3pLA9f6
rLxzYI0cMuVYQYZ+Xh8OPVNC8C9+KJp2QNhqZHZXaf5kaDFweQQAwtjIhbAKG+qO
BqcaOE20by6QIH378k/VW798gRU8S/ohsMNGsU8l6K8uDeDrsZYGowy3Naq9bVV/
xAfQHR9nlXOGumfMrWrzl6H2Zfqq6yTZsjBjo9yeL4n26VIgf3KCmp+gHfYY4ftI
q/NGNEtOijFI0z10MTD4Y3xH9zyS0CMD/irjqzF0E1HEwF617Kw8zMbHaozjsYEG
xZvSJtwM3mduyxANASORLGiQcZo9t8TSZBi1YdF3CtVO2stXZY+3rD1aQWSHxbhN
hhGdr8CXZ57Wq363wi4epxVj5y+DE8+W2RTtHUWkRoMNR7MatO9Fu6fzrhJvQKr9
0miAyNtgibaGfyqQGiOR0hKyZUj2qO4egsGBXVK0GXhtcHA6YWxpY2VAd29uZGVy
bGFuZC5saXSJATQEEwEIAB4FAlr6hWUCmy8FiwkIBwIGlQoJCAsCBJYCAwECngEA
CgkQjj26DsTcw7fvVgf/Y88ABzLXTFgLo4EO1z7eBNT4Y4dJ8zyKNkcwJRVbOup1
lVNwMb65IyqnxbTXVssAHMYD9EmHzQfV1B/BlcH3DhYnVNpOoOreW93rTRcZS2Ew
UtACUBZatc+nZCyJ/2cSm862upKkYSWWBhQj7W0wj+UmnGZbbzQFZhO3zZC8OISv
X48gB9DlvRcjTypdNxfY+LQv5r4oebwABRisq9bqnfRsGt3JaoeeGS//EqppST6T
7niM96sp1dxHUKaUAqS0lxCkfUo2vv7pH8REY3t1VTvVe/d2FpMBs77wHMQSKlGZ
ovSdIgpRjJZ3TZQkMgreW31TSySr/DCZ2HwLiIp1TQ==
=8D8m
-----END PGP PRIVATE KEY BLOCK-----

pgpdump gives me this output:

$pgpdump bc.sec
Old: Secret Key Packet(tag 5)(938 bytes)
    Ver 4 - new
    Public key creation time - Tue May 15 08:59:49 CEST 2018
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(2048 bits) - ...
    RSA e(17 bits) - ...
    RSA d(2043 bits) - ...
    RSA p(1024 bits) - ...
    RSA q(1024 bits) - ...
    RSA u(1022 bits) - ...
    Checksum - 7f 2a 
Old: One-Pass Signature Packet(tag 4)(26 bytes)
    Unknown version(35)
    Sig type - unknown(91)
    Hash alg - unknown(hash 210)
    Pub alg - Reserved for Elliptic Curve(pub 18)
    Key ID - 0xB26548F6A8EE1E82
    Next packet - other than one pass signature
Old: Reserved(tag 0)(23890 bytes)
pgpdump: unexpected end of file.

On the other hand gpg lists the key as follows:

$ gpg --list-packets bc.sec 
# off=0 ctb=95 tag=5 hlen=3 plen=938
:secret key packet:
    version 4, algo 1, created 1526367589, expires 0
    pkey[0]: [2048 bits]
    pkey[1]: [17 bits]
    skey[2]: [2043 bits]
    skey[3]: [1024 bits]
    skey[4]: [1024 bits]
    skey[5]: [1022 bits]
    checksum: 7f2a
    keyid: 8E3DBA0EC4DCC3B7
# off=941 ctb=b4 tag=13 hlen=2 plen=25
:user ID packet: "xmpp:alice@wonderland.lit"
# off=968 ctb=89 tag=2 hlen=3 plen=308
:signature packet: algo 1, keyid 8E3DBA0EC4DCC3B7
    version 4, created 1526367589, md5len 0, sigclass 0x13
    digest algo 8, begin of digest ef 56
    hashed subpkt 2 len 4 (sig created 2018-05-15)
    critical hashed subpkt 27 len 1 (key flags: 2F)
    critical hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
    critical hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
    critical hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
    critical hashed subpkt 30 len 1 (features: 01)
    subpkt 16 len 8 (issuer key ID 8E3DBA0EC4DCC3B7)
    data: [2047 bits]

Most importantly note the differing key id. Do you have any idea what's going on?

HeikoStamer commented 6 years ago

Maybe a SHA-1 hash (20 bytes) instead of a checksum (2 bytes) is appened after the secret RSA values, although S2K usage convention is 0 (cf. sec. 5.5.3 RFC 4880). However, both (GPG and pgpdump) fail to detect this issue.

vanitasvitae commented 6 years ago

@cwgit do you have an idea?

kazu-yamamoto commented 6 years ago

I have read RFC 4880 again but it seems to me that plain_Secret_Key() is implemented as the RFC specifies.

kazu-yamamoto commented 6 years ago

Maybe a SHA-1 hash (20 bytes) instead of a checksum (2 bytes) is appened after the secret RSA values, although S2K usage convention is 0 (cf. sec. 5.5.3 RFC 4880). However, both (GPG and pgpdump) fail to detect this issue.

@HeikoStamer You are right. Skipping 18 more bytes displays this data correctly.

kazu-yamamoto commented 6 years ago

So, I believe that this is a bug of bouncycastle 1.59.

vanitasvitae commented 6 years ago

@HeikoStamer @kazu-yamamoto Thank you, I will report it back to them and see if I can work around that issue in my case :)

vanitasvitae commented 6 years ago

David Hook from BouncyCastle wrote me this:

Ask them to read the last paragraph of Section 5.5.3 RFC 4880.

" The two-octet checksum that follows the algorithm-specific portion is
   the algebraic sum, mod 65536, of the plaintext of all the algorithm-
   specific octets (including MPI prefix and data).  With V3 keys, the
   checksum is stored in the clear.  With V4 keys, the checksum is
   encrypted like the algorithm-specific data.  This value is used to
   check that the passphrase was correct.  However, this checksum is
   deprecated; an implementation SHOULD NOT use it, but should rather
   use the SHA-1 hash denoted with a usage octet of 254.  The reason for
   this is that there are some attacks that involve undetectably
   modifying the secret key."

There is further discussion on this earlier in Section 5.5.3 as well.

Regards,

David

Update: David is not sure any more, he'll look into it once more.

bcgit commented 6 years ago

Yes, the issue was actually the S2K usage. This should now be fixed. Apologies for my confusion.

HeikoStamer commented 6 years ago

@vanitasvitae If you post a fixed example key, I can check it against dkg-keycheck with DKGPG

bcgit commented 6 years ago

I think this one should be correct. Let me know. Thanks.

-----BEGIN PGP PRIVATE KEY BLOCK----- Version: BCPG v1.60b05

lQOYBFr8nnABCADAnm0auu+rqBL7HdAPo+WKfL47hHNzB6dC34SLWS1UGjPRPQH4 Iqf6/3sqI2XpwJO0yjs1y3WKobb1JQpcdfM12W4O69k4zK5FUMYBQDTOj4LJQeLf xTtJB9sTHjSDMNzRl+sH77sCm0bjpyMDrRy4AaefP0tImDGhudKUzok1swGFP9cN cWVrCGeDLY47ziw/jAiKs6GX6DPeJZsedZD4pO7vjT7bjadvEPaDfdgO+Lc3gFDF sYLu+tVgIMa4PwHwbR3MO9vjuzIwQNPo5uUvBGcTA6ohgW+Hcplfj1eUItSilzNH Iq833WcHlvs+N8qVIpxGLtFnkfHW9RSJV6H7ABEBAAEAB/4l3sAKslguwqPAtXLT sGCP4siwAPGF2ypaboGruAO+dkxbxgfeFko6ggJgHYeK9q7Tq7MKd48Li5HiDr9D wHjpzG7kBiC2Fx/oRuI3Gr2HIxYOpaKKZkeqqx26W4TtiizQFHNEIzD8aTT9yz2K Gn37+29OUu5lPm77ogIx+Y1mfgx2n39iv1NpbfaSvtxRlsuMhIl+uESFYMXuow4S pJZ325lIpNRA+tU0dt9lKEok+T5S7eMMNh0+DsiM5x0XoroJSPITNEwRFUxJMYM1 pJoRAh2/LMHTEKvEzb7qp3GdcD7rDhFSHRhlR9p3MnU6F3yE05zJe+iRsb9nEwwX 21WxBADIbuijq0ZuS4uit9s0+A7YPrq1+NII1sBT4PnbyoSm8q7lTUhz9+MLtCPD sa3wCVr85R38Y+uvccZJrWE9MpZliU7O+hJ/1w6C7fD7jp9UXNhE1SZ0nnI0sj70 vX44D/4C7S8nb+u8GbrJ8Z6BsCQpPwxznbomSTQGu6lzbR2YUwQA9gTqx9Aagutn 3hJ6/1pLnSGePdKOdsRtmw75EdiRMAeMmFJMKmYeUPXz+e/Mn0KGHl+7My4xKg0C gX4GaBvnjzrkdv2+pI91ca2aez9xCT/C0WmfmSJKzC2auWMjN7KtdvIBGjOh8u5y aKcq/aqsKkLAmEFJdE9+ijGZK8qPerkD/1IiiVKYHPXVdJZ3HMVDU34rTzfdMFXd Js7+K2V3Jh5N0trLQRsiubJ8PyrZHMXqrbau1gViRw3iGyNLveuEym3bCVGwMXZr Rtj9zMuOQGAfy1JhzdN92m1iLWloN13Cjrlw5Vi2ZR1ukyBQdSvGiEsjQr4vRMbR 1Zq9J1sBLj/yPQy0F3htcHA6anVsaWV0QGNhcHVsZXQubGl0iQE0BBMBCAAeBQJa /J5wApsvBYsJCAcCBpUKCQgLAgSWAgMBAp4BAAoJEMMQKbEcq6QsPcwH/0y9EcS7 +y7DlG+l/dikC3l/dZXXq/GgQaU7dwntrDdcqDZ7W4qdFcWeBMROSWJ/+gGq68uO sT/qj3fVuCMWYM8ddu+U4vMwV3PF646NR8E1ih8Xhn9l4TBIKJIDGEpHDcBRRJD2 clEtyQNZhe9hqKP8meR/f97tVROAyUft68HjiepqPaC8B+F2U5Amx/+gWtK5h6R4 qYEM1r7yz84pnW44+B+8mbzf2XgxlMYSfJz3L7fsjhZu+8ExB+qrCV8QIMztugFv zP+rlceWu21AJgGtGh31O2evhCRh2/+B2Sfmixn/jJMMjy5EGUqbfzwSJXWeIBYC BuNShngvvR2FPEU= =tt7J -----END PGP PRIVATE KEY BLOCK-----

HeikoStamer commented 6 years ago

@bcgit Yes, it seems to be okay. $ dkg-keycheck -V -V -p bc.asc INFO: using LibTMCG version 1.3.13 INFO: encdatalen = 0 INFO: skalgo = 0 INFO: s2kconv = 0 INFO: s2k_type = 0 s2k_hashalgo = 0 s2k_count = 0 INFO: key ID of private primary key: c3 10 29 b1 1c ab a4 2c INFO: key ID of primary key: c3 10 29 b1 1c ab a4 2c INFO: number of selfsigs = 0 INFO: number of keyrevsigs = 0 INFO: number of certrevsigs = 0 INFO: number of userids = 1 INFO: number of userattributes = 0 INFO: number of subkeys = 0 INFO: number of revkeys = 0 INFO: userid = "xmpp:juliet@capulet.lit" INFO: number of selfsigs = 1 INFO: number of revsigs = 0 INFO: number of certsigs = 0 INFO: user ID is valid INFO: primary key update expirationtime to 0 INFO: primary key update flags to 2f INFO: primary key update features to 1 INFO: primary key update psa to 9 8 7 2 INFO: primary key update pha to 10 9 8 11 2 INFO: primary key update pca to 2 3 1 INFO: primary key update revkeys with added INFO: key flags on primary key are CSEeA INFO: RSA with |n| = 2048 bits, |e| = 17 bits OpenPGP V4 Key ID of primary key: C31029B11CABA42C OpenPGP V4 fingerprint of primary key: EBB9 5CEA C034 D603 9170 C2A2 C310 29B1 1CAB A42C OpenPGP Key Creation Time: Wed May 16 23:11:12 2018 OpenPGP Key Expiration Time: undefined OpenPGP Revocation Keys: none OpenPGP Key Flags: CSEeA Public-key algorithm: RSA Security level of public key: |n| = 2048 bit, e = 65537 n is not probable prime n is congruent 3 mod 4 n = ... Legendre-Jacobi symbol (i/n): #(+1) = 4999340 #(-1) = 5000659 e is probable prime e is okay OpenPGP User ID: xmpp:juliet@capulet.lit

bcgit commented 6 years ago

Thanks for confirming it.