# 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](https://github.com/mtrojnar/osslsigncode), which doesn't provide a library, so please ping me if things start breaking, and I'll update!
```rust
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
```rust
# 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
```rust
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
```toml
[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](./LICENSE) and
[`vendor/osslsigncode/LICENSE.txt`](vendor/osslsigncode/LICENSE.txt).
The compiled submodule revision is exported as `VENDOR_COMMIT`.