Skip to content

Commit

Permalink
fix encoding bugs
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Huseby <[email protected]>
  • Loading branch information
dhuseby committed May 10, 2024
1 parent f042133 commit a78080b
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "multicid"
version = "1.0.1"
version = "1.0.2"
edition = "2021"
authors = ["Dave Grantham <[email protected]>"]
description = "Multicodec compatible content identifier implementation"
Expand Down
7 changes: 4 additions & 3 deletions src/cid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ use multibase::Base;
use multicodec::Codec;
use multihash::Multihash;
use multitrait::{Null, TryDecodeFrom};
use multiutil::{Base58Encoder, BaseEncoded, CodecInfo, EncodingInfo};
use multiutil::{Base58Encoder, BaseEncoded, CodecInfo, DetectedEncoder, EncodingInfo};

/// the multicodec sigil for Cid
pub const SIGIL: Codec = Codec::Cidv1;

/// a bare base58 encoded Cid
pub type LegacyEncodedCid = BaseEncoded<Cid, Base58Encoder>;

/// a multibase encoded Cid
pub type EncodedCid = BaseEncoded<Cid>;
/// a multibase encoded Cid that detects encoding while decoding. this allows transparent support
/// for Base58Btc encoded v0 Cid's as well as multibase encoded v1 Cid's
pub type EncodedCid = BaseEncoded<Cid, DetectedEncoder>;

/// implementation of cid
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq)]
Expand Down
103 changes: 79 additions & 24 deletions src/vlad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,31 @@ use multicodec::Codec;
use multikey::{nonce, Multikey, Nonce, Views};
use multisig::Multisig;
use multitrait::{Null, TryDecodeFrom};
use multiutil::{BaseEncoded, CodecInfo, EncodingInfo};
use multiutil::{BaseEncoded, CodecInfo, DetectedEncoder, EncodingInfo};

/// the Vlad multicodec sigil
pub const SIGIL: Codec = Codec::Vlad;

/// a multibase encoded Vlad
pub type EncodedVlad = BaseEncoded<Vlad>;
/// a multibase encoded Vlad that can decode from any number of encoding but always encodes to
/// Vlad's preferred Base32Lower multibase encoding (i.e. liberal in what we except, strict in what
/// we generate)
pub type EncodedVlad = BaseEncoded<Vlad, DetectedEncoder>;

/// A verifiable long-lived address (VLAD) represents an identifier for loosely
/// coupled distributed systems that combines a random unique idenitfier (none)
/// with the content address of a verification function in executable format.
/// A verifiable long-lived address (VLAD) represents an identifier for loosely coupled distributed
/// systems that combines a random unique idenitfier (none) with the content address of a
/// verification function in executable format.
///
/// The goal is to avoid the anti-pattern of using public keys as identifiers.
/// Public keys are chosen because they are random and unique enough to be
/// useful identifiers and are also a cryptographic commitment to a validation
/// function--the public key signature validation function. Using public keys
/// as an identifer is an anti-pattern because using key material means that
/// the identifiers are subject to compromise and must be rotated often to
/// maintain security so their "shelf-life" is limited. Rotating and/or
/// abandoning keys due to compromise causes the identifier to become invalid.
/// Any system that stores these identifiers then possesses broken links to
/// the value the identifier is associated with.
/// The goal is to avoid the anti-pattern of using public keys as identifiers. Public keys are
/// chosen because they are random and unique enough to be useful identifiers and are also a
/// cryptographic commitment to a validation function--the public key signature validation
/// function. Using public keys as an identifer is an anti-pattern because using key material means
/// that the identifiers are subject to compromise and must be rotated often to maintain security
/// so their "shelf-life" is limited. Rotating and/or abandoning keys due to compromise causes the
/// identifier to become invalid. Any system that stores these identifiers then possesses broken
/// links to the value the identifier is associated with.
///
/// The solution is to realize that we only need a random identifier and a
/// cryptographic commitment to a validation function to replace keys as
/// identifiers. VLADs meet those requirements.
/// The solution is to realize that we only need a random identifier and a cryptographic commitment
/// to a validation function to replace keys as identifiers. VLADs meet those requirements.
#[derive(Clone, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct Vlad {
/// the random nonce for uniqueness
Expand Down Expand Up @@ -203,6 +202,7 @@ mod tests {
use crate::cid;
use multihash::mh;
use multikey::EncodedMultikey;
use multiutil::base_name;

#[test]
fn test_default() {
Expand Down Expand Up @@ -295,6 +295,59 @@ mod tests {
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
}

#[test]
fn test_encodings_roundtrip() {
// build a nonce
let mut rng = rand::rngs::OsRng::default();
let nonce = nonce::Builder::new_from_random_bytes(32, &mut rng)
.try_build()
.unwrap();

// build a cid
let cid = cid::Builder::new(Codec::Cidv1)
.with_target_codec(Codec::DagCbor)
.with_hash(
&mh::Builder::new_from_bytes(Codec::Sha3512, b"for great justice, move every zig!")
.unwrap()
.try_build()
.unwrap(),
)
.try_build()
.unwrap();

let encodings = vec![
Base::Base2,
Base::Base8,
Base::Base10,
Base::Base16Lower,
Base::Base16Upper,
Base::Base32Lower,
Base::Base32Upper,
Base::Base32HexLower,
Base::Base32HexUpper,
Base::Base32Z,
Base::Base36Lower,
Base::Base36Upper,
Base::Base58Flickr,
Base::Base58Btc,
Base::Base64,
Base::Base64Url,
];

for encoding in encodings {
let vlad = Builder::default()
.with_nonce(&nonce)
.with_cid(&cid)
.with_base_encoding(encoding)
.try_build_encoded()
.unwrap();

let s = vlad.to_string();
println!("{}: ({}) {}", base_name(encoding), s.len(), s);
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
}
}

#[test]
fn test_signed_vlad() {
// build a cid
Expand All @@ -309,24 +362,26 @@ mod tests {
.try_build()
.unwrap();

let s = "zF3WX3Dwnv7jv2nPfYL6e2XaLdNyaiwkPyzEtgw65d872KYG22jezzuYPtrds8WSJ3Sv8SCA";
let s = "bhkasmcdumvzxiidlmv4qcaja42hlepmnedftr7ibzzo56qaswo6jvdmypljivo3b3imhjxqfnsvq";
let mk = EncodedMultikey::try_from(s).unwrap();

let vlad = Builder::default()
.with_signing_key(&mk)
.with_cid(&cid)
.with_base_encoding(Base::Base16Lower)
.with_base_encoding(Base::Base32Z)
.try_build_encoded()
.unwrap();

// make sure the signature checks out
assert_eq!((), vlad.verify(&mk).unwrap());
let s = vlad.to_string();
println!("({}) {}", s.len(), s);
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
//println!("BASE32Z ({}) {}", s.len(), s);
let de = EncodedVlad::try_from(s.as_str()).unwrap();
assert_eq!(vlad, de);
assert_eq!(Base::Base32Z, de.encoding());
let vlad = vlad.to_inner();
let v: Vec<u8> = vlad.clone().into();
println!("BLAH: {}", hex::encode(&v));
//println!("BLAH: {}", hex::encode(&v));
assert_eq!(vlad, Vlad::try_from(v.as_ref()).unwrap());
}

Expand Down

0 comments on commit a78080b

Please sign in to comment.