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]]
|
[[bin]]
|
||||||
name = "credit5000"
|
name = "credit5000"
|
||||||
path = "src/main.rs"
|
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