Module agent

Source
Expand description

Module to build recipients/signers for the various types of COSE messages.

This structure is also used to build counter signatures that can be present in any type of COSE message.

§Example

This example shows a cose-sign1 message with 2 counter signatures present in it, one of them is counter signed externally to the crate.

§Encoding the message

use cose::message::CoseMessage;
use cose::agent::CoseAgent;
use cose::keys;
use cose::algs;
use openssl::bn::BigNum;
use openssl::bn::BigNumContext;
use openssl::ec::EcPoint;
use openssl::ec::{EcGroup, EcKey};
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::sign::{Signer, Verifier};
use openssl::nid::Nid;
use hex;

fn main() {
    let msg = b"This is the content.".to_vec();
    let kid = b"kid2".to_vec();

    // Prepare cose-key to encode the message
    let mut key = keys::CoseKey::new();
    key.kty(keys::OKP);
    key.alg(algs::EDDSA);
    key.crv(keys::ED25519);
    key.x(hex::decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a").unwrap());
    key.d(hex::decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap());
    key.key_ops(vec![keys::KEY_OPS_SIGN]);

    // Prepare cose_sign1 message
    let mut sign1 = CoseMessage::new_sign();
    sign1.header.alg(algs::EDDSA, true, false);
    sign1.payload(msg);

    // Add key and generate the signature without AAD
    sign1.key(&key).unwrap();
    sign1.secure_content(None).unwrap();


    // Prepare counter signature 1 key
    let mut counter1_key = keys::CoseKey::new();
    counter1_key.kty(keys::EC2);
    counter1_key.alg(algs::ES256);
    counter1_key.crv(keys::P_256);
    counter1_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
    counter1_key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
    counter1_key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
    counter1_key.key_ops(vec![keys::KEY_OPS_SIGN]);

    // Prepare counter signature 1
    let mut counter1 = CoseAgent::new_counter_sig();
    counter1.header.kid(vec![0], true, false);
    counter1.header.alg(algs::ES256, true, false);

    // Add counter signature 1 key, counter sign and add to the cose-sign1 message
    counter1.key(&counter1_key).unwrap();
    sign1.counter_sig(None, &mut counter1).unwrap();
    sign1.add_counter_sig(counter1).unwrap();


    // Prepare counter signature 2
    let mut counter2 = CoseAgent::new_counter_sig();
    counter2.header.alg(algs::ES256, true, false);
    counter2.header.kid([3].to_vec(), true, false);

    // Get content to counter sign externally
    let to_sign = sign1.get_to_sign(None, &mut counter2).unwrap();

    // Prepare private key to sign the content
    let counter2_priv_key = hex::decode("02d1f7e6f26c43d4868d87ceb2353161740aacf1f7163647984b522a848df1c3").unwrap();

    // Sign the content externally
    let number = BigNum::from_slice(counter2_priv_key.as_slice()).unwrap();
    let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
    let ec_key = EcKey::from_private_components(&group, &number, &EcPoint::new(&group).unwrap()).unwrap();
    let final_key = PKey::from_ec_key(ec_key).unwrap();
    let mut signer = Signer::new(MessageDigest::sha256(), &final_key).unwrap();
    signer.update(to_sign.as_slice()).unwrap();

    // Add counter signature to the cose-sign1 message
    counter2.add_signature(signer.sign_to_vec().unwrap()).unwrap();
    sign1.add_counter_sig(counter2).unwrap();

    // Encode cose-sign1 message
    sign1.encode(true).unwrap();
}

§Decoding the message

use cose::message::CoseMessage;
use cose::agent::CoseAgent;
use cose::keys;
use cose::algs;
use openssl::bn::BigNum;
use openssl::bn::BigNumContext;
use openssl::ec::EcPoint;
use openssl::ec::{EcGroup, EcKey};
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::sign::{Signer, Verifier};
use openssl::nid::Nid;
use hex;

fn main() {

    // Prepare cose-key to encode the message
    let mut key = keys::CoseKey::new();
    key.kty(keys::OKP);
    key.alg(algs::EDDSA);
    key.crv(keys::ED25519);
    key.x(hex::decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a").unwrap());
    key.key_ops(vec![keys::KEY_OPS_VERIFY]);

    // Prepare CoseMessage with the cose-sign1 message to decode
    let mut verify = CoseMessage::new_sign();
    verify.bytes = hex::decode("d28443a10127a107828346a20441000126a058402d9410644cfe376119fcb4ff9c48ee97a14fec58e6b02fc10b61d3dc667b2fcb74ab7cce6b2303066e5440e3d5cdd5a164c4483972eba8a9d85e924384365d4d8346a20126044103a058473045022100ce59168dd9e23b229c7f9362deb0efb9c1210ae0ed3e224c968210493ed96d97022024da25640eabd57e0f306abcc9e46973d530c34d7f112eea8ab27f0464312c0c54546869732069732074686520636f6e74656e742e58406354488f9f290e36cd80e23762e664a5cb03e4267c66a8cffaef7c66d89a40bf2cbb8222432a08e5ee410d8b540c6931d26fb6af673f7e2100655d8bae765c04").unwrap();
    verify.init_decoder(None).unwrap();

    // Add key and decode the message
    verify.key(&key).unwrap();
    verify.decode(None, None).unwrap();


    // Prepare counter signature 1 cose-key
    let mut c1_key = keys::CoseKey::new();
    c1_key.kty(keys::EC2);
    c1_key.alg(algs::ES256);
    c1_key.crv(keys::P_256);
    c1_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
    c1_key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
    c1_key.key_ops(vec![keys::KEY_OPS_VERIFY]);

    // Prepare counter signature 2 public key
    let counter2_pub_key =
    hex::decode("0398f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91d6280").unwrap();

    // Get counter signature 1 index
    let mut c1 = verify.header.get_counter(&vec![0]).unwrap()[0];

    // Add counter signature 1 key and verify
    verify.header.counters[c1].key(&c1_key).unwrap();
    verify.counters_verify(None, c1).unwrap();

    // Get counter signature 2
    let mut c2 = verify.header.get_counter(&vec![3]).unwrap()[0];

    // Get content to verify the counter signature externally
    let to_verify = verify.get_to_verify(None, &c2).unwrap();

    // Verify signture externally
    let mut ctx = BigNumContext::new().unwrap();
    let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
    let point = EcPoint::from_bytes(&group, &counter2_pub_key, &mut ctx).unwrap();
    let ec_key = EcKey::from_public_key(&group, &point).unwrap();
    let final_key = PKey::from_ec_key(ec_key).unwrap();
    let mut verifier = Verifier::new(MessageDigest::sha256(), &final_key).unwrap();
    verifier.update(&to_verify).unwrap();
    assert!(verifier.verify(&verify.header.counters[c2].payload).unwrap());
}

Structs§

CoseAgent
COSE recipient, signer or counter-signature structure.