signedshot 0.1.3__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1331,7 +1331,7 @@ dependencies = [
1331
1331
 
1332
1332
  [[package]]
1333
1333
  name = "signedshot-validator"
1334
- version = "0.1.3"
1334
+ version = "0.1.4"
1335
1335
  dependencies = [
1336
1336
  "anyhow",
1337
1337
  "base64",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "signedshot-validator"
3
- version = "0.1.3"
3
+ version = "0.1.4"
4
4
  edition = "2021"
5
5
  description = "Validator for SignedShot media authenticity proofs"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signedshot
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "signedshot"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "Validator for SignedShot media authenticity proofs"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -151,6 +151,9 @@ fn validate_command(sidecar_path: &Path, media_path: &Path, json_output: bool) -
151
151
  println!(" Publisher ID: {}", result.capture_trust.publisher_id);
152
152
  println!(" Device ID: {}", result.capture_trust.device_id);
153
153
  println!(" Method: {}", result.capture_trust.method);
154
+ if let Some(ref app_id) = result.capture_trust.app_id {
155
+ println!(" App ID: {}", app_id);
156
+ }
154
157
  println!(" Issued At: {}", result.capture_trust.issued_at);
155
158
  println!(" Key ID: {}", kid);
156
159
 
@@ -27,6 +27,16 @@ pub struct JwtHeader {
27
27
  pub kid: Option<String>,
28
28
  }
29
29
 
30
+ /// Attestation information from the JWT
31
+ #[derive(Debug, Clone, Serialize, Deserialize)]
32
+ pub struct Attestation {
33
+ /// Attestation method (sandbox, app_check, app_attest)
34
+ pub method: String,
35
+ /// App ID from attestation (e.g., bundle ID), if available
36
+ #[serde(skip_serializing_if = "Option::is_none")]
37
+ pub app_id: Option<String>,
38
+ }
39
+
30
40
  #[derive(Debug, Clone, Serialize, Deserialize)]
31
41
  pub struct CaptureTrustClaims {
32
42
  pub iss: String,
@@ -36,7 +46,7 @@ pub struct CaptureTrustClaims {
36
46
  pub capture_id: String,
37
47
  pub publisher_id: String,
38
48
  pub device_id: String,
39
- pub method: String,
49
+ pub attestation: Attestation,
40
50
  }
41
51
 
42
52
  #[derive(Debug, Clone)]
@@ -97,10 +107,10 @@ fn validate_claims(claims: &CaptureTrustClaims) -> Result<()> {
97
107
  }
98
108
 
99
109
  let valid_methods = ["sandbox", "app_check", "app_attest"];
100
- if !valid_methods.contains(&claims.method.as_str()) {
110
+ if !valid_methods.contains(&claims.attestation.method.as_str()) {
101
111
  return Err(ValidationError::InvalidJwt(format!(
102
- "Invalid method '{}', expected one of: {:?}",
103
- claims.method, valid_methods
112
+ "Invalid attestation method '{}', expected one of: {:?}",
113
+ claims.attestation.method, valid_methods
104
114
  )));
105
115
  }
106
116
 
@@ -179,19 +189,34 @@ mod tests {
179
189
  #[test]
180
190
  fn parse_valid_jwt() {
181
191
  let header = r#"{"alg":"ES256","typ":"JWT","kid":"test-key"}"#;
182
- let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","method":"sandbox"}"#;
192
+ let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","attestation":{"method":"sandbox"}}"#;
183
193
  let token = make_jwt(header, payload);
184
194
 
185
195
  let parsed = parse_jwt(&token).unwrap();
186
196
  assert_eq!(parsed.header.alg, "ES256");
187
197
  assert_eq!(parsed.claims.capture_id, "123");
188
- assert_eq!(parsed.claims.method, "sandbox");
198
+ assert_eq!(parsed.claims.attestation.method, "sandbox");
199
+ assert_eq!(parsed.claims.attestation.app_id, None);
200
+ }
201
+
202
+ #[test]
203
+ fn parse_jwt_with_app_id() {
204
+ let header = r#"{"alg":"ES256","typ":"JWT","kid":"test-key"}"#;
205
+ let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","attestation":{"method":"app_check","app_id":"io.foo.bar"}}"#;
206
+ let token = make_jwt(header, payload);
207
+
208
+ let parsed = parse_jwt(&token).unwrap();
209
+ assert_eq!(parsed.claims.attestation.method, "app_check");
210
+ assert_eq!(
211
+ parsed.claims.attestation.app_id,
212
+ Some("io.foo.bar".to_string())
213
+ );
189
214
  }
190
215
 
191
216
  #[test]
192
217
  fn reject_invalid_algorithm() {
193
218
  let header = r#"{"alg":"HS256","typ":"JWT"}"#;
194
- let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","method":"sandbox"}"#;
219
+ let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","attestation":{"method":"sandbox"}}"#;
195
220
  let token = make_jwt(header, payload);
196
221
 
197
222
  let result = parse_jwt(&token);
@@ -201,7 +226,7 @@ mod tests {
201
226
  #[test]
202
227
  fn reject_invalid_audience() {
203
228
  let header = r#"{"alg":"ES256","typ":"JWT"}"#;
204
- let payload = r#"{"iss":"https://example.com","aud":"wrong","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","method":"sandbox"}"#;
229
+ let payload = r#"{"iss":"https://example.com","aud":"wrong","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","attestation":{"method":"sandbox"}}"#;
205
230
  let token = make_jwt(header, payload);
206
231
 
207
232
  let result = parse_jwt(&token);
@@ -211,7 +236,7 @@ mod tests {
211
236
  #[test]
212
237
  fn reject_invalid_method() {
213
238
  let header = r#"{"alg":"ES256","typ":"JWT"}"#;
214
- let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","method":"invalid"}"#;
239
+ let payload = r#"{"iss":"https://dev-api.signedshot.io","aud":"signedshot","sub":"capture-service","iat":1705312200,"capture_id":"123","publisher_id":"456","device_id":"789","attestation":{"method":"invalid"}}"#;
215
240
  let token = make_jwt(header, payload);
216
241
 
217
242
  let result = parse_jwt(&token);
@@ -35,6 +35,7 @@ impl PyValidationResult {
35
35
  dict.set_item("device_id", &self.inner.capture_trust.device_id)?;
36
36
  dict.set_item("capture_id", &self.inner.capture_trust.capture_id)?;
37
37
  dict.set_item("method", &self.inner.capture_trust.method)?;
38
+ dict.set_item("app_id", &self.inner.capture_trust.app_id)?;
38
39
  dict.set_item("issued_at", self.inner.capture_trust.issued_at)?;
39
40
  dict.set_item("key_id", &self.inner.capture_trust.key_id)?;
40
41
  Ok(dict)
@@ -29,6 +29,8 @@ pub struct CaptureTrustResult {
29
29
  pub capture_id: String,
30
30
  /// Attestation method (sandbox, app_check, app_attest)
31
31
  pub method: String,
32
+ /// App ID from attestation (e.g., bundle ID), if available
33
+ pub app_id: Option<String>,
32
34
  /// Unix timestamp when the JWT was issued
33
35
  pub issued_at: i64,
34
36
  /// Key ID used to sign the JWT
@@ -47,7 +49,8 @@ impl CaptureTrustResult {
47
49
  publisher_id: claims.publisher_id.clone(),
48
50
  device_id: claims.device_id.clone(),
49
51
  capture_id: claims.capture_id.clone(),
50
- method: claims.method.clone(),
52
+ method: claims.attestation.method.clone(),
53
+ app_id: claims.attestation.app_id.clone(),
51
54
  issued_at: claims.iat,
52
55
  key_id,
53
56
  }
@@ -257,6 +260,7 @@ mod tests {
257
260
  device_id: "dev-456".to_string(),
258
261
  capture_id: "cap-789".to_string(),
259
262
  method: "sandbox".to_string(),
263
+ app_id: None,
260
264
  issued_at: 1705312200,
261
265
  key_id: Some("key-1".to_string()),
262
266
  },
@@ -289,6 +293,7 @@ mod tests {
289
293
  device_id: "dev-456".to_string(),
290
294
  capture_id: "cap-789".to_string(),
291
295
  method: "sandbox".to_string(),
296
+ app_id: None,
292
297
  issued_at: 1705312200,
293
298
  key_id: None,
294
299
  },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes