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