lib: Add Obligation and Cert types with construction
This commit is contained in:
parent
3278f33899
commit
81d2e8b116
2 changed files with 106 additions and 0 deletions
|
@ -6,3 +6,7 @@ edition = "2021"
|
|||
[[bin]]
|
||||
name = "credit5000"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
ed25519-dalek = "2.1.1"
|
||||
rand = "0.8.5"
|
||||
|
|
102
src/lib.rs
Normal file
102
src/lib.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
use dalek::Verifier;
|
||||
use ed25519_dalek as dalek;
|
||||
use rand::prelude as rand;
|
||||
|
||||
pub type Address = [u8; 32];
|
||||
pub type Signature = [u8; 64];
|
||||
pub type Salt = [u8; 32];
|
||||
|
||||
/// TODO: Use hashes instead of public addresses.
|
||||
/// TODO: Don't forget document endiannes.
|
||||
/// TODO: Allow doubly signed obligations or implement abstract interfaces for Cert (see below).
|
||||
|
||||
/// Implement abstract Cert datatype to allow attestation of hyper-relations:
|
||||
/// TODO: Use serializable trait to generalize over the subject field.
|
||||
/// TODO: Allow per subject type verification trait. Hard not to go
|
||||
/// full crypto-conditions but better not to complicate things too
|
||||
/// much.
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Obligation {
|
||||
pub from: Address,
|
||||
pub to: Address,
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
impl Obligation {
|
||||
fn serialize(self) -> Vec<u8> {
|
||||
[&self.from[..], &self.value.to_le_bytes()[..], &self.to[..]].concat()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cert {
|
||||
pub subject: Obligation,
|
||||
pub signature: Signature,
|
||||
pub salt: Salt,
|
||||
}
|
||||
|
||||
impl Cert {
|
||||
/// TODO: add optional salt argument
|
||||
pub fn new(sub: Obligation, sig: Signature) -> Result<Self, &'static str> {
|
||||
match dalek::VerifyingKey::from_bytes(&sub.from)
|
||||
.unwrap()
|
||||
.verify(&sub.serialize()[..], &dalek::Signature::from_bytes(&sig))
|
||||
{
|
||||
Ok(_) => Ok(Self {
|
||||
subject: sub,
|
||||
signature: sig,
|
||||
salt: rand::random(),
|
||||
}),
|
||||
Err(_) => Err("Invalid signature"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Cert, Obligation};
|
||||
use ed25519_dalek::{Signer, SigningKey};
|
||||
|
||||
#[test]
|
||||
fn serialize_obligation() {
|
||||
assert_eq!(
|
||||
Obligation {
|
||||
from: [1; 32],
|
||||
to: [2; 32],
|
||||
value: 4_294_967_295, // Max u32 (255 255 255 255)
|
||||
}
|
||||
.serialize(),
|
||||
[
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 255, 255, 255, 255, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cert_new() {
|
||||
let sk_gen = || {
|
||||
let skobj = SigningKey::from_bytes(&rand::random());
|
||||
(
|
||||
skobj.clone(),
|
||||
skobj.to_bytes(),
|
||||
skobj.verifying_key().to_bytes(),
|
||||
)
|
||||
};
|
||||
let (f, _, fpk) = sk_gen();
|
||||
let (_, _, tpk) = sk_gen();
|
||||
let sub = Obligation {
|
||||
from: fpk,
|
||||
to: tpk,
|
||||
value: 1000,
|
||||
};
|
||||
let sig = f.sign(&sub.serialize()[..]).to_bytes();
|
||||
let cert = Cert::new(sub, sig);
|
||||
assert!(cert.is_ok());
|
||||
assert_eq!(cert.unwrap().subject, sub);
|
||||
assert_eq!(cert.unwrap().signature, sig);
|
||||
assert!(Cert::new(sub, [0; 64]).is_err());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue