// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// //! Example program demonstrating signature creation. use coset::{iana, CborSerializable, CoseError}; #[derive(Copy, Clone)] struct FakeSigner {} // Use a fake signer/verifier (to avoid pulling in lots of dependencies). impl FakeSigner { fn sign(&self, data: &[u8]) -> Vec { data.to_vec() } fn verify(&self, sig: &[u8], data: &[u8]) -> Result<(), String> { if sig != self.sign(data) { Err("failed to verify".to_owned()) } else { Ok(()) } } } fn main() -> Result<(), CoseError> { // Build a fake signer/verifier (to avoid pulling in lots of dependencies). let signer = FakeSigner {}; let verifier = signer; // Inputs. let pt = b"This is the content"; let aad = b"this is additional data"; // Build a `CoseSign1` object. let protected = coset::HeaderBuilder::new() .algorithm(iana::Algorithm::ES256) .key_id(b"11".to_vec()) .build(); let sign1 = coset::CoseSign1Builder::new() .protected(protected) .payload(pt.to_vec()) .create_signature(aad, |pt| signer.sign(pt)) .build(); // Serialize to bytes. let sign1_data = sign1.to_vec()?; println!( "'{}' + '{}' => {}", String::from_utf8_lossy(pt), String::from_utf8_lossy(aad), hex::encode(&sign1_data) ); // At the receiving end, deserialize the bytes back to a `CoseSign1` object. let mut sign1 = coset::CoseSign1::from_slice(&sign1_data)?; // Check the signature, which needs to have the same `aad` provided. let result = sign1.verify_signature(aad, |sig, data| verifier.verify(sig, data)); println!("Signature verified: {:?}.", result); assert!(result.is_ok()); // Changing an unprotected header leaves the signature valid. sign1.unprotected.content_type = Some(coset::ContentType::Text("text/plain".to_owned())); assert!(sign1 .verify_signature(aad, |sig, data| verifier.verify(sig, data)) .is_ok()); // Providing a different `aad` means the signature won't validate. assert!(sign1 .verify_signature(b"not aad", |sig, data| verifier.verify(sig, data)) .is_err()); // Changing a protected header invalidates the signature. sign1.protected.header.content_type = Some(coset::ContentType::Text("text/plain".to_owned())); sign1.protected.original_data = None; assert!(sign1 .verify_signature(aad, |sig, data| verifier.verify(sig, data)) .is_err()); Ok(()) }