Closed maltfield closed 3 years ago
Thanks for the detailed and well-referenced report.
As I also fetch stuff from pypi, I am interested to know more:
Once signed, how can one verify that the signature was done by me ? In the sense of "which keys should be expected to have signed this package": it is trivially easy for an attacker to generate a key pair with my email address as identity, as sending email is not involved in issuance and verification processes. While I do have a gpg key on the email address present in setup.py
and which I also use to commit here, I believe I have exactly zero signatures on it (bad !), so its legitimacy is objectively questionable to anyone but me.
Yes, you should go to a local key signing party and get your key integrated into the WoT.
In the meantime, I recommend that you write a short txt file listing your name, any usernames/aliases you use, your email address, your master pgp key's full fingerprint, and stating that you're the project lead for this project. Be sure to include URLs to the project on github and PyPI to avoid ambiguity.
Sign the document and upload it to a few distinct domains (including here on github by including it in your repo). The WoT is helpful, but if the above cryptographically-signed txt file is available on many distinct authoritative domains, then it provides a mechanism for your clients to answer the question: "which keys should be expected to have signed this package?"
For best practices, see also:
I've just been playing with signature on another package I had to release (pprofile). I tried to first upload a non-signed tgz to test pypi, and then upload the signature. Both operations apparently succeeded, but I see no visible change on test pypi: only one file in the release. Then I uploaded both at once to normal pypi, and again I see no mention of the signature.
Is pypi very quiet about signatures, or am I doing something wrong ?
Thanks for your enthusiasm in fixing this issue! By making the signatures available on PyPI, you're giving the ability for downstream developers to secure their build pipelines.
PyPI doesn't have very good support for signatures, and none of the consumer tools support it; it's a power-user feature that users have to verify manually. But your signature is available. You just append .asc
to the the tarball to download it.
user@disp7439:~$ wget https://files.pythonhosted.org/packages/dd/db/198fd60559f77c5334f520e2a94cde5c8c6f5f4e65f82f5b22269e6e5ff2/pprofile-2.0.5.tar.gz
--2020-07-05 17:10:58-- https://files.pythonhosted.org/packages/dd/db/198fd60559f77c5334f520e2a94cde5c8c6f5f4e65f82f5b22269e6e5ff2/pprofile-2.0.5.tar.gz
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 54876 (54K) [application/x-tar]
Saving to: ‘pprofile-2.0.5.tar.gz’
pprofile-2.0.5.tar. 100%[===================>] 53.59K 45.0KB/s in 1.2s
2020-07-05 17:11:03 (45.0 KB/s) - ‘pprofile-2.0.5.tar.gz’ saved [54876/54876]
user@disp7439:~$ wget https://files.pythonhosted.org/packages/dd/db/198fd60559f77c5334f520e2a94cde5c8c6f5f4e65f82f5b22269e6e5ff2/pprofile-2.0.5.tar.gz.asc
--2020-07-05 17:11:08-- https://files.pythonhosted.org/packages/dd/db/198fd60559f77c5334f520e2a94cde5c8c6f5f4e65f82f5b22269e6e5ff2/pprofile-2.0.5.tar.gz.asc
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 833 [application/octet-stream]
Saving to: ‘pprofile-2.0.5.tar.gz.asc’
pprofile-2.0.5.tar. 100%[===================>] 833 --.-KB/s in 0s
2020-07-05 17:11:10 (29.2 MB/s) - ‘pprofile-2.0.5.tar.gz.asc’ saved [833/833]
user@disp7439:~$
Unfortunately, I was not able to find your key in a usable way. Please publish your public key in at least one location (with the UID) and publish the fingerprint widely so users can cross-reference several out-of-band sources to confirm the fingerprint of your key. Examples include:
Sorry for the delay.
I modified the wording of the KEYS file to
What do you think of this:
This file contains the PGP keys authorised to sign releases.
NOTE: Releases from version 1.8.1 onward must be expected to be signed.
If one is not signed, please do not use it, and report it as a bug.
Users:
Adding/updating trusted keys:
gpg --homedir <gpg homedir to verify this project's releases>
--import KEYS
Fetching and checking a release:
wget <pypi release URL>
wget <pypi release URL>.asc
gpg --homedir <gpg homedir to verify this project's releases>
--verify <release file name>.asc
Release maintainers:
Adding your key to this file:
LC_ALL=C; (gpg --list-sigs <your key id>
&& gpg --armor --export <your key id>) >> KEYS
Signing and publishing a release:
git clean -idx
python setup.py sdist check
# Check dist content before signing as desired
gpg --armor --detach-sign dist/<release file>
twine upload dist/<release file> dist/<release file>.asc
(to be followed by my key, too long to be worth pasting here)
I just uploaded my key to keys.openpgp.org and validated my main email address (the key has another one I still have control of but do not use).
I re-released 1.8 to test.pypi.org with a signature, if you could confirm I'm doing it right... I tried again uploading only the .asc to the regular pypi now that I know how to retrieve it, but it is not present for me. It probably only works if both are uploaded in one call then ?
I want to close #33 before the next release, which should be 1.8.1 unless something functionally bigger comes up.
Great to see progress on this, thanks :)
It looks good
user@disp2781:~$ wget https://test-files.pythonhosted.org/packages/27/5c/4d1ebbcfb19071832ac9b4e4674435f4a33e34b8d5186d4aac9ff374f83c/libusb1-1.8.tar.gz.asc
--2020-08-01 21:31:26-- https://test-files.pythonhosted.org/packages/27/5c/4d1ebbcfb19071832ac9b4e4674435f4a33e34b8d5186d4aac9ff374f83c/libusb1-1.8.tar.gz.asc
Resolving test-files.pythonhosted.org (test-files.pythonhosted.org)... 151.101.153.63, 2a04:4e42:24::319
Connecting to test-files.pythonhosted.org (test-files.pythonhosted.org)|151.101.153.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 833 [application/octet-stream]
Saving to: ‘libusb1-1.8.tar.gz.asc’
libusb1-1.8.tar.gz.asc 100%[==========================================>] 833 --.-KB/s in 0s
2020-08-01 21:31:27 (28.4 MB/s) - ‘libusb1-1.8.tar.gz.asc’ saved [833/833]
user@disp2781:~$ wget https://test-files.pythonhosted.org/packages/27/5c/4d1ebbcfb19071832ac9b4e4674435f4a33e34b8d5186d4aac9ff374f83c/libusb1-1.8.tar.gz
--2020-08-01 21:31:30-- https://test-files.pythonhosted.org/packages/27/5c/4d1ebbcfb19071832ac9b4e4674435f4a33e34b8d5186d4aac9ff374f83c/libusb1-1.8.tar.gz
Resolving test-files.pythonhosted.org (test-files.pythonhosted.org)... 151.101.153.63, 2a04:4e42:24::319
Connecting to test-files.pythonhosted.org (test-files.pythonhosted.org)|151.101.153.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 78282 (76K) [application/x-tar]
Saving to: ‘libusb1-1.8.tar.gz’
libusb1-1.8.tar.gz 100%[==========================================>] 76.45K 243KB/s in 0.3s
2020-08-01 21:31:31 (243 KB/s) - ‘libusb1-1.8.tar.gz’ saved [78282/78282]
user@disp2781:~$ gpg --list-packets libusb1-1.8.tar.gz.asc
# off=0 ctb=89 tag=2 hlen=3 plen=563
:signature packet: algo 1, keyid D6D2B809181BC8C0
version 4, created 1596288288, md5len 0, sigclass 0x00
digest algo 10, begin of digest 0a 3d
hashed subpkt 33 len 21 (issuer fpr v4 F1AE76AC4CAF41097D326A7DD6D2B809181BC8C0)
hashed subpkt 2 len 4 (sig created 2020-08-01)
subpkt 16 len 8 (issuer key ID D6D2B809181BC8C0)
data: [4095 bits]
user@disp2781:~$
user@disp2781:~$ wget https://keys.openpgp.org/vks/v1/by-fingerprint/983AE8B73B9115987A923845CAC936914257B0C1
--2020-08-01 21:33:44-- https://keys.openpgp.org/vks/v1/by-fingerprint/983AE8B73B9115987A923845CAC936914257B0C1
Resolving keys.openpgp.org (keys.openpgp.org)... 37.218.245.50, 2a00:c6c0:0:154:1::1
Connecting to keys.openpgp.org (keys.openpgp.org)|37.218.245.50|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5340 (5.2K) [application/pgp-keys]
Saving to: ‘983AE8B73B9115987A923845CAC936914257B0C1’
983AE8B73B9115987A923845CAC 100%[==========================================>] 5.21K --.-KB/s in 0s
2020-08-01 21:33:45 (106 MB/s) - ‘983AE8B73B9115987A923845CAC936914257B0C1’ saved [5340/5340]
user@disp2781:~$
user@disp2781:~$ gpg --import 983AE8B73B9115987A923845CAC936914257B0C1
gpg: key CAC936914257B0C1: public key "Vincent Pelletier <plr.vincent@gmail.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
user@disp2781:~$
user@disp2781:~$ gpg --verify libusb1-1.8.tar.gz.asc
gpg: assuming signed data in 'libusb1-1.8.tar.gz'
gpg: Signature made Sat 01 Aug 2020 07:09:48 PM +0545
gpg: using RSA key F1AE76AC4CAF41097D326A7DD6D2B809181BC8C0
gpg: Good signature from "Vincent Pelletier <plr.vincent@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 983A E8B7 3B91 1598 7A92 3845 CAC9 3691 4257 B0C1
Subkey fingerprint: F1AE 76AC 4CAF 4109 7D32 6A7D D6D2 B809 181B C8C0
user@disp2781:~$
The only thing I would maybe add to your KEYS file is
<pypi release URL>
) https://stackoverflow.com/a/62687869Thanks, changes applied and file pushed to master. I keep this bug open as an extra reminder for myself to actually sign the next release.
1.8.1 has just been released with signatures !
Feel free to reopen if I've done any mistake.
@vpelletier Can you please also add your gpg key to the OpenPGP.org keyserver and verify your email address?
Reason: Uploading your key to multiple distinct TLDs hosted by multiple places will allow people to double-check the fingerprint on two sites, which greatly reduces the risk of getting the wrong key (eg reduces need to trust GitHub).
Also, the more places you can upload it the better (for some, just write fingerprint 983A E8B7 3B91 1598 7A92 3845 CAC9 3691 4257 B0C1
if that makes more sense). Do you have any of the following?
The more places people can cross-reference to confirm that they have the correct key for you, the better.
EDIT: Oh, I see. It's listed on keys.openpgp.org as your gmail address :)
1. your personal website (not GitHub pages) 2. https://keybase.io/ 3. Social media presence (twitter/mastodon/etc) 5. Business Cards 7. Any other public "user profile" accounts you use
I have none of those.
4. Stack Exchange https://stackexchange.com/users/2522763/vpelletier
Updated, although it does not seem to appear on stackexchange profile, but does appear on the stackoverflow and meta profiles.
6. Email Signature
Done.
EDIT: Oh, I see. It's listed on keys.openpgp.org as your gmail address :)
Yeah, because I created this key long ago, then I stopped using the main email address associated with it (although I still have control of it for now), and left it there.
Describe the bug
When a user downloads this python module using
pip
, there is no cryptographic authenticity or integrity validation to protect the user from a MITM attack.Therefore, this project is making any other projects that obtain the
libusb1
module viapip
in their build process vulnerable to a watering hole attack.Expected behavior
A developer should have a mechanism to cryptographically verify the integrity and authenticity of libusb1 when obtaining it through
pip
.To Reproduce
pip install libusb1
Additional context
Possible solutions include:
Using the
--sign
argument oftwine
when uploading packages to PyPIPublishing a cryptographically signed document (ideally using
gpg
) listing the hashes for all packages uploaded to PyPI, which users can then pass intopip
using the--hash
argument