Skip to content

Commit a3dcd01

Browse files
committed
introduce new artifact api
1 parent 1d37aa6 commit a3dcd01

File tree

13 files changed

+565
-261
lines changed

13 files changed

+565
-261
lines changed

crates/sigstore-conformance/src/main.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use sigstore_oidc::IdentityToken;
1212
use sigstore_rekor::RekorClient;
1313
use sigstore_trust_root::TrustedRoot;
1414
use sigstore_tsa::TimestampClient;
15-
use sigstore_types::{Bundle, SignatureContent};
15+
use sigstore_types::{Bundle, Sha256Hash, SignatureContent};
1616
use sigstore_verify::{verify, VerificationPolicy};
1717

1818
use std::env;
@@ -382,12 +382,12 @@ fn verify_bundle(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
382382
.into());
383383
}
384384

385-
// Create a policy that skips artifact hash validation since we already checked it
386-
let digest_policy = policy.skip_artifact_hash();
387-
let dummy_artifact = vec![];
385+
// Convert digest bytes to Sha256Hash for verification
386+
let artifact_digest = Sha256Hash::try_from_slice(&digest_bytes)
387+
.map_err(|e| format!("Invalid digest: {}", e))?;
388388

389-
// Verify the signature with trusted root
390-
let result = verify(&dummy_artifact, &bundle, &digest_policy, &trusted_root)?;
389+
// Verify the signature with trusted root using the digest directly
390+
let result = verify(artifact_digest, &bundle, &policy, &trusted_root)?;
391391

392392
if !result.success {
393393
return Err("Verification failed".into());

crates/sigstore-crypto/src/hash.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use aws_lc_rs::digest::{self, Context, SHA256};
44
use sigstore_types::Sha256Hash;
5+
use std::io::{self, Read};
56

67
/// Hash data using SHA-256, returning a typed hash
78
pub fn sha256(data: &[u8]) -> Sha256Hash {
@@ -44,6 +45,31 @@ impl Default for Sha256Hasher {
4445
}
4546
}
4647

48+
/// Compute SHA-256 hash by reading from a reader (streaming, constant memory)
49+
///
50+
/// This is useful for hashing large files without loading them entirely into memory.
51+
///
52+
/// # Example
53+
/// ```no_run
54+
/// use std::fs::File;
55+
/// use sigstore_crypto::sha256_reader;
56+
///
57+
/// let file = File::open("large-file.tar.gz").unwrap();
58+
/// let hash = sha256_reader(file).unwrap();
59+
/// ```
60+
pub fn sha256_reader(mut reader: impl Read) -> io::Result<Sha256Hash> {
61+
let mut hasher = Sha256Hasher::new();
62+
let mut buf = [0u8; 8192];
63+
loop {
64+
let n = reader.read(&mut buf)?;
65+
if n == 0 {
66+
break;
67+
}
68+
hasher.update(&buf[..n]);
69+
}
70+
Ok(hasher.finalize())
71+
}
72+
4773
#[cfg(test)]
4874
mod tests {
4975
use super::*;
@@ -70,4 +96,16 @@ mod tests {
7096
let direct = sha256(b"hello");
7197
assert_eq!(hash, direct);
7298
}
99+
100+
#[test]
101+
fn test_sha256_reader() {
102+
use std::io::Cursor;
103+
104+
let data = b"hello world, this is a test of streaming hash";
105+
let cursor = Cursor::new(data);
106+
let hash = sha256_reader(cursor).unwrap();
107+
108+
let direct = sha256(data);
109+
assert_eq!(hash, direct);
110+
}
73111
}

crates/sigstore-crypto/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub use checkpoint::{
1616
verify_signature_auto, Checkpoint, CheckpointSignature, CheckpointVerifyExt, KeyType,
1717
};
1818
pub use error::{Error, Result};
19-
pub use hash::{sha256, Sha256Hasher};
19+
pub use hash::{sha256, sha256_reader, Sha256Hasher};
2020
pub use keyring::Keyring;
2121
pub use signing::{KeyPair, SigningScheme};
2222
pub use verification::{verify_signature, verify_signature_prehashed, VerificationKey};

crates/sigstore-sign/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ sigstore-tsa = { workspace = true }
1818
thiserror = { workspace = true }
1919
base64 = { workspace = true }
2020
x509-cert = { workspace = true }
21+
serde_json = { workspace = true }
2122

2223
[dev-dependencies]
2324
tokio = { workspace = true }
2425
chrono = { workspace = true }
2526
serde = { workspace = true }
26-
serde_json = { workspace = true }
2727
hex = { workspace = true }
2828

2929
[features]

crates/sigstore-sign/README.md

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,48 @@ This crate provides high-level APIs for creating Sigstore signatures. It orchest
2727
## Usage
2828

2929
```rust
30-
use sigstore_sign::{Signer, SigningConfig};
30+
use sigstore_sign::{SigningContext, Attestation, AttestationSubject};
31+
use sigstore_oidc::IdentityToken;
32+
use sigstore_types::Sha256Hash;
3133

32-
let config = SigningConfig::production();
33-
let signer = Signer::new(config).await?;
34+
// Create a signing context for production
35+
let context = SigningContext::production();
3436

35-
// Sign a blob
36-
let bundle = signer.sign(artifact_bytes).await?;
37+
// Get an identity token (from OIDC provider)
38+
let token = IdentityToken::new("your-identity-token".to_string());
3739

38-
// Sign with a DSSE envelope
39-
let bundle = signer.sign_dsse(payload_type, payload).await?;
40+
// Create a signer
41+
let signer = context.signer(token);
42+
43+
// Sign artifact bytes
44+
let artifact = b"hello world";
45+
let bundle = signer.sign(artifact).await?;
46+
47+
// Or sign with a pre-computed digest (for large files)
48+
let digest = Sha256Hash::from_hex("b94d27b9...")?;
49+
let bundle = signer.sign(digest).await?;
50+
51+
// Sign an in-toto attestation (DSSE envelope)
52+
let subject = AttestationSubject::new("artifact.tar.gz", digest);
53+
let attestation = Attestation::new("https://slsa.dev/provenance/v1")
54+
.with_subject(subject)
55+
.with_predicate(serde_json::json!({"key": "value"}));
56+
let bundle = signer.sign_attestation(attestation).await?;
57+
58+
// Write bundle to file
59+
std::fs::write("artifact.sigstore.json", bundle.to_json_pretty()?)?;
4060
```
4161

4262
## Configuration
4363

4464
```rust
45-
use sigstore_sign::SigningConfig;
65+
use sigstore_sign::SigningContext;
4666

47-
// Production (default)
48-
let config = SigningConfig::production();
67+
// Production environment
68+
let context = SigningContext::production();
4969

5070
// Staging environment
51-
let config = SigningConfig::staging();
52-
53-
// Custom configuration
54-
let config = SigningConfig {
55-
fulcio_url: "https://fulcio.example.com".into(),
56-
rekor_url: "https://rekor.example.com".into(),
57-
// ...
58-
};
71+
let context = SigningContext::staging();
5972
```
6073

6174
## Related Crates

crates/sigstore-sign/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ pub use sigstore_tsa as tsa;
3535
pub use sigstore_types as types;
3636

3737
pub use error::{Error, Result};
38-
pub use sign::{sign_context, Signer, SigningConfig, SigningContext};
38+
pub use sign::{
39+
sign_context, Attestation, AttestationSubject, Signer, SigningConfig, SigningContext,
40+
};

0 commit comments

Comments
 (0)