cryptouri/
encoding.rs

1//! CryptoURI encoding support
2
3/// Characters to use when encoding CryptoUris
4#[derive(Debug, Eq, PartialEq)]
5pub(crate) struct Encoding {
6    /// Scheme prefix for hashes
7    pub hash_scheme: &'static str,
8
9    /// Scheme prefix for public keys
10    pub public_key_scheme: &'static str,
11
12    /// Scheme prefix for secret keys
13    pub secret_key_scheme: &'static str,
14
15    /// Scheme prefix for signatures
16    pub signature_scheme: &'static str,
17
18    /// Bech32 delimiter which separates "Human Readable Part" from binary part
19    pub delimiter: char,
20
21    /// Character used to combine disparate primitives into a ciphersuite
22    pub combine: char,
23
24    /// Fragment delimiter
25    pub fragment_delimiter: Option<char>,
26}
27
28// TODO: compute schemes using delimiter rather than hardcoding each one
29
30/// Normal URI encoding
31pub(crate) const URI_ENCODING: &Encoding = &Encoding {
32    hash_scheme: "crypto:hash:",
33    public_key_scheme: "crypto:pub:key:",
34    secret_key_scheme: "crypto:sec:key:",
35    signature_scheme: "crypto:sig:",
36    delimiter: ':',
37    combine: '+',
38    fragment_delimiter: Some('#'),
39};
40
41/// URI-embeddable (a.k.a. "dasherized") encoding
42pub(crate) const DASHERIZED_ENCODING: &Encoding = &Encoding {
43    hash_scheme: "crypto-hash-",
44    public_key_scheme: "crypto-pub-key-",
45    secret_key_scheme: "crypto-sec-key-",
46    signature_scheme: "crypto-sig-",
47    delimiter: '-',
48    combine: '_',
49    fragment_delimiter: None,
50};
51
52/// Objects that can be encoded as CryptoUri
53pub trait Encodable {
54    /// Encode this object in URI generic syntax
55    fn to_uri_string(&self) -> String;
56
57    /// Encode this object in URI-embeddable "dasherized" format
58    fn to_dasherized_string(&self) -> String;
59}
60
61macro_rules! impl_encodable {
62    ($scheme:ident, $name:ident, $alg:expr) => {
63        impl crate::encoding::Encodable for $name {
64            #[inline]
65            fn to_uri_string(&self) -> String {
66                use subtle_encoding::bech32::{self, Bech32};
67                Bech32::new(
68                    bech32::DEFAULT_CHARSET,
69                    $crate::encoding::URI_ENCODING.delimiter,
70                )
71                .encode(
72                    $crate::encoding::URI_ENCODING.$scheme.to_owned() + $alg,
73                    &self.0[..],
74                )
75            }
76
77            #[inline]
78            fn to_dasherized_string(&self) -> String {
79                use subtle_encoding::bech32::{self, Bech32};
80                Bech32::new(
81                    bech32::DEFAULT_CHARSET,
82                    $crate::encoding::DASHERIZED_ENCODING.delimiter,
83                )
84                .encode(
85                    $crate::encoding::DASHERIZED_ENCODING.$scheme.to_owned() + $alg,
86                    &self.0[..],
87                )
88            }
89        }
90    };
91}
92
93macro_rules! impl_encodable_hash {
94    ($name:ident, $alg:expr) => {
95        impl_encodable!(hash_scheme, $name, $alg);
96    };
97}
98
99macro_rules! impl_encodable_public_key {
100    ($name:ident, $alg:expr) => {
101        impl_encodable!(public_key_scheme, $name, $alg);
102    };
103}
104
105macro_rules! impl_encodable_secret_key {
106    ($name:ident, $alg:expr) => {
107        impl crate::encoding::Encodable for $name {
108            #[inline]
109            fn to_uri_string(&self) -> String {
110                use secrecy::ExposeSecret;
111                use subtle_encoding::bech32::{self, Bech32};
112                Bech32::new(
113                    bech32::DEFAULT_CHARSET,
114                    $crate::encoding::URI_ENCODING.delimiter,
115                )
116                .encode(
117                    $crate::encoding::URI_ENCODING.secret_key_scheme.to_owned() + $alg,
118                    &self.expose_secret()[..],
119                )
120            }
121
122            #[inline]
123            fn to_dasherized_string(&self) -> String {
124                use secrecy::ExposeSecret;
125                use subtle_encoding::bech32::{self, Bech32};
126                Bech32::new(
127                    bech32::DEFAULT_CHARSET,
128                    $crate::encoding::DASHERIZED_ENCODING.delimiter,
129                )
130                .encode(
131                    $crate::encoding::DASHERIZED_ENCODING
132                        .secret_key_scheme
133                        .to_owned()
134                        + $alg,
135                    &self.expose_secret()[..],
136                )
137            }
138        }
139    };
140}
141
142macro_rules! impl_encodable_signature {
143    ($name:ident, $alg:expr) => {
144        impl_encodable!(signature_scheme, $name, $alg);
145    };
146}