• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 //! Example program demonstrating signed CWT processing.
18 use coset::{cbor::value::Value, cwt, iana, CborSerializable, CoseError};
19 
20 #[derive(Copy, Clone)]
21 struct FakeSigner {}
22 
23 // Use a fake signer/verifier (to avoid pulling in lots of dependencies).
24 impl FakeSigner {
sign(&self, data: &[u8]) -> Vec<u8>25     fn sign(&self, data: &[u8]) -> Vec<u8> {
26         data.to_vec()
27     }
28 
verify(&self, sig: &[u8], data: &[u8]) -> Result<(), String>29     fn verify(&self, sig: &[u8], data: &[u8]) -> Result<(), String> {
30         if sig != self.sign(data) {
31             Err("failed to verify".to_owned())
32         } else {
33             Ok(())
34         }
35     }
36 }
37 
main() -> Result<(), CoseError>38 fn main() -> Result<(), CoseError> {
39     // Build a fake signer/verifier (to avoid pulling in lots of dependencies).
40     let signer = FakeSigner {};
41     let verifier = signer;
42 
43     // Build a CWT ClaimsSet (cf. RFC 8392 A.3).
44     let claims = cwt::ClaimsSetBuilder::new()
45         .issuer("coap://as.example.com".to_string())
46         .subject("erikw".to_string())
47         .audience("coap://light.example.com".to_string())
48         .expiration_time(cwt::Timestamp::WholeSeconds(1444064944))
49         .not_before(cwt::Timestamp::WholeSeconds(1443944944))
50         .issued_at(cwt::Timestamp::WholeSeconds(1443944944))
51         .cwt_id(vec![0x0b, 0x71])
52         // Add additional standard claim.
53         .claim(
54             iana::CwtClaimName::Scope,
55             Value::Text("email phone".to_string()),
56         )
57         // Add additional private-use claim.
58         .private_claim(-70_000, Value::Integer(42.into()))
59         .build();
60     let aad = b"";
61 
62     // Build a `CoseSign1` object.
63     let protected = coset::HeaderBuilder::new()
64         .algorithm(iana::Algorithm::ES256)
65         .build();
66     let unprotected = coset::HeaderBuilder::new()
67         .key_id(b"AsymmetricECDSA256".to_vec())
68         .build();
69     let sign1 = coset::CoseSign1Builder::new()
70         .protected(protected)
71         .unprotected(unprotected)
72         .payload(claims.clone().to_vec()?)
73         .create_signature(aad, |pt| signer.sign(pt))
74         .build();
75 
76     // Serialize to bytes.
77     let sign1_data = sign1.to_vec()?;
78 
79     // At the receiving end, deserialize the bytes back to a `CoseSign1` object.
80     let sign1 = coset::CoseSign1::from_slice(&sign1_data)?;
81 
82     // Real code would:
83     // - Use the key ID to identify the relevant local key.
84     // - Check that the key is of the same type as `sign1.protected.algorithm`.
85 
86     // Check the signature.
87     let result = sign1.verify_signature(aad, |sig, data| verifier.verify(sig, data));
88     println!("Signature verified: {:?}.", result);
89     assert!(result.is_ok());
90 
91     // Now it's safe to parse the payload.
92     let recovered_claims = cwt::ClaimsSet::from_slice(&sign1.payload.unwrap())?;
93 
94     assert_eq!(recovered_claims, claims);
95     Ok(())
96 }
97