-
Notifications
You must be signed in to change notification settings - Fork 83
/
signed.rs
91 lines (80 loc) · 2.5 KB
/
signed.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
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
use crate::envelope::EnvelopeExt;
use crate::envelope::Plaintext;
use crate::error::Result;
use identity_core::crypto::KeyPair;
use identity_core::crypto::PublicKey;
use identity_core::utils::encode_b58;
use libjose::jose::JoseTokenType;
use libjose::jws::Decoder;
use libjose::jws::Encoder;
use libjose::jws::JwsAlgorithm;
use libjose::jws::JwsFormat;
use libjose::jws::JwsHeader;
use serde::Deserialize;
use serde::Serialize;
/// Supported digital signature algorithms
///
/// [Reference](https://identity.foundation/didcomm-messaging/spec/#algorithms)
#[derive(Clone, Copy, Debug)]
pub enum Algorithm {
EdDSA, // crv=Ed25519
ES256,
ES256K,
}
impl From<Algorithm> for JwsAlgorithm {
fn from(other: Algorithm) -> Self {
match other {
Algorithm::EdDSA => Self::EdDSA,
Algorithm::ES256 => Self::ES256,
Algorithm::ES256K => Self::ES256K,
}
}
}
/// A DIDComm Signed Message
///
/// [Reference](https://identity.foundation/didcomm-messaging/spec/#didcomm-signed-message)
///
/// # Layout
///
/// `JWS(Plaintext)`
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Envelope(String);
impl Envelope {
pub fn from_message<T: Serialize>(message: &T, algorithm: Algorithm, keypair: &KeyPair) -> Result<Self> {
Plaintext::from_message(message).and_then(|plaintext| Self::from_plaintext(&plaintext, algorithm, keypair))
}
pub fn from_plaintext(envelope: &Plaintext, algorithm: Algorithm, keypair: &KeyPair) -> Result<Self> {
let header: JwsHeader = {
let mut header: JwsHeader = JwsHeader::new(algorithm.into());
header.set_kid(encode_b58(keypair.public()));
header.set_typ(JoseTokenType::JWM.name());
header
};
Encoder::new()
.format(JwsFormat::Compact)
.recipient((keypair.secret().as_ref(), &header))
.encode(envelope.as_bytes())
.map_err(Into::into)
.map(Self)
}
pub fn to_message<T>(&self, algorithm: Algorithm, public: &PublicKey) -> Result<T>
where
for<'a> T: Deserialize<'a>,
{
let token = Decoder::new(public.as_ref())
.key_id(encode_b58(public))
.format(JwsFormat::Compact)
.algorithm(algorithm.into())
.decode(self.as_bytes())?;
serde_json::from_slice(&token.claims.to_vec()).map_err(Into::into)
}
}
impl EnvelopeExt for Envelope {
const FEXT: &'static str = "dcsm";
const MIME: &'static str = "application/didcomm-signed+json";
fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}