Rust and WASM did-method-plc tools and structures

fix: fix did derivation and signature generation.

This fixes two bugs that were affecting did derivation and signature
generation.

- The `UnsignedOperation` and `Operation` types were not serializing
prev as `null` and were instead skipping serialization when it was
`None`.
- The DID was being calculated from the hash of the JSON encoding
instead of the CBOR encoding.

Changed files
+6 -8
src
+3 -3
src/builder.rs
··· 3 use crate::crypto::SigningKey; 4 use crate::did::Did; 5 use crate::document::ServiceEndpoint; 6 - use crate::encoding::{base32_encode, sha256}; 7 use crate::error::{PlcError, Result}; 8 use crate::operations::{Operation, UnsignedOperation}; 9 use crate::validation::{ ··· 229 230 // The DID is derived from the CID by taking the hash portion 231 // For simplicity, we'll hash the entire serialized operation 232 - let serialized = serde_json::to_vec(operation) 233 - .map_err(|e| PlcError::DagCborError(e.to_string()))?; 234 235 let hash = sha256(&serialized); 236 let encoded = base32_encode(&hash);
··· 3 use crate::crypto::SigningKey; 4 use crate::did::Did; 5 use crate::document::ServiceEndpoint; 6 + use crate::encoding::{base32_encode, dag_cbor_encode, sha256}; 7 use crate::error::{PlcError, Result}; 8 use crate::operations::{Operation, UnsignedOperation}; 9 use crate::validation::{ ··· 229 230 // The DID is derived from the CID by taking the hash portion 231 // For simplicity, we'll hash the entire serialized operation 232 + let serialized = 233 + dag_cbor_encode(operation).map_err(|e| PlcError::DagCborError(e.to_string()))?; 234 235 let hash = sha256(&serialized); 236 let encoded = base32_encode(&hash);
+3 -5
src/operations.rs
··· 30 services: HashMap<String, ServiceEndpoint>, 31 32 /// Previous operation CID (null for genesis) 33 - #[serde(skip_serializing_if = "Option::is_none")] 34 prev: Option<String>, 35 36 /// Base64url-encoded signature ··· 193 services: services.clone(), 194 prev: prev.clone(), 195 }, 196 - Operation::PlcTombstone { prev, .. } => UnsignedOperation::PlcTombstone { 197 - prev: prev.clone(), 198 - }, 199 Operation::LegacyCreate { 200 signing_key, 201 recovery_key, ··· 247 services: HashMap<String, ServiceEndpoint>, 248 249 /// CID of previous operation (None for genesis) 250 - #[serde(skip_serializing_if = "Option::is_none")] 251 prev: Option<String>, 252 }, 253
··· 30 services: HashMap<String, ServiceEndpoint>, 31 32 /// Previous operation CID (null for genesis) 33 prev: Option<String>, 34 35 /// Base64url-encoded signature ··· 192 services: services.clone(), 193 prev: prev.clone(), 194 }, 195 + Operation::PlcTombstone { prev, .. } => { 196 + UnsignedOperation::PlcTombstone { prev: prev.clone() } 197 + } 198 Operation::LegacyCreate { 199 signing_key, 200 recovery_key, ··· 246 services: HashMap<String, ServiceEndpoint>, 247 248 /// CID of previous operation (None for genesis) 249 prev: Option<String>, 250 }, 251