1 // Copyright 2021 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 signature creation.
18 use coset::{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     // Inputs.
44     let pt = b"This is the content";
45     let aad = b"this is additional data";
46 
47     // Build a `CoseSign1` object.
48     let protected = coset::HeaderBuilder::new()
49         .algorithm(iana::Algorithm::ES256)
50         .key_id(b"11".to_vec())
51         .build();
52     let sign1 = coset::CoseSign1Builder::new()
53         .protected(protected)
54         .payload(pt.to_vec())
55         .create_signature(aad, |pt| signer.sign(pt))
56         .build();
57 
58     // Serialize to bytes.
59     let sign1_data = sign1.to_vec()?;
60     println!(
61         "'{}' + '{}' => {}",
62         String::from_utf8_lossy(pt),
63         String::from_utf8_lossy(aad),
64         hex::encode(&sign1_data)
65     );
66 
67     // At the receiving end, deserialize the bytes back to a `CoseSign1` object.
68     let mut sign1 = coset::CoseSign1::from_slice(&sign1_data)?;
69 
70     // Check the signature, which needs to have the same `aad` provided.
71     let result = sign1.verify_signature(aad, |sig, data| verifier.verify(sig, data));
72     println!("Signature verified: {:?}.", result);
73     assert!(result.is_ok());
74 
75     // Changing an unprotected header leaves the signature valid.
76     sign1.unprotected.content_type = Some(coset::ContentType::Text("text/plain".to_owned()));
77     assert!(sign1
78         .verify_signature(aad, |sig, data| verifier.verify(sig, data))
79         .is_ok());
80 
81     // Providing a different `aad` means the signature won't validate.
82     assert!(sign1
83         .verify_signature(b"not aad", |sig, data| verifier.verify(sig, data))
84         .is_err());
85 
86     // Changing a protected header invalidates the signature.
87     sign1.protected.header.content_type = Some(coset::ContentType::Text("text/plain".to_owned()));
88     sign1.protected.original_data = None;
89     assert!(sign1
90         .verify_signature(aad, |sig, data| verifier.verify(sig, data))
91         .is_err());
92     Ok(())
93 }
94