summon_client_sdk/
signatures.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use cardano_multiplatform_lib::address::Address as Address;
use cardano_message_signing as cms;
use cardano_multiplatform_lib::crypto::PrivateKey as PrivateKey;
use cardano_message_signing::error::JsError;
use cms::utils::ToBytes;
use serde::{Serialize, Deserialize};
use wasm_bindgen::prelude::wasm_bindgen;


/**
 *   To be returned from signing functions
 *   DataSignatureRes {
 *      dt: DataSignature | None,
 *      error: String
 *   }
 */
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct DataSignatureRes {
    dt: Option<DataSignature>,
    error: String,
}

#[wasm_bindgen]
impl DataSignatureRes {
    #[wasm_bindgen(constructor)]
    pub fn new(dt: Option<DataSignature>, error_in: Option<String>) -> Self {
        Self {
            dt,
            error: error_in.unwrap_or("".to_string())
        }
    }
    pub fn error(&self) -> String {
        self.error.clone()
    }
    pub fn dt(&self) -> Option<DataSignature> {
        self.dt.clone()
    }
}

/**
 *   signature:  COSESign1 bytes
 *   key: COSEKey hex bytes
 */
#[wasm_bindgen]
#[derive(Serialize, Deserialize, Clone)]
pub struct DataSignature {
    signature: Vec<u8>, //COSESign1 bytes
    key: Vec<u8>, //COSEKey bytes
}

#[wasm_bindgen]
impl DataSignature {
    #[wasm_bindgen(constructor)]
    pub fn new(cose_sig: &[u8], cose_key: &[u8]) -> Self {
        Self {
            key: cose_key.to_vec(),
            signature: cose_sig.to_vec()
        }
    }
    pub fn key(&self) -> Vec<u8> {
        self.key.clone()
    }
    pub fn signature(&self) -> Vec<u8> {
        self.signature.clone()
    }
}

/**
 *  **Sign data CIP30-like**
 *   returns -> 
 *    DataSignature {
 *      signature:  COSESign1 bytes
 *      key: COSEKey bytes
 *    } OR error string
 */
pub fn sign_data_like_cip30(key: PrivateKey, address_bech32: &str, message: &str) -> Result<DataSignature, JsError> {
    let public_key = key.to_public();
    let mut protected_headers = cms::HeaderMap::new();

    protected_headers.set_algorithm_id(&cms::Label::from_algorithm_id(
        cms::builders::AlgorithmId::EdDSA,
    ));

    let maybe_address = Address::from_bech32(address_bech32);

    match maybe_address {
        Ok(address) => {

            let cbor_value_address = cms::cbor::CBORValue::new_bytes(
                address
                .to_bytes(),
            );
        
            protected_headers.set_header(
                &cms::Label::new_text("address".to_string()),
                &cbor_value_address,
            ).expect("Failed to set address protected COSESign1 header value");

            let protected_serialized = cms::ProtectedHeaderMap::new(&protected_headers);
            let unprotected_headers = cms::HeaderMap::new();
            let headers = cms::Headers::new(&protected_serialized, &unprotected_headers);
            let builder = cms::builders::COSESign1Builder::new(&headers, message.as_bytes().to_vec(), false);
            let to_sign = builder.make_data_to_sign().to_bytes();
            let signed_sig_struc = key.sign(&to_sign);
        
            let mut key = cms::COSEKey::new(&cms::Label::from_key_type(cms::builders::KeyType::OKP));
            key.set_algorithm_id(&cms::Label::from_algorithm_id(
                cms::builders::AlgorithmId::EdDSA,
            ));
            key.set_header(
                &cms::Label::new_int(&cms::utils::Int::new_negative(
                    cms::utils::BigNum::from_str("1").unwrap(),
                )),
                &cms::cbor::CBORValue::new_int(
                    &cms::utils::Int::new_i32(6), //cms::CurveType.Ed25519
                ),
            ).expect("Failed to set encryption COSESign1 header value"); // crv (-1) set to Ed25519 (6)
            key.set_header(
                &cms::Label::new_int(&cms::utils::Int::new_negative(
                    cms::utils::BigNum::from_str("2").unwrap(),
                )),
                &cms::cbor::CBORValue::new_bytes(public_key.as_bytes()),
            ).expect("Failed to set content type COSESign1 header value"); // x (-2) set to public key
            let cose_sign1 = builder.build(signed_sig_struc.to_bytes());
        
            return Ok(DataSignature::new(
                &cose_sign1.to_bytes(),
                &key.to_bytes(),
            ));
        },
        _ => Err(JsError::from_str("Failed to serialize provided address.")),
    }
}