-
Notifications
You must be signed in to change notification settings - Fork 892
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
rustup-init.exe needs to be code-signed #1568
Comments
I agree, all official releases should be signed, ideally with keys which have a good chain of trust. |
We discussed this in an infra team meeting. In summary:
(other open questions involve things like: What about OSX signing? Does the approach we choose for rustup generalise to other binaries we distribute?) |
@aidanhs I have no experience with signing of Windows binaries (I have with signing packages and repositories for Debian based Linux distros), but I expect the approach to take on one binary to work on the all others on that same platform. Typically the platform specific docs should provide exact details, and automation should be possible for all, but the exact details will probably be different. BTW, if individual binary/file signing is not possible, the second best thing is to sign the packaging format and files with checksums for each file. This is a good idea no matter what to make sure tool chains are not corrupted, infected or modified and some commands could allow verification. |
@jseyfried can you share Windows binary signing best practices? |
I have some slight idea on how it works. You get a code signing cert and you would invoke signtool.exe from the Windows SDK somewhere in the build/packaging process to sign the output executables (.exe/.dll). Some interest points I can think of:
If all you care is for the initial SmartScreen warning on To have Note: When most (if not all) browsers on Windows download a file, they add an NTFS alternate data stream |
Regarding secure storage of the keys, I think a Yubikey device or something similar can do this. For instance, at EuroBSD 2018 the gift package contained a microcontroller based key storage device. The device was sponsored by Modirum and is using the Gnuk OpenPGP firmware from the Free Software Initiative of Japan and it looks like a USB stick. |
An update on the secure key storage, on the Gnuk project page there is a list of compatible devices, and one of them, Nitrokey Start, looks quite cheap (29€) and looks nice, comes pre-installed with all needed SW, and it seems the company has very big names as clients: Google, BBC, SuSE, Redhat, Mozilla, Nvidia, ABB, Adobe... (link to pdf). |
How would a USB dongle be connected to the CI infrastructure? It seems to me a cloud-based HSMaaS solution such as SDKMS would be more convenient. We can provide a free account for the Rust project, someone from the infra team please contact me to set this up. |
Be careful about types of hardware keys and their software. I've got one that on every signing pops up a GUI that asks for a PIN. There's no CLI version. It doesn't work over SSH and gets in the way of build automation. |
signtool.exe is a PITA; I know, I've tried it.
The easy way to do it is osslsigncode, which can run under any platform that can run basic C code and OpenSSL. |
Isn't this simply a matter of trying to access the machine keystore when you should be using the user keystore? |
I'm running Symantec (on Win7), and it too prevents me from running the downloaded exe, because it's unsigned. The file is even deleted from the Downloads folder... I assume Firefox is signed, so I don't see why RustUp can't be... Notwithstanding the above, how's one supposed to get Rust up-and-running on Windows given this??? Not caring about Windows users for Rust? Note that this is on a corporate computer, which means I can't control or disable Symantec. UPDATE: Temporarily disabled Symantec with help from admin, so could run downloaded installer. BUT Symantec re-enables itself shortly after, and intercepts attempts to run the installed cargo, rustc, etc... executables (also unsigned obviously, although if coming from signed installer might be OK), deleting them from disk (like the -init.exe installer). I conclude that RUST as a language is not ready to be used by professional developers working on Windows in Corporate environments with mandatory AV software, despite it being mature (4 years since 1.0 release). I guess I'll have to stick to C++ :). Note that by contrast, I had zero-issues using GoLang in that same environment. |
We do care we care greatly. Sadly while we have someone volunteering to help us with sorting out code-signing, it is a complex logistical problem because there's not (yet) a mechanism in place for the project to hold a legal entity to be identified by the certificates. Many people manage to use Rust on Windows, even people with Symantec, Avast, McAffee, and other AVs, so it must be possible. Sadly I'm not the right person to tell you how to do it :( |
I think this ticket needs to get escalated out of just our team and into a broader cross-team space - basically the artifacts in the channels are the problem, of which rustup.exe is a special case. |
Ideally cargo itself would allow easy code signing, which implies support for signing in the tools it forks. |
@ddevienne the technical part of doing the signing is not the issue. As @kinnison mentioned, the big hurdle now is obtaining a trusted (by MS) code signing certificate. |
I have an update. The following has been the status since early April, but unfortunately none of this was communicated to us until today 😕 Mozilla has basically agreed to let us use their code-signing certificate & infrastructure. 🎉 There's a KMS that Mozilla runs called autograph that's used for signing. They don't want to give Rust CI direct access to this service, so a little proxy utility is needed on Mozilla's taskcluster. When CI needs something signed, it will ping that proxy service with a link to the binary, then the utility will contact autograph to get it signed. Autograph doesn't have native support for PE signing, but we can use the Generic RSA signing API to get regular PKCS#1 v1.5 signing. The following is needed to complete the flow:
I don't have time to actively work on this, but happy to help mentor someone on this issue (Windows dev environment not required). This shows how to interact with autograph over the network to get an RSA SHA1 PKCS#1 v1.5 signature. It needs to be modified to use the Generic RSA signing API. /* Cargo dependencies:
hawk = { version = "3", default-features = false, features = ["use_openssl"] }
hyper = "0.10"
serde = { version = "1", features = ["derive"] }
serde_repr = "0.1"
serde_json = "1"
*/
use serde::{Serialize, Deserialize};
use serde_repr::Serialize_repr;
use hawk::{RequestBuilder, Credentials, Key, SHA256, PayloadHasher};
use hyper::{Client, status::StatusCode, Url, header::{Authorization, ContentType}};
#[derive(Serialize)]
// from https://github.com/mozilla-services/autograph/tree/master/signer/mar#signature-request
struct SignInput<'a> {
input: &'a str,
keyid: &'a str,
options: SignOptions,
}
#[derive(Serialize)]
struct SignOptions {
sigalg: MarSigAlg
}
#[derive(Serialize_repr)]
#[repr(u8)]
// from https://godoc.org/go.mozilla.org/mar#pkg-constants
enum MarSigAlg {
RsaPkcs1Sha1 = 1,
RsaPkcs1Sha384 = 2,
EcdsaP256Sha256 = 3,
EcdsaP384Sha384 = 4,
}
#[derive(Deserialize)]
struct SignOutput {
signature: String,
}
fn sign(url: &str, keyid: &str, input: &str, userid: &str, userkey: &str) -> String {
let body = serde_json::to_vec(&[SignInput {
input, keyid, options: SignOptions { sigalg: MarSigAlg::RsaPkcs1Sha1 }
}]).unwrap();
let url = Url::parse(url).unwrap().join("sign/hash").unwrap();
let credentials = Credentials {
id: userid.to_string(),
key: Key::new(userkey, SHA256).unwrap(),
};
let payload_hash = PayloadHasher::hash("application/json", SHA256, &body).unwrap();
let request = RequestBuilder::new("POST", url.host_str().unwrap(), url.port().unwrap(), url.path())
.hash(&payload_hash[..])
.request();
let hawk_header = request.make_header(&credentials).unwrap();
let client = Client::new();
let res = client.post(url)
.body(&body[..])
.header(ContentType::json())
.header(Authorization(format!("Hawk {}", hawk_header)))
.send()
.unwrap();
assert_eq!(res.status, StatusCode::Created);
let res: Vec<SignOutput> = serde_json::from_reader(res).unwrap();
res.into_iter().next().unwrap().signature
}
fn main() {
let input_sha1hash = "3JBQjLq8/8b9ezhFDLTjya/rt74=";
// default key & credentials from autograph dev docker container
println!("{}", sign("http://172.17.0.2:8000", "testmar", input_sha1hash, "alice", "fs5wgcer9qj819kfptdlp8gm227ewxnzvsuj9ztycsx08hfhzu"));
} |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I'm new to rust and I'm downloading rustup-init.exe for the first time. While we wait for this issue to get fixed, I would recommend please at least publish a SHA256 or SHA512 hash of the file on the website that we can verify. |
@rtrusso Next to each binary of |
@kinnison can you please show us URL for the .sha256 checksum file of rustup-init.exe? |
Sure, the URLs are of the form:
Where For the current release, for https://static.rust-lang.org/rustup/archive/1.19.0/x86_64-pc-windows-msvc/rustup-init.exe And the corresponding checksum is https://static.rust-lang.org/rustup/archive/1.19.0/x86_64-pc-windows-msvc/rustup-init.exe.sha256 |
Autograph now has direct support for PKCS v1.5 signing, I updated my status comment above accordingly. |
Similar to rust-lang/rust#67472, Cynet is also flagging this as malware: |
@rustbot label: +O-windows |
Another option is to use Azure Key Vault for the signing, that might overall be the easiest solution, I think. One can then use https://github.com/vcsjones/AzureSignTool to integrate all of that into a CI workflow. I think roughly the steps would be:
|
We are still willing to sponsor free signing key storage in Fortanix DSM. |
We're still waiting for the foundation to reach a point that infra can deal with setting up key storage etc. @jethrogb 's offer is definitely in their notes for when we're ready. |
Sounds like this is gonna get more noticeable in future Win11 updates thanks to Smart App Control which requires some code signature on the binary. |
This comment was marked as abuse.
This comment was marked as abuse.
FWIW Microsoft already white-list rustup.exe in their behavioural list shortly after each release. Being signed is probably better, but most developers should not be experiencing warning dialogues at this point. |
@rbtcollins That's for Windows. What about macOS? Code signing files ensure the file came from publisher and hasn't been modified thereafter. We can verify the integrity of files too. It's really necessary from a security POV. Not all OSs are about Windows only!! |
Fundamentally someone needs to work with rust's infra team to perform signing of release builds, and if code changes are needed to work well with that, to make those changes too. |
This thread is a few years old, I hope someone really takes it seriously and implements it in the CI. |
NOTE: Edited by @kinnison
Mozilla are prepared to offer access to their Autograph signing service. Thus if you want to help, the relevant useful comment is #1568 (comment) which will guide you through what needs to be done. @jethrogb has indicated they are prepared to mentor this process.
Original posting comes below...
rustup-init.exe
(downloaded from https://win.rustup.rs/) is not signed with an EV code signing certificate. As a result, there isn't an obvious way for Windows users to verify the download. (Neither https://www.rust-lang.org/tools/install nor https://rustup.rs/ shows any gpg keys or even checksums for use.)Moreover, the
rustup-init.exe
can get blocked by SmartScreen. Even though users can bypass it by clicking on "More Info" then "Run anyway", it doesn't bring any confidence.SmartScreen operates on the basis of reputation. The SmartScreen warning might eventually go away when the
rustup-init.exe
gets used by more users, but it resets whenever a new version is built and published. Ifrustup-init.exe
is code-signed, the reputation will be inherited by any programs signed with the same certificate, which should make SmartScreen happy. (See: https://blogs.msdn.microsoft.com/ie/2012/08/14/microsoft-smartscreen-extended-validation-ev-code-signing-certificates/)The text was updated successfully, but these errors were encountered: