Skip to content

Commit a78080b

Browse files
committed
fix encoding bugs
Signed-off-by: Dave Huseby <[email protected]>
1 parent f042133 commit a78080b

File tree

3 files changed

+84
-28
lines changed

3 files changed

+84
-28
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "multicid"
3-
version = "1.0.1"
3+
version = "1.0.2"
44
edition = "2021"
55
authors = ["Dave Grantham <[email protected]>"]
66
description = "Multicodec compatible content identifier implementation"

src/cid.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ use multibase::Base;
55
use multicodec::Codec;
66
use multihash::Multihash;
77
use multitrait::{Null, TryDecodeFrom};
8-
use multiutil::{Base58Encoder, BaseEncoded, CodecInfo, EncodingInfo};
8+
use multiutil::{Base58Encoder, BaseEncoded, CodecInfo, DetectedEncoder, EncodingInfo};
99

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

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

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

1920
/// implementation of cid
2021
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq)]

src/vlad.rs

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,31 @@ use multicodec::Codec;
66
use multikey::{nonce, Multikey, Nonce, Views};
77
use multisig::Multisig;
88
use multitrait::{Null, TryDecodeFrom};
9-
use multiutil::{BaseEncoded, CodecInfo, EncodingInfo};
9+
use multiutil::{BaseEncoded, CodecInfo, DetectedEncoder, EncodingInfo};
1010

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

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

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

207207
#[test]
208208
fn test_default() {
@@ -295,6 +295,59 @@ mod tests {
295295
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
296296
}
297297

298+
#[test]
299+
fn test_encodings_roundtrip() {
300+
// build a nonce
301+
let mut rng = rand::rngs::OsRng::default();
302+
let nonce = nonce::Builder::new_from_random_bytes(32, &mut rng)
303+
.try_build()
304+
.unwrap();
305+
306+
// build a cid
307+
let cid = cid::Builder::new(Codec::Cidv1)
308+
.with_target_codec(Codec::DagCbor)
309+
.with_hash(
310+
&mh::Builder::new_from_bytes(Codec::Sha3512, b"for great justice, move every zig!")
311+
.unwrap()
312+
.try_build()
313+
.unwrap(),
314+
)
315+
.try_build()
316+
.unwrap();
317+
318+
let encodings = vec![
319+
Base::Base2,
320+
Base::Base8,
321+
Base::Base10,
322+
Base::Base16Lower,
323+
Base::Base16Upper,
324+
Base::Base32Lower,
325+
Base::Base32Upper,
326+
Base::Base32HexLower,
327+
Base::Base32HexUpper,
328+
Base::Base32Z,
329+
Base::Base36Lower,
330+
Base::Base36Upper,
331+
Base::Base58Flickr,
332+
Base::Base58Btc,
333+
Base::Base64,
334+
Base::Base64Url,
335+
];
336+
337+
for encoding in encodings {
338+
let vlad = Builder::default()
339+
.with_nonce(&nonce)
340+
.with_cid(&cid)
341+
.with_base_encoding(encoding)
342+
.try_build_encoded()
343+
.unwrap();
344+
345+
let s = vlad.to_string();
346+
println!("{}: ({}) {}", base_name(encoding), s.len(), s);
347+
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
348+
}
349+
}
350+
298351
#[test]
299352
fn test_signed_vlad() {
300353
// build a cid
@@ -309,24 +362,26 @@ mod tests {
309362
.try_build()
310363
.unwrap();
311364

312-
let s = "zF3WX3Dwnv7jv2nPfYL6e2XaLdNyaiwkPyzEtgw65d872KYG22jezzuYPtrds8WSJ3Sv8SCA";
365+
let s = "bhkasmcdumvzxiidlmv4qcaja42hlepmnedftr7ibzzo56qaswo6jvdmypljivo3b3imhjxqfnsvq";
313366
let mk = EncodedMultikey::try_from(s).unwrap();
314367

315368
let vlad = Builder::default()
316369
.with_signing_key(&mk)
317370
.with_cid(&cid)
318-
.with_base_encoding(Base::Base16Lower)
371+
.with_base_encoding(Base::Base32Z)
319372
.try_build_encoded()
320373
.unwrap();
321374

322375
// make sure the signature checks out
323376
assert_eq!((), vlad.verify(&mk).unwrap());
324377
let s = vlad.to_string();
325-
println!("({}) {}", s.len(), s);
326-
assert_eq!(vlad, EncodedVlad::try_from(s.as_str()).unwrap());
378+
//println!("BASE32Z ({}) {}", s.len(), s);
379+
let de = EncodedVlad::try_from(s.as_str()).unwrap();
380+
assert_eq!(vlad, de);
381+
assert_eq!(Base::Base32Z, de.encoding());
327382
let vlad = vlad.to_inner();
328383
let v: Vec<u8> = vlad.clone().into();
329-
println!("BLAH: {}", hex::encode(&v));
384+
//println!("BLAH: {}", hex::encode(&v));
330385
assert_eq!(vlad, Vlad::try_from(v.as_ref()).unwrap());
331386
}
332387

0 commit comments

Comments
 (0)