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

SHA1 PGP signatures aren't supported anymore #3185

Open
g2p opened this issue Feb 1, 2023 · 14 comments
Open

SHA1 PGP signatures aren't supported anymore #3185

g2p opened this issue Feb 1, 2023 · 14 comments
Labels

Comments

@g2p
Copy link

g2p commented Feb 1, 2023

Problem

As described here: https://www.reddit.com/r/rust/comments/10qlf1q/nightly_dc1d9d50f_20230131_signature_verification/

rustup update and rustup check report that https://static.rust-lang.org/dist/channel-rust-nightly.toml / https://static.rust-lang.org/dist/channel-rust-nightly.toml.asc aren't valid anymore.

Steps

rustup check

751.7 KiB / 751.7 KiB (100 %) 719.4 KiB/s in  1s ETA:  0s
warning: Signature verification failed for 'https://static.rust-lang.org/dist/channel-rust-nightly.toml'
nightly-x86_64-unknown-linux-gnu - Update available : 1.69.0-nightly (001a77fac 2023-01-30) -> 1.69.0-nightly (dc1d9d50f 2023-01-31)
rustup update
rustup update nightly
info: syncing channel updates for 'nightly-x86_64-unknown-linux-gnu'
warning: Signature verification failed for 'https://static.rust-lang.org/dist/channel-rust-nightly.toml'
info: latest update on 2023-02-01, rust version 1.69.0-nightly (dc1d9d50f 2023-01-31)
^C

Manually

cd ~/src/github.com/rust-lang/rustup
curl -O https://static.rust-lang.org/dist/channel-rust-nightly.toml
curl -O https://static.rust-lang.org/dist/channel-rust-nightly.toml.asc
sqv --keyring src/rust-key.pgp.ascii channel-rust-nightly.toml{.asc,}
Signing key on 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE is not bound:
           No binding signature at time 2023-02-01T00:44:45Z
  because: Policy rejected non-revocation signature (PositiveCertification) requiring second pre-image resistance
  because: SHA1 is not considered secure since 2023-02-01T00:00:00Z

sqv is from cargo install sequoia-sqv.

Possible Solution(s)

This should be fixed outside rustup, but I don't know where to file a report on the release process. Please switch away from using SHA1 in keys or signatures.

Notes

No response

Rustup version

rustup --version
rustup 1.25.1 (bb60b1e89 2022-07-12)

Installed toolchains

nightly-x86_64-unknown-linux-gnu
@pietroalbini
Copy link
Member

Working on a fix.

@pietroalbini
Copy link
Member

Thanks for investigating this! I opened a PR that should suppress the warning, hopefully we'll be able to release a new Rustup version with that today. #3186

@reillysiemens
Copy link

Thanks for being so on top of this, @pietroalbini!

@rbtcollins
Copy link
Contributor

Do we need to do more work here (e.g. switch to a stronger hash in the infra channels, and resign older releases?)

@bjorn3
Copy link
Member

bjorn3 commented Feb 14, 2023

As I understand it SHA1 is used as part of signing subkeys of the root signing key. It isn't used as part of signing the actual release tarballs.

@nwalfield
Copy link

Do we need to do more work here (e.g. switch to a stronger hash in the infra channels, and resign older releases?)

It would be good to update the signing certificate so that it is valid without SHA-1. This can be done with e.g. sq-keyring-linter --fix.

Ideally, rustup would also opportunistically download the certificate in order to get updates, e.g., from https://rustup.rs/root.pgp and from https://keys.openpgp.org. Since the certificate is pinned in rustup, an attacker may be able to withhold updates (although this is mitigate partially by checking for updates from multiple locations), but they won't be able to trick the user into using the wrong certificate.

@kpcyrd
Copy link

kpcyrd commented Feb 15, 2023

Be careful when refreshing update keys out of band, this should only update existing keys but reject any new subkeys to not break future update transparency efforts.

@nwalfield
Copy link

Be careful when refreshing update keys out of band, this should only update existing keys but reject any new subkeys to not break future update transparency efforts.

Why should new subkeys be rejected?

@kpcyrd
Copy link

kpcyrd commented Feb 15, 2023

The rust release key rust-key@rust-lang.org is currently setup like this (although the first one is technically not a subkey):

108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE  Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE  Subkey 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE  Subkey C13466B7E169A085188632165CB4A9347B3B09DC
108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE  Subkey 29D57CE15D76E78CD57D326A8E9AA3F7AB3F5826

Or in gpg output:

