Skip to content

Commit af1b8ec

Browse files
authored
Merge pull request #12 from cryptidtech/ml/traits
Add Bs traits
2 parents d008921 + 1b0a46e commit af1b8ec

File tree

8 files changed

+217
-15
lines changed

8 files changed

+217
-15
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ default-members = ["crates/bs"]
44
members = [
55
"cli",
66
"crates/bs",
7+
"crates/bs-traits",
78
"crates/bsp2p",
89
"crates/content-addressable",
910
"crates/multibase",
@@ -36,6 +37,7 @@ unexpected_cfgs = { level = "warn", check-cfg = [
3637
[workspace.dependencies]
3738
# Crate ependencies
3839
bs = { path = "crates/bs" }
40+
bs-traits = { path = "crates/bs-traits" }
3941
multibase = { path = "crates/multibase" }
4042
multicid = { path = "crates/multicid" }
4143
multicodec = { path = "crates/multicodec" }

crates/bs-traits/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "bs-traits"
3+
version.workspace = true
4+
edition.workspace = true
5+
authors.workspace = true
6+
description.workspace = true
7+
readme = "README.md"
8+
license = "Functional Source License 1.1"
9+
10+
[dependencies]
11+
thiserror.workspace = true
12+
13+
[lints]
14+
workspace = true

crates/bs-traits/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[![](https://img.shields.io/badge/made%20by-Cryptid%20Technologies-gold.svg?style=flat-square)][CRYPTID]
2+
[![](https://img.shields.io/badge/project-provenance-purple.svg?style=flat-square)][PROVENANCE]
3+
4+
# BS-Traits
5+
6+
The traits used by Better Sign

crates/bs-traits/src/error.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: FSL-1.1
2+
3+
/// Error type for the crates
4+
#[derive(Debug, thiserror::Error)]
5+
#[non_exhaustive]
6+
pub enum Error {
7+
/// Signing operation failed
8+
#[error("signing operation failed")]
9+
SignError,
10+
11+
/// Verification operation failed
12+
#[error("verification operation failed")]
13+
VerifyError,
14+
15+
/// Encryption operation failed
16+
#[error("encryption operation failed")]
17+
EncryptError,
18+
19+
/// Decryption operation failed
20+
#[error("decryption operation failed")]
21+
DecryptError,
22+
23+
/// Key retrieval operation failed
24+
#[error("key retrieval operation failed")]
25+
KeyError,
26+
}

crates/bs-traits/src/lib.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// SPDX-License-Identifier: FSL-1.1
2+
3+
mod error;
4+
pub use error::Error;
5+
6+
use core::num::NonZeroUsize;
7+
8+
/// Trait for types that can sign data
9+
pub trait Signer {
10+
/// The type of key used to sign
11+
type Key;
12+
/// The type of signature
13+
type Signature;
14+
15+
/// Attempt to sign the data
16+
fn try_sign(&self, key: &Self::Key, data: &[u8]) -> Result<Self::Signature, Error>;
17+
18+
/// Sign the data and return the signature
19+
fn sign(&self, key: &Self::Key, data: &[u8]) -> Self::Signature {
20+
self.try_sign(key, data).expect("signing operation failed")
21+
}
22+
}
23+
24+
/// Trait for types that can verify signatures
25+
pub trait Verifier {
26+
/// The type of key used to verify
27+
type Key;
28+
/// The type of signature
29+
type Signature;
30+
31+
/// Verify that the provided signature for the given data is authentic
32+
fn verify(
33+
&self,
34+
key: &Self::Key,
35+
data: &[u8],
36+
signature: &Self::Signature,
37+
) -> Result<(), Error>;
38+
}
39+
40+
/// Trait for types that can encrypt data
41+
pub trait Encryptor {
42+
/// The type of key used to encrypt
43+
type Key;
44+
/// The type of ciphertext
45+
type Ciphertext;
46+
/// The type of plaintext, might include the nonce, and additional authenticated data
47+
type Plaintext;
48+
49+
/// Attempt to encrypt the plaintext
50+
fn try_encrypt(
51+
&self,
52+
key: &Self::Key,
53+
plaintext: &Self::Plaintext,
54+
) -> Result<Self::Ciphertext, Error>;
55+
56+
/// Encrypt the plaintext
57+
fn encrypt(&self, key: &Self::Key, plaintext: &Self::Plaintext) -> Self::Ciphertext {
58+
self.try_encrypt(key, plaintext)
59+
.expect("encryption operation failed")
60+
}
61+
}
62+
63+
/// Trait for types that can decrypt data
64+
pub trait Decryptor {
65+
/// The type of key used to decrypt
66+
type Key;
67+
/// The type of ciphertext
68+
type Ciphertext;
69+
/// The type of plaintext
70+
type Plaintext;
71+
72+
/// Attempt to decrypt the ciphertext
73+
fn decrypt(
74+
&self,
75+
key: &Self::Key,
76+
ciphertext: &Self::Ciphertext,
77+
) -> Result<Self::Plaintext, Error>;
78+
}
79+
80+
/// Trait for types that can split a secret into shares
81+
pub trait SecretSplitter {
82+
/// The type of secret to split
83+
type Secret;
84+
/// The type of identifier for the shares
85+
type Identifier;
86+
/// The output from splitting the secret.
87+
/// Might include the threshold and limit used to split the secret,
88+
/// the shares, and the verifiers, identifiers,
89+
/// or any other information needed to reconstruct the secret
90+
/// and verify the shares.
91+
type Output;
92+
93+
/// Split the secret into shares.
94+
///
95+
/// Conditions for `split` to succeed:
96+
/// - Threshold must be less than or equal to limit.
97+
/// - Threshold must be greater than or equal to 2.
98+
fn split(
99+
&self,
100+
secret: &Self::Secret,
101+
threshold: NonZeroUsize,
102+
limit: NonZeroUsize,
103+
) -> Result<Self::Output, Error>;
104+
105+
/// Split the secret into shares with the given identifiers.
106+
/// The number of shares will be equal to the number of identifiers i.e. the `limit`.
107+
///
108+
/// Conditions for `split_with_identifiers` to succeed:
109+
/// - Threshold must be less than or equal to the number of identifiers.
110+
/// - Threshold must be greater than or equal to 2.
111+
/// - Identifiers must be unique.
112+
/// - Identifiers must not be empty.
113+
fn split_with_identifiers(
114+
&self,
115+
secret: &Self::Secret,
116+
threshold: NonZeroUsize,
117+
identifiers: &[Self::Identifier],
118+
) -> Result<Self::Output, Error>;
119+
}
120+
121+
/// Trait for types that can combine shares into a secret
122+
pub trait SecretCombiner {
123+
/// The type of secret to combine
124+
type Secret;
125+
/// The type of identifier for the shares
126+
type Identifier;
127+
/// The type of shares to combine
128+
type Shares;
129+
130+
/// Combine the shares into a secret
131+
fn combine(&self, shares: &[(Self::Identifier, Self::Shares)]) -> Result<Self::Secret, Error>;
132+
}
133+
134+
/// Trait for types that can retrieve a key
135+
pub trait GetKey {
136+
/// The type of key
137+
type Key;
138+
/// The type of key path
139+
type KeyPath;
140+
/// The type of codec
141+
type Codec;
142+
143+
/// Get the key
144+
fn get_key(
145+
&self,
146+
key_path: &Self::KeyPath,
147+
codec: &Self::Codec,
148+
threshold: usize,
149+
limit: usize,
150+
) -> Result<Self::Key, Error>;
151+
}

crates/bs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ readme = "README.md"
88
license = "Functional Source License 1.1"
99

1010
[dependencies]
11+
bs-traits.workspace = true
1112
best-practices.workspace = true
1213
multicid.workspace = true
1314
multicodec.workspace = true

crates/bs/src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ pub enum Error {
1010
#[error(transparent)]
1111
Update(#[from] UpdateError),
1212

13+
/// Traits error
14+
#[error(transparent)]
15+
Traits(#[from] bs_traits::Error),
16+
1317
/// BestPractices error
1418
#[error(transparent)]
1519
BestPractices(#[from] best_practices::error::Error),

crates/bs/src/ops/open/mod.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
update::{op, script, OpParams},
1010
Error,
1111
};
12+
use bs_traits::{GetKey, Signer};
1213
use multicid::{cid, vlad, Cid};
1314
use multicodec::Codec;
1415
use multihash::mh;
@@ -19,10 +20,10 @@ use std::{fs::read, path::Path};
1920
use tracing::debug;
2021

2122
/// open a new provenance log based on the config
22-
pub fn open_plog<F1, F2>(config: Config, get_key: F1, sign_entry: F2) -> Result<Log, Error>
23+
pub fn open_plog<G, S>(config: Config, get_key: &G, sign_entry: &S) -> Result<Log, Error>
2324
where
24-
F1: Fn(&Key, Codec, usize, usize) -> Result<Multikey, Error>,
25-
F2: Fn(&Multikey, &[u8]) -> Result<Multisig, Error>,
25+
G: GetKey<Key = Multikey, KeyPath = Key, Codec = Codec>,
26+
S: Signer<Key = Multikey, Signature = Multisig>,
2627
{
2728
// 0. Set up the list of ops we're going to add
2829
let mut op_params = Vec::default();
@@ -35,7 +36,7 @@ where
3536
.try_for_each(|params| -> Result<(), Error> {
3637
match params {
3738
p @ OpParams::KeyGen { .. } => {
38-
let _ = load_key(&mut op_params, p, &get_key)?;
39+
let _ = load_key(&mut op_params, p, get_key)?;
3940
}
4041
p @ OpParams::CidGen { .. } => {
4142
let _ = load_cid(&mut op_params, p, |path| -> Result<Vec<u8>, Error> {
@@ -54,7 +55,7 @@ where
5455
.vlad_params
5556
.ok_or::<Error>(OpenError::InvalidVladParams.into())?;
5657
// get the vlad signing key
57-
let vlad_mk = load_key(&mut op_params, &vlad_key_params, &get_key)?;
58+
let vlad_mk = load_key(&mut op_params, &vlad_key_params, get_key)?;
5859
// get the cid for the first lock script
5960
let mut first_lock_script: Option<Script> = None;
6061
let cid = load_cid(
@@ -82,15 +83,15 @@ where
8283
.ok_or::<Error>(OpenError::InvalidKeyParams.into())?;
8384

8485
// get the entry signing key
85-
let entry_mk = load_key(&mut op_params, &entrykey_params, &get_key)?;
86+
let entry_mk = load_key(&mut op_params, &entrykey_params, get_key)?;
8687

8788
// get the params for the pubkey
8889
let pubkey_params = config
8990
.pubkey_params
9091
.ok_or::<Error>(OpenError::InvalidKeyParams.into())?;
9192

9293
// get the pubkey
93-
let _ = load_key(&mut op_params, &pubkey_params, &get_key)?;
94+
let _ = load_key(&mut op_params, &pubkey_params, get_key)?;
9495

9596
// load the entry lock script
9697
let lock_script = {
@@ -162,7 +163,8 @@ where
162163
// get the serialzied version of the entry with an empty "proof" field
163164
let ev: Vec<u8> = e.clone().into();
164165
// call the call back to have the caller sign the data
165-
let ms = sign_entry(&entry_mk, &ev)
166+
let ms = sign_entry
167+
.try_sign(&entry_mk, &ev)
166168
.map_err(|e| PlogError::from(EntryError::SignFailed(e.to_string())))?;
167169
// store the signature as proof
168170
Ok(ms.into())
@@ -179,13 +181,9 @@ where
179181
Ok(log)
180182
}
181183

182-
fn load_key<F>(
183-
ops: &mut Vec<OpParams>,
184-
params: &OpParams,
185-
mut get_key: F,
186-
) -> Result<Multikey, Error>
184+
fn load_key<G>(ops: &mut Vec<OpParams>, params: &OpParams, get_key: &G) -> Result<Multikey, Error>
187185
where
188-
F: FnMut(&Key, Codec, usize, usize) -> Result<Multikey, Error>,
186+
G: GetKey<Key = Multikey, KeyPath = Key, Codec = Codec>,
189187
{
190188
debug!("load_key: {:?}", params);
191189
match params {
@@ -197,7 +195,7 @@ where
197195
revoke,
198196
} => {
199197
// call back to generate the key
200-
let mk = get_key(key, *codec, *threshold, *limit)?;
198+
let mk = get_key.get_key(key, codec, *threshold, *limit)?;
201199

202200
// get the public key
203201
let pk = mk.conv_view()?.to_public_key()?;

0 commit comments

Comments
 (0)