iop_sdk_wasm/morpheus/
private.rs

1use super::*;
2
3/// Private keys of the Morpheus subtree in a vault.
4///
5/// @see MorpheusPlugin.priv
6#[wasm_bindgen(js_name = MorpheusPrivate)]
7pub struct JsMorpheusPrivate {
8    inner: MorpheusPrivate,
9}
10
11#[wasm_bindgen(js_class = MorpheusPrivate)]
12impl JsMorpheusPrivate {
13    /// Access to the public keys of the subtree. Same as {@link MorpheusPlugin.pub} would return.
14    #[wasm_bindgen(getter = pub)]
15    pub fn public(&self) -> JsMorpheusPublic {
16        let inner = self.inner.public();
17        JsMorpheusPublic::from(inner)
18    }
19
20    /// Accessor for the BIP32 path of the Morpheus subtree.
21    #[wasm_bindgen(getter = path)]
22    pub fn bip32_path(&self) -> String {
23        self.inner.node().path().to_string()
24    }
25
26    /// There can be several usages of DIDs differentiated inside the vault invisible externally, e.g. on a blockchain.
27    /// Each represents a separate subtree under the Morpheus subtree in the vault.
28    ///
29    /// Use 'persona', 'device', 'group' or 'resource' in singular as a parameter.
30    pub fn kind(&self, did_kind: &str) -> Result<JsMorpheusPrivateKind, JsValue> {
31        let did_kind: DidKind = did_kind.parse().map_err_to_js()?;
32        self.kind_impl(did_kind)
33    }
34
35    /// Alias for {@link kind('persona')}
36    #[wasm_bindgen(getter)]
37    pub fn personas(&self) -> Result<JsMorpheusPrivateKind, JsValue> {
38        self.kind_impl(DidKind::Persona)
39    }
40
41    /// Alias for {@link kind('device')}
42    #[wasm_bindgen(getter)]
43    pub fn devices(&self) -> Result<JsMorpheusPrivateKind, JsValue> {
44        self.kind_impl(DidKind::Device)
45    }
46
47    /// Alias for {@link kind('group')}
48    #[wasm_bindgen(getter)]
49    pub fn groups(&self) -> Result<JsMorpheusPrivateKind, JsValue> {
50        self.kind_impl(DidKind::Group)
51    }
52
53    /// Alias for {@link kind('resource')}
54    #[wasm_bindgen(getter)]
55    pub fn resources(&self) -> Result<JsMorpheusPrivateKind, JsValue> {
56        self.kind_impl(DidKind::Resource)
57    }
58
59    /// Finds the {@link MorpheusPrivateKey} that belongs to the given multicipher {@link PublicKey}. You can check the DID kind or
60    /// index of the key or get the actual {@link PrivateKey} from the returned object.
61    ///
62    /// An error will be thrown if the public key has never been used yet in this vault.
63    #[wasm_bindgen(js_name = keyByPublicKey)]
64    pub fn key_by_pk(&self, pk: &JsMPublicKey) -> Result<JsMorpheusPrivateKey, JsValue> {
65        let inner = self.inner.key_by_pk(pk.inner()).map_err_to_js()?;
66        Ok(JsMorpheusPrivateKey::from(inner))
67    }
68
69    /// Finds the {@link MorpheusPrivateKey} that belongs to the given multicipher {@link KeyId}. You can check the DID kind or
70    /// index of the key or get the actual {@link PrivateKey} from the returned object.
71    ///
72    /// An error will be thrown if the key identifier has never been used yet in this vault.
73    #[wasm_bindgen(js_name = keyById)]
74    pub fn key_by_id(&self, id: &JsMKeyId) -> Result<JsMorpheusPrivateKey, JsValue> {
75        let pk = self.inner.public().key_by_id(id.inner()).map_err_to_js()?;
76        let js_pk = JsMPublicKey::from(pk);
77        self.key_by_pk(&js_pk)
78    }
79
80    /// Signs some binary payload with a private key that belongs to the given multicipher {@link KeyId}.
81    ///
82    /// The returned {@link SignedBytes} has separate properties for signature and public key.
83    ///
84    /// Note, that usually it is usually a bad security to let the user sign a binary content that was not reviewed by the user on a
85    /// trusted user interface **before** serialization into that binary format.
86    ///
87    /// @see keyById
88    #[wasm_bindgen(js_name = signDidOperations)]
89    pub fn sign_did_operations(
90        &self, id: &JsMKeyId, message: &[u8],
91    ) -> Result<JsSignedBytes, JsValue> {
92        let signer = self.create_signer(id)?;
93        let (public_key, signature) = signer.sign(message).map_err_to_js()?;
94
95        let js_pk = JsMPublicKey::from(public_key);
96        let js_sig = JsMSignature::from(signature);
97        JsSignedBytes::new(&js_pk, message, &js_sig)
98    }
99
100    /// Signs a witness request for a verifiable claim with a private key that belongs to the given multicipher {@link KeyId}. An error
101    /// will be thrown if the JSON does not conform to the schema of a witness request.
102    ///
103    /// The returned {@link SignedJson} has separate properties for signature and public key, but can be serialized into a JSON format
104    /// widely used in the IOP Stack™.
105    ///
106    /// @see keyById
107    #[wasm_bindgen(js_name = signWitnessRequest)]
108    pub fn sign_witness_request(
109        &self, id: &JsMKeyId, js_req: &JsValue,
110    ) -> Result<JsSignedJson, JsValue> {
111        let signer = self.create_signer(id)?;
112        let request: WitnessRequest = js_req.into_serde().map_err(err_to_js)?;
113        let signed_request = signer.sign_witness_request(request).map_err(err_to_js)?;
114
115        into_signed_json(signed_request)
116    }
117
118    /// Signs a witness statemet for a verifiable claim with a private key that belongs to the given multicipher {@link KeyId}. An
119    /// error will be thrown if the JSON does not conform to the schema of a witness statement.
120    ///
121    /// The returned {@link SignedJson} has separate properties for signature and public key, but can be serialized into a JSON format
122    /// widely used in the IOP Stack™.
123    ///
124    /// @see keyById
125    #[wasm_bindgen(js_name = signWitnessStatement)]
126    pub fn sign_witness_statement(
127        &self, id: &JsMKeyId, js_stmt: &JsValue,
128    ) -> Result<JsSignedJson, JsValue> {
129        let signer = self.create_signer(id)?;
130        let statement: WitnessStatement = js_stmt.into_serde().map_err(err_to_js)?;
131        let signed_statement = signer.sign_witness_statement(statement).map_err(err_to_js)?;
132
133        into_signed_json(signed_statement)
134    }
135
136    /// Signs a claim presentation for verifiable claims with a private key that belongs to the given multicipher {@link KeyId}. An
137    /// error will be thrown if the JSON does not conform to the schema of a claim presentation.
138    ///
139    /// The returned {@link SignedJson} has separate properties for signature and public key, but can be serialized into a JSON format
140    /// widely used in the IOP Stack™.
141    ///
142    /// @see keyById
143    #[wasm_bindgen(js_name = signClaimPresentation)]
144    pub fn sign_claim_presentation(
145        &self, id: &JsMKeyId, js_presentation: &JsValue,
146    ) -> Result<JsSignedJson, JsValue> {
147        let signer = self.create_signer(id)?;
148        let presentation: ClaimPresentation = js_presentation.into_serde().map_err(err_to_js)?;
149        let signed_presentation =
150            signer.sign_claim_presentation(presentation).map_err(err_to_js)?;
151
152        into_signed_json(signed_presentation)
153    }
154
155    fn kind_impl(&self, did_kind: DidKind) -> Result<JsMorpheusPrivateKind, JsValue> {
156        let inner = self.inner.kind(did_kind).map_err_to_js()?;
157        Ok(JsMorpheusPrivateKind::from(inner))
158    }
159
160    fn create_signer(&self, id: &JsMKeyId) -> Result<PrivateKeySigner, JsValue> {
161        let js_sk = self.key_by_id(id)?;
162        let sk: MPrivateKey = js_sk.inner().private_key();
163        Ok(PrivateKeySigner::new(sk))
164    }
165}
166
167impl From<MorpheusPrivate> for JsMorpheusPrivate {
168    fn from(inner: MorpheusPrivate) -> Self {
169        Self { inner }
170    }
171}
172
173impl Wraps<MorpheusPrivate> for JsMorpheusPrivate {
174    fn inner(&self) -> &MorpheusPrivate {
175        &self.inner
176    }
177}
178
179fn into_signed_json<T: Signable>(signed: Signed<T>) -> Result<JsSignedJson, JsValue> {
180    let (public_key, content, signature, nonce) = signed.into_parts();
181    let content = serde_json::to_value(content).map_err(err_to_js)?;
182    let signed_json = Signed::from_parts(public_key, content, signature, nonce);
183    Ok(signed_json.into())
184}