% gpg --fingerprint --fingerprint --list-keys 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
pub   rsa4096 2013-09-26 [SC]
      108F 6620 5EAE B0AA A8DD  5E1C 85AB 96E6 FA1B E5FE
uid           [ unknown] Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
sub   rsa4096 2013-09-26 [E]
      29D5 7CE1 5D76 E78C D57D  326A 8E9A A3F7 AB3F 5826
sub   rsa4096 2014-12-15 [S]
      C134 66B7 E169 A085 1886  3216 5CB4 A934 7B3B 09DC

This means the following keys can issue signatures for updates and need to be monitored (I guess the encryption-only key can be ignored):

108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
C13466B7E169A085188632165CB4A9347B3B09DC

This is currently hard-coded into the rustup binary, as long as I can ensure the user has a legitimate copy of rustup I can be sure it's going to attempt to enforce this policy.

Now if we allow subkey updates (essentially "if we allow delegation of trust"), somebody with access to 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE could issue a new subkey (we're going to refer to it as 1337133713371337133713371337133713371337) that also has the signing capability enabled. If the person we're targeting downloads this key (or especially if it's going to saved to ~/.rustup), their new set of trusted keys that can issue signatures for updates looks like this:

108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
C13466B7E169A085188632165CB4A9347B3B09DC
1337133713371337133713371337133713371337

But because you don't know about this secret subkey you're still monitoring the transparency log for these two keys:

108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
C13466B7E169A085188632165CB4A9347B3B09DC

This means I could safely submit my malicious update (signed by 1337133713371337133713371337133713371337) to the transparency log and get inclusion proof without setting of any alarms. Even if the signature gets discovered during the attack it would be very difficult to detect the key compromise itself because you can't know if the signature from 1337133713371337133713371337133713371337 has any trust delegated to it unless you also know the content of ~/.rustup of the user I'm targeting.

@nwalfield
Copy link

Thanks for your write up. What transparency log are you talking about? I wasn't aware that rustup was using that.

@kpcyrd
Copy link

kpcyrd commented Feb 15, 2023

(This went slightly off-topic, feel free to skip to the next section):

rustup itself isn't using any transparency log, there are two projects attempting to do this for pgp-in-general though:

Searching for the public rekor log currently yields one entry for the rust release key (src/rust-key.pgp.ascii is located in the rustup repository):

% rekor-cli search --public-key src/rust-key.pgp.ascii
Found matching entries (listed by UUID):
24296fb24b8ad77a49f171daa9a8b39041e6b36ec74785714cead6b07b7293d910440c751875550d

Inspecting the entry shows it's a signature over the sha256 hash 642f09caa48e97de84958f8d4da5160ca298b94bf5360ba12c15be72877d487a:

% rekor-cli get --uuid 24296fb24b8ad77a49f171daa9a8b39041e6b36ec74785714cead6b07b7293d910440c751875550d
LogID: c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d
Index: 12409326
IntegratedTime: 2023-02-01T13:51:48Z
UUID: 24296fb24b8ad77a49f171daa9a8b39041e6b36ec74785714cead6b07b7293d910440c751875550d
Body: {
  "RekordObj": {
    "data": {
      "hash": {
        "algorithm": "sha256",
        "value": "642f09caa48e97de84958f8d4da5160ca298b94bf5360ba12c15be72877d487a"
      }
    },
    "signature": {
      "content": "LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KCndzRmNCQUFCQ2dBUUJRSmoyYlg5Q1JDRnE1Ym0raHZsL2dBQUdiVVAvQWhoYS9GU3hqQitSL0RRWTArSExZVTgKMy81MEFqWGpyRFhwZ0JoV0YwbTJoTjJkVWxsZXdUNTV0R2JOdzNJeUduSmQwRmxNZWZtTU1EVkswM081aFphcwpxdFVhbXVWUTZDYWRVSm4xVGtpdzZESnowSTRJd3hpQWJlNlB5NmJ6WjhUNHZwcWVGUE9BajRsR0dNNS82eFZsCm5FNXJnK1pUY09na1hlZFdsZkNpY1J4TmJTVmtFYTNsczVJbWtrRU04bW9uc1JjRmszZXRVOUJ2aG1MSWNVSk0KMlVaRU1KWHlwUjk3REh5WWN2TkNFdE5RaWw1Z1NscVZaZXFFUlY0VmFZanNkZnVtS0lnUWoxQjAzQ3BZcEUwZgpyL29sR3BUNjk1ZFhUV2FsbVp4aWg5RTU1czkvVTFETlpvcXU1b3FzWG56T3VsVC9MV2lsVzI2KzltRXhyZDFKCkZPdi9iTW5WUFNNMEJFbVEzRFp5L2IrVmNTY09jcDMvMEhMOXREZmtWTjliQ3g5aTlENlEzUkYxMDNhVmY3NWQKLzVZdENScFIyaWhQYlovZkxxWk5SSkdGSHRsVlljK2ZxTzdKRXRxOTdEdnY0Wkg0RStETE5oMGYvT1lYdG1XbwpUNXRjSURyQ0lGaGROQ2ZEa2VONWt5Zk4wZjdDWERYQUhZQnRUMHFkb0U4VExsNzdFRFhVNzl0S3BxYUxwczMyCmIzYnF0SHFKbkVvUlZ5c2tXRnJUZk5pQ2k0MTdGL0t0N2ljMGlGSWxIVURJWHhOcVVSQWhvOVhobkwrb3dodEwKVjlxRHcvelBnZWt5eUNqU2FsNjhJV3hUSUtUTDFtLzJVOEhNSTJNdXV1VVpjYm1qUkJDanIrZE52bEtSSU51aQpIR04rcFo5TFFCazI5NEhKWlNRUwo9eEFkbQotLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS0K",
      "format": "pgp",
      "publicKey": {
        "content": "LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgp4c0ZOQkZKRXdNa0JFQURsUEFDYTJLN3JlRDR4NXpkOGFmS3g3NVFZS214cVp3eXdSYmdlSUNlRDRiS2lRb0paCmRVam1uMUxnckdhWHVCTUtYSlFoeUEzNGUvMVlaZWwvOGV0K0hQRTVYcGxqQmZOWVhXYlZvY0UxVU1VVG5GVTkKQ0tYYTRBaEozM2Y3d2UyL1FtTlJNVWlmdzVhZFB3R01nNEQ4Y0RLWGswMk5kbnFRbG1GQnl2MHZTYUFyUjVrbgpnWktuTFk2bzB6WjlCdXl5NzYxSW0vU2hYcXY0QVRVZ1lpRmM0OHozM0c0aitCRG1uMHJ5R3IxYUZkUDU4dEhwCmdqV3RMWnMwaVdlRk5SRFlEamU2T0R5dS9Nak95dUFXYjJwWURINDdYdTdYZWRNWnplbkgyVExNOXl0L2h5T1YKeFJlRFBodm9Ha2FPOHhxSGlvSk1vUFFpMWdCanVCZWV3bUZ5VFNQUzRkZUFTdWtoQ0ZPY1Rzdy9lbnpKYWdpUwpaQXE2SW1laGR1a2UrcGVBTDF6NFB1Um16RFBPMkxQaFZTN0NEWHR1S0FZcVVWMllha1RxOE1aVWVtcFZodzVuCkxxVmFKNS9YaXlPY3Y0MDVQbmtUMjVlSVZWVmdoeEFneXo2Yk9VL1VNakdRWWxrVXhJN1laOXRkcmVMbEZ5UFIKT1VMMzBFOHEvYUNkNFBHSlYyNHlKMXVpdCt5Uzh4anlVaU1LbTRKN29NUDJYZEJOOThUVWZMR3c3U0tlQXh5VQo5MkJIbHhnN3l5UGZJNFRnbHNDem9TZ0VJVjZ4b0dPVlJSQ1lsR3pTalVmejBiQ01DY2xoVFFSQmtlZ0tjakIzCnNNVHlHM1NQWmJqVGxDcXJGSHkxM2U2aEdsMzdOaHM4L012WFV5c3EyY2x1RUlTbjViaXZUS0VlZVFBUkFRQUIKelVSU2RYTjBJRXhoYm1kMVlXZGxJQ2hVWVdjZ1lXNWtJRkpsYkdWaGMyVWdVMmxuYm1sdVp5QkxaWGtwSUR4eQpkWE4wTFd0bGVVQnlkWE4wTFd4aGJtY3ViM0puUHNMQmVBUVRBUUlBSWdVQ1VrVEF5UUliQXdZTENRZ0hBd0lHCkZRZ0NDUW9MQkJZQ0F3RUNIZ0VDRjRBQUNna1FoYXVXNXZvYjVmNWZZUS8vYjFEV0sxTlNHeDVuWjN6WVplSEoKOW13R0NmdElhQTJJUmdoQUdyTmY0WThEYVBxUit3MU9kSWVnV244a0NvR2ZQZkdBVlc1WFhKZytPeGs2UUlhRAoyaEpvakJVcnExREFMZUNaVmV3elRWdzZCTjRER3VVZXhzYzUzYThEY1kyWWs1V0UzbGw2VUtxL1lQaVdpUE5YCjlyOEZFMk1Kd01BQkI2bVdaTHFKZWc0UkNycmlCaUNHMjZOWnhHRTdSVHRQSHlwcG9WeFdLQUZEaVd5TmRKKzMKVW5qbGRXclQ5eEZxanFmWFd3OUJoejgvRW9hR2VTU2JNSUFRRGtRUXBwMVNXcGxqcGdxdmN0WmxjNWZIaHNHNgpsbXpXNVJNNE5HOE9LdnEzVXJCaWh2Z3p3cklmb0VES3BYYmszRFhxYVNzMW84MU5INWZ0VldXYkpwL3l3TTlRCnVNQzZuMFlXaU1aTVExY0ZCeTd0dWtwTWtkK1ZQYlBraVN3QmhQa2ZaSXpVQVdkNzRuYW5ONVNLQnRjbnltZ0oKK09KY3hmWkxpVWtYUmowYVVUMUdMQTkvN3duaWtoSkkrUnZ3UmZIQmdyc3NYQktOUE9mWEdXYWp0SUFtWmMydAprUjFFOHpqQlZMSWQ3cjVNOGc1MkhLaytKK3k1ZlZnSlk5MW54RzB6Zjc4MkpqdFl1ejkra25RZDU1SkxGSkNPCmhoYnYzdVJ2aHZrcWdhdUhhZ1I1WDl2Q010Y3ZxRHNlSzdMWHJSYU9kT1VEcksvWmcvYWJpNWQrTkl5WmZFdC8KT2JGc3YzaWRBSWUvenBVNnhhMW5ZTmUzK0l4bGI2bWxabTNXQ1dHeFdlK0d2Tlcva3EzNmpaL3YvOHBZTXlWTwpwL2tKcW5mOXk0ZGJ1ZnVZQmcrUkxxRE93VTBFVWtUQXlRRVFBTnh5MnRUU2VSc3BmcnBCazkranUrS1ozemM0CnVtYUlzRWE1RHhKMnpJS0h5d1ZBUjY3VW0wSzFZUkcwNy9GNSt0RDlUSVJrZHgycGNtcGptU1F6cWRrM3pxYTkKMlp6ZWlqanoyUk55Qlk4cVlteUUwOEluY2pUc0ZGQjhPbnZkWGNzQWdqQ0ZtSTFCS25lUHhyQUJMLzJrOFgxOApheXNQYjBiZVdxUVZzaTVGc1NwQUh1Nmsxa2FMS2MrMTMweDZIZi9ZSkFqZW8rUzdIZVU1TmVPejN6RCtoNWJBClEyNXFNaVZIWDNGd0g3ckZLWnRGRm9nOU9nanppMFRrREtLeG9lRkt5QURmSWR0ZUpXRmpPbENJOUtvSWhmWHEKRXQ5Sk1ueEFwR3FzSkVsSnRmUWpJZGhNTjRMbmVwMldrdWRIQWZ3Si80MTJmZTd3aVcwcmNCTXZyL0JsQkdSWQp2TTRzVGdOMDU4RXdJdVk5UW1jOFJLNGdiQmY2R3NmR05Kaldveko1WG1YRWxta1FDQXZiUUZvQWZpNVRHZlZiCjc3UVFyaHJRbFNwZklZcnZmcHZqWW9xajYxOFNiVTZ1Qmh6aDc1OGdMbGxtTUI4TE9oeFd0cTlleW4xck1XeVIKS0wxZkVrZnZ2TWM3OHpQK1B4NnlETWE2VUllejhqWlhRODdab3U5RXJpTGJ6RjRRZklZQXFSOUxVU01uTGs2SwpvNjF0U0ZtRkVEb2JDM3RjMWprU2c0elplL3d4c2tuOTZLT2xtbnhnTUdPMHZKN0FTcnlub3hFblFFOGszV3dBCisvWUpEd2JvSVI3ekR3VHkzSnczbW4xRmduSCtjN1JiOWg5Z2VPenhLWUlOQkZ6NUhkME1LeDdrWjFVNldvYlcKS2lZWXhjQ21vRWVndVNQSEFCRUJBQUhDd1Y4RUdBRUNBQWtGQWxKRXdNa0NHd3dBQ2drUWhhdVc1dm9iNWY3ZgpGQS8vUmEraXRKRjROc0V5eWh4NHhZRE9QcTR1ajBWV1ZqTGRhYkR2RmpRdGJCTHdJeWgyYm04dU8zQVk0ci9yCnJNNVdXUThvSVhRMnZ2WHBBUU85ZzhpTmxGZXo2T0x6YmZkU0c4MEFHNzRwUXFWVlZ5Q1F4RDdGYW5CL0tHZ2UKdEFvT3N0RnhhQ0FnNG54Rmxhck1jdEZxT09YQ0ZreWxXbDUwNEpWSU92Z2JiYnlqNkk3cUNVbWJtcWF6QlNNVQpLOGMvTnorRk51MlVmL2xZV09lR29nUlNCZ1MwQ1ZCY2JtUFVwbkRITHhaV05YRFdRT0N4YmhBMVVmNThoY3l1CjAzNmtraVdIaDJPR2dKcWxvMldJcmFQWHgxY0d3MUV5K1U2ZXhidHJaZkU1a005cFp6Ukc3Wlk4M0NYcFlXTXAKa3lWWE5XbWY5SmNJV1dCclh2Sm1NaTBGRHZ0Z2czUHQxdG5veHFkaWxrNnloaWVGYzhMcUJuNkNaZ0ZVQmswdApOU2FXazNQc04wTjZVdDhWWFk2c2FpN01KMEdpaDFnRTF4YWRXajJ6Zlo5c0xHeXQyalo2d0srK1U4ODFZZVhBCnJ5YUdLSjhzSXMxODJod1FiNHFON2VpVUh6THRJaDhvVkJIbzhRNEJKU2F0ODhFNS9nT0Q2SVFJcHhjNDJpUkwKVCtvTlp3MWhkd055UE9UMUdNa2tuODZsM283a2x3bVFVV0NQbTZ2bDFhSHAzb21vK0dIQzYzUHBORk81Um5jSgpJbG8zYUJLS21vRTVsRFNNR0U4S0ZzbzVhd1RvOXo5UW5WUGtSc2s2cWVCWWl0OXhFM3gzUytpd2pjU2cwbmllCmFBa2MwTjAwbmM5VjlqZlB2dDR6LzVBNXZqSGgrTmhGd0g1aDJ2QkpWUGRzejZuT3dVMEVWSTlrZUFFUUFMM1IKb1ZzSG5jSlRtakhmQk9WNEpKc3ZDdW00RHVKRFovckRkeGF1R2NqTVVXWmFHMzM4WmVobkRxRzFZbi95czd6RQphS1lVbXF5VCtYUCtNMklBUVJUeXh3bFUxUnNEbGVtUWZXckVTZlpRQ0NtYm5GU2NMMEU3Y0J6eTR4dnRJblFlClVhRmdKWjFCbXhielFyeCtlQkJkT1REdjdSTG5OVnlnUm1Nem1rRGh4TzFJR0V1MSszRVRJZy9EeEZFN1ZRWTAKSXQvWXd6K25IdTFvNEhlbWMvR2RLeHU5aGNZdmNSVmMvWGh1ZXEvemNJTTk2bDBtK0NGYnMwSE1LQ2o4ZGdNZQpOZzZwYmJEak5NK2NWKzVCZ3BSZElwRTJsOVc3SW1wYkxpaHFjWnQ0N0o2b1d0L1JEUlZvS096UnhqaFVMVnlWCjJWUDlFU3I0OEhuYnZ4Y3B2VUFFRENRVWhzR3B1cjRFS0hGSjlBbVE0emY5MWdXTHJEYzZRbWxBQ245bzlBUlUKZk9WNWFGc1pJOW5pMU1KRUluSlRQMzdzdHovdURFQ1JpZTRMVEw0TzZQNERrdG84Uk9NMnd6WnE1Q2lSTmZuVApQUDdBUmZ4bENrcGcrZ3BMWVJseEdVdlJuNkVlWXdEdGlNUUpVUVBmcEdIU3ZUaFVsZ0RFc0RycHA0U1FTbWRBCkNCK3J2YVJxQ2F3V0tvWHMwSW4vOXd5bEdvclJVdXBlcUdDMEkwL3JoK2Y1bWF5RnZPUnp3eS80S0s0UUlFVjkKYVlUWFR2U1JsMzVNZXZmWFUxQ3VtbGFxbGU2U0RrTHIzWm5GUWdKQnFhcDBZK05tbXoySGZPL3BvaHNidEhQWAo5MlNOM2RLcWFvU0J2ek5HWTVXVDNDc3F4RHRpazM3a1IzZjkvREhwQUJFQkFBSEN3MzRFR0FFQ0FBa0ZBbFNQClpIZ0NHd0lDS1FrUWhhdVc1dm9iNWY3QlhTQUVHUUVDQUFZRkFsU1BaSGdBQ2drUVhMU3BOSHM3Q2R3ZW1BLysKS0ZvR3VGcVUwdUtUOXFibE40dWdSeWlsNWl0bVRSVmZmbDR0bTVPb1drVzh1RG51N1VlM3Z6ZHp5KzlOVjhYMgp3Ukc4MzVxalhpaldQKytBR3V4Z1c2TEI5blY1T1dpS01DSE9XblVqSlE2cE5RTUFnU042OVF6a0ZYVkYvcTVmCmJrbWE5VGdTYndqclZNeVB6TFNSd3E3SHNUM1YwMlFmcjRjeXEzOVFlSUxHeS9OSFc1ejZMWm5CeTNCYVZTZDAKbEdqQ0VjM3lmSDVPYUI3OW5hNFc4NldDVjVuNElUN2NvakZNK0xkTDZQNDZSZ21FdFdTRzMvQ0RqbkpsNkJMUgpXcWF0Uk5CV0xJTUtNcG4rWXZPT0w5VHd1UDF4YnFXcjF2WjY2d2tzbTUzTklEY1docHRwcDBLRXV6YlUwL0R0Ck9sdEJoY1g4dE9tTzM2THJTYWRYOXJ3Y2tTRVRDVllrbG1wQUhOeFBtbDAxMVlORFRodEJpZHZzaWN3MXZad1IKSHNYbit0eGxMNlJBSVJOK0ovUnczdU9pSkFxTjlRZ2VkcHgycStFMTV0OE1pVGcvRlh0QjlTeXNuc2tGVC9CSAp6MFVTTktKVVkwYnRaQnczZVhXelVuWmY1OUQ4VlcxTS85Snd6bkNIQXgwYzl3eS9nUkRpd3Q5dzRSb1hyeUpEClZBd1pnOHJ3QnlqbGRvaVRoVUpoa0NZdkowUjN4SDNrUG5QbEdYRFc0OUU5UjhDMnVtUkMzY1lPTDRVOWRPUTEKNWhTbFl5ZEY1dXJGR0NMSXZvZHRFOXE4MHVocHl0OEwvNWpqOXRid1pXdjZKTG5mQnF1WlNuQ0dxRlpSZlhsYgpKcGhrOStDQlFXd2laU1JMWlJ6cVE0ZmZsNHh5THVvbHgwMVBNYWF0a1FiUmF3LytKcGdSTmx1cktRMFBzVHJPCjh0enRPL3RwQkJqL2h1YzJER2tTd0VXdmtmV0VsUzVSTERLZG9NVnMvajVDTFlVSnpaVmlrVUpSbTdtN2IrT0EKUDNXMW5iRGh1SUQrWFYxQ1NCbUdpZlF3cG9QVHlzMjFzdFRJR0xnem5KcklmRTVtb0Z2aU9McUQvTHJjWWxzcQpDUWcweWxldTdTak9zLy84ZE0zbUMyRnlMYUUvZENaOGwyRENMaEh3MCt5bnlSQXZTSzZhR0NtWno2ak1qbVlGCk1YZ2l5N3pFU2tzTW5WRk11bElKSmhSM2VCMHd4MkdpdGlialkvWmhRN3REM2kweXk5SUxSMDdkRno0cGdrVk0KYWZ4cFZSN2Ztck1aMHQreUVOZCs5cXp5QVpzMGtzeE9Sb2MyemU5MFNDeDJqd0VYLzNLK200STBoUDJIL3c1VwpncWR2dVJMaXFmKzRCR1c0enFXa0xMbE5JZS9va3QwcjgyU3dIdEROMFVpMWFzbVpUR2o2c204U1h0d3grNWNFCjM4TXR0V3FqRGlpYlFPU3RoUlZjRVRCeVJZTThLY2pZU1VDaTRQb0JjM05wRE9Oa0ZiWm02WG9mUi9mNW1UY2wKMmpEdzZmSWVWYzRIZDFqQkdhak56RXF0bmVxcWJkQWtQUWFMc3VEMlRNa1FmVERKZkUvSWxqd2pyaERhOU1pKwpvZHRuTVdxOHZsd09aWjI0LzgvQk5LNXFYdUNZTDY3TzdBSkI0WlE2QlQrZzR6OTZpUkxidXB6dS9YSnlYa1FGCnJPWS9HaGVndm43ZkRybnQyS0M5TXBnZUZCWHpVcCtrNXJ6VWRGOGpiQ3g1YXBWakExc1dYQjlLaDNMK0RVd0YKTXZlNjk2QjV0bEh5YzFLeGpIUjZ3OUdSc2g0PQo9cE0xZwotLS0tLUVORCBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0t"
      }
    }
  }
}

We don't know what this data was though, the rust project would need to keep a public archive of all data they've signed to allow auditing. If I recall correctly this would be an archive of all release-stable.toml, these then contain a sha256sum of the other artifacts, so if you have a complete view of all release-stable.toml you also have a complete view of all compilers that have been distributed.


Anyway regarding the original issue and since I looked into the keys anyway, this is the output of sq-keyring-linter:

% sq-keyring-linter --fix rust-key.pgp.ascii
Certificate 85AB96E6FA1BE5FE is not valid under the standard policy: No binding signature at time 2023-02-15T17:23:07Z
Certificate 85AB96E6FA1BE5FE contains a User ID ("Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>") protected by SHA-1
Certificate 85AB96E6FA1BE5FE: User ID Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>: Failed to update binding signature: Invalid argument: No secret key
Certificate 85AB96E6FA1BE5FE, key 5CB4A9347B3B09DC uses a SHA-1-protected binding signature.
Certificate 85AB96E6FA1BE5FE, key 5CB4A9347B3B09DC: Failed to update binding signature: Invalid argument: No secret key
Certificate 85AB96E6FA1BE5FE, key 8E9AA3F7AB3F5826 uses a SHA-1-protected binding signature.
Certificate 85AB96E6FA1BE5FE, key 8E9AA3F7AB3F5826: Failed to update binding signature: Invalid argument: No secret key
Examined 1 certificate.
  0 certificates are invalid and were not linted. (GOOD)
  1 certificate was linted.
  1 of the 1 certificates (100%) has at least one issue. (BAD)
0 of the linted certificates were revoked.
  0 of the 0 certificates has revocation certificates that are weaker than the certificate and should be recreated. (GOOD)
0 of the linted certificates were expired.
1 of the non-revoked linted certificate has at least one non-revoked User ID:
  1 has at least one User ID protected by SHA-1. (BAD)
  1 has all User IDs protected by SHA-1. (BAD)
1 of the non-revoked linted certificates has at least one non-revoked, live subkey:
  1 has at least one non-revoked, live subkey with a binding signature that uses SHA-1. (BAD)
0 of the non-revoked linted certificates have at least one non-revoked, live, signing-capable subkey:
  0 certificates have at least one non-revoked, live, signing-capable subkey with a strong binding signature, but a backsig that uses SHA-1. (GOOD)
Failed to fix 3 issues. (BAD)

Basically the primary key 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE self-certifies the uid Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org> and both subkeys belong to 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE but it does so with sha1:

% sq packet dump rust-key.pgp.ascii
Public-Key Packet, old CTB, 525 bytes
    Version: 4
    Creation time: 2013-09-26 23:18:33 UTC
    Pk algo: RSA
    Pk size: 4096 bits
    Fingerprint: 108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE
    KeyID: 85AB96E6FA1BE5FE
  
User ID Packet, old CTB, 68 bytes
    Value: Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
  
Signature Packet, old CTB, 568 bytes
    Version: 4
    Type: PositiveCertification
    Pk algo: RSA
    Hash algo: SHA1
    Hashed area:
      Signature creation time: 2013-09-26 23:18:33 UTC
      Key flags: CS
      Symmetric algo preferences: AES256, AES192, AES128, CAST5, TripleDES
      Hash preferences: SHA256, SHA1, SHA384, SHA512, SHA224
      Compression preferences: Zlib, BZip2, Zip
      Features: MDC
      Keyserver preferences: no modify
    Unhashed area:
      Issuer: 85AB96E6FA1BE5FE
    Digest prefix: 5F61
    Level: 0 (signature over data)
  
Public-Subkey Packet, old CTB, 525 bytes
    Version: 4
    Creation time: 2013-09-26 23:18:33 UTC
    Pk algo: RSA
    Pk size: 4096 bits
    Fingerprint: 29D57CE15D76E78CD57D326A8E9AA3F7AB3F5826
    KeyID: 8E9AA3F7AB3F5826
  
Signature Packet, old CTB, 543 bytes
    Version: 4
    Type: SubkeyBinding
    Pk algo: RSA
    Hash algo: SHA1
    Hashed area:
      Signature creation time: 2013-09-26 23:18:33 UTC
      Key flags: EtEr
    Unhashed area:
      Issuer: 85AB96E6FA1BE5FE
    Digest prefix: DF14
    Level: 0 (signature over data)
  
Public-Subkey Packet, old CTB, 525 bytes
    Version: 4
    Creation time: 2014-12-15 22:45:12 UTC
    Pk algo: RSA
    Pk size: 4096 bits
    Fingerprint: C13466B7E169A085188632165CB4A9347B3B09DC
    KeyID: 5CB4A9347B3B09DC
  
Signature Packet, old CTB, 1086 bytes
    Version: 4
    Type: SubkeyBinding
    Pk algo: RSA
    Hash algo: SHA1
    Hashed area:
      Signature creation time: 2014-12-15 22:45:12 UTC
      Key flags: S
    Unhashed area:
      Issuer: 85AB96E6FA1BE5FE
      Embedded signature: 
        Signature Packet
          Version: 4
          Type: PrimaryKeyBinding
          Pk algo: RSA
          Hash algo: SHA1
          Hashed area:
            Signature creation time: 2014-12-15 22:45:12 UTC
          Unhashed area:
            Issuer: 5CB4A9347B3B09DC
          Digest prefix: 1E98
          Level: 0 (signature over data)
        
    Digest prefix: D16B
    Level: 0 (signature over data)

To fix this with sequoia, use:

$ apt-get install sq-keyring-linter
$ gpg --export-secret-keys rust-key@rust-lang.org | sq-keyring-linter --fix | gpg --import

gpg is going to ask for as password to protect the secret key, but sq-keyring-linter is going to immediately ask for the password again to issue new sha2 signatures for the uid paket and both subkeys, so it doesn't really matter what you set there.

I've tried to find instructions on how to fix the key with gpg natively but it seems very involved (https://old.nixaid.com/gpg-migration-sha1-to-sha2/). It also doesn't explain how to get rid of the subkey signatures and suggests to revoke them and generate new ones (?!).

Cross-referecing the release scripts, this should work:

(
for x in  "op://tnuk54f56audltg5e7if776ieq/67bxwduvibdkpio7psx53preka/56b6j26lmvelpn6jeecsr5fsxi" "op://tnuk54f56audltg5e7if776ieq/q6ztr2lrorg3fa3mzg6kx26bnm/m6tnrye775cefbekajhawec3ja" "op://tnuk54f56audltg5e7if776ieq/fnzoe3nw7rck7ezqhwpkj7j2xe/kjzmpsermnc4bovkwslhjd34se"; do
op read "$x"
done
) | sq-keyring-linter --fix -p "$(op read op://tnuk54f56audltg5e7if776ieq/pks4bn2wf4r7plue24cdqsw4ga/password)" | gpg --import

# in rustup codebase

gpg --armor --export rust-key@rust-lang.org > src/rust-key.pgp.ascii

If you just want to go with a new key and you want to go with gpg again, put this in your ~/.gnupg/gpg.conf first:

personal-cipher-preferences AES256
personal-digest-preferences SHA512
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

Sorry this reply got so long, if anything is unclear please just let me know.

@rbtcollins
Copy link
Contributor

I had assumed we'd update the embedde certificate in rustup via new rustup release rather than sideloading keys. We need to do that in some form of expand-contract so that rustup's self-update continues to work across the transition.

@kpcyrd
Copy link

kpcyrd commented Feb 15, 2023

I reverse engineered the rustup self-update recently and the pgp signatures aren't fully in use yet.

rustup fetches this url: https://static.rust-lang.org/rustup/release-stable.toml

schema-version = '1'
version = '1.25.2'

If this version is less recent than rustup's own version (say 1.25.1) it's going to fetch and execute the elf file from this url next: https://static.rust-lang.org/rustup/archive/1.25.2/x86_64-unknown-linux-musl/rustup-init.

Security is provided by https and pgp signatures aren't mandatory yet, so rolling out the update shouldn't cause issues.

I have unit-tests for rustup here: https://github.com/kpcyrd/sh4d0wup/blob/main/contrib/plot-rustup.yaml

@pietroalbini
Copy link
Member

Let's not bikeshed a key rotation mechanism in this thread, but let's focus on removing the SHA1 signatures from the existing key. Key rotation (and in general enforcing signatures) would require a larger design effort, and I know it's one of the priorities of the foundation security engineer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants