osslsigncode 0.1.1

In-process Rust bindings for the vendored osslsigncode Authenticode implementation
docs.rs failed to build osslsigncode-0.1.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

osslsigncode

This is a safe (hopefully), Rust API for Authenticode.

Sign, verify, inspect, and strip signatures on PE/CAB/MSI/APPX and script files.

Bindings against osslsigncode, which doesn't provide a library, so please ping me if things start breaking, and I'll update!

use osslsigncode::{Credential, Digest, Secret, TrustAnchors, Unsigned};
use std::path::Path;

let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let dir = tempfile::tempdir().unwrap();
let input = root.join("vendor/osslsigncode/tests/files/unsigned.js");
let credential = Credential::pkcs12(root.join("tests/fixtures/publisher.p12"), Secret::value("secret"));

let signed = Unsigned::open(&input)?
    .sign(credential)
    .digest(Digest::Sha256)
    .output(dir.path().join("app-signed.js"))
    .sign()?;

signed
    .verify()
    .trust(TrustAnchors {
        ca_file: Some(root.join("tests/fixtures/ca.pem")),
        ..Default::default()
    })
    .ignore_timestamp()
    .check()?;
# Ok::<(), osslsigncode::Error>(())

Extracting and inspecting

# use osslsigncode::{Credential, Digest, Secret, Unsigned};
# use std::path::Path;
# let root = Path::new(env!("CARGO_MANIFEST_DIR"));
# let dir = tempfile::tempdir().unwrap();
# let input = root.join("vendor/osslsigncode/tests/files/unsigned.js");
# let credential = Credential::pkcs12(root.join("tests/fixtures/publisher.p12"), Secret::value("secret"));
# let signed = Unsigned::open(&input)?.sign(credential).digest(Digest::Sha256).output(dir.path().join("signed.js")).sign()?;
use std::io::Read;

let mut sig = Vec::new();
signed.extract_signature().pem().reader()?.read_to_end(&mut sig).unwrap();
assert!(sig.starts_with(b"-----BEGIN"));

// Inspect the embedded signature without asserting trust.
let info = signed.inspect()?;
assert_eq!(info.digest, Some(Digest::Sha256));
assert!(info.signers[0].subject.contains("CN="));

let unsigned = signed.strip().output(dir.path().join("stripped.js")).strip()?;
assert_eq!(std::fs::read(unsigned.path()).unwrap(), std::fs::read(&input).unwrap());
# Ok::<(), osslsigncode::Error>(())

Builder completeness

use osslsigncode::{Credential, Digest, Secret, Timestamp, Unsigned};
use std::path::Path;

let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let input = root.join("vendor/osslsigncode/tests/files/unsigned.js");
let credential = Credential::pkcs12(root.join("tests/fixtures/publisher.p12"), Secret::value("secret"));

let _ready = Unsigned::open(&input)
    .unwrap()
    .sign(credential)
    .digest(Digest::Sha256)
    .timestamp(Timestamp::rfc3161("http://timestamp.example"))
    .output("builder-only.js");
// `_ready.sign()` would run the job; omitting it still type-checks `Ready`.

Using from another crate

[dependencies]
osslsigncode = "0.2.0"

Clone with submodules. You need a C compiler, libclang (bindgen), and Perl when the vendored OpenSSL feature is enabled.

License

The vendored upstream implementation is licensed under the GNU General Public License, version 3 or later, with an OpenSSL linking exception. See LICENSE and vendor/osslsigncode/LICENSE.txt. The compiled submodule revision is exported as VENDOR_COMMIT.