// 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<u8> {
        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(())
}
