Add PublicKey{Map,Set} and make the Signature versions private.
This commit is contained in:
		
							parent
							
								
									593d0e469b
								
							
						
					
					
						commit
						daf160324c
					
				| @ -7,7 +7,7 @@ use ring::digest::{digest, SHA256}; | ||||
| use serde_json::{from_str, from_value, map::Map, to_string, to_value, Value}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     keys::KeyPair, | ||||
|     keys::{KeyPair, PublicKeyMap}, | ||||
|     signatures::SignatureMap, | ||||
|     split_id, | ||||
|     verification::{Ed25519Verifier, Verified, Verifier}, | ||||
| @ -95,7 +95,7 @@ static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "uns | ||||
| /// let mut value = serde_json::from_str("{}").unwrap();
 | ||||
| ///
 | ||||
| /// // Sign the JSON with the key pair.
 | ||||
| /// assert!(ruma_signatures::sign_json("example.com", &key_pair, &mut value).is_ok());
 | ||||
| /// assert!(ruma_signatures::sign_json("domain", &key_pair, &mut value).is_ok());
 | ||||
| /// ```
 | ||||
| ///
 | ||||
| /// This will modify the JSON from an empty object to a structure like this:
 | ||||
| @ -103,7 +103,7 @@ static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "uns | ||||
| /// ```json
 | ||||
| /// {
 | ||||
| ///     "signatures": {
 | ||||
| ///         "example.com": {
 | ||||
| ///         "domain": {
 | ||||
| ///             "ed25519:1": "K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"
 | ||||
| ///         }
 | ||||
| ///     }
 | ||||
| @ -209,23 +209,23 @@ pub fn canonical_json(value: &Value) -> Result<String, Error> { | ||||
| /// let value = serde_json::from_str(
 | ||||
| ///     r#"{
 | ||||
| ///         "signatures": {
 | ||||
| ///             "example.com": {
 | ||||
| ///             "domain": {
 | ||||
| ///                 "ed25519:1": "K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"
 | ||||
| ///             }
 | ||||
| ///         }
 | ||||
| ///     }"#
 | ||||
| /// ).unwrap();
 | ||||
| ///
 | ||||
| /// // Create the `SignatureMap` that will inform `verify_json` which signatures to verify.
 | ||||
| /// let mut signature_set = HashMap::new();
 | ||||
| /// signature_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string());
 | ||||
| /// // Create the `PublicKeyMap` that will inform `verify_json` which signatures to verify.
 | ||||
| /// let mut public_key_set = HashMap::new();
 | ||||
| /// public_key_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string());
 | ||||
| /// let mut public_key_map = HashMap::new();
 | ||||
| /// public_key_map.insert("example.com".to_string(), signature_set);
 | ||||
| /// public_key_map.insert("domain".to_string(), public_key_set);
 | ||||
| ///
 | ||||
| /// // Verify at least one signature for each entity in `public_key_map`.
 | ||||
| /// assert!(ruma_signatures::verify_json(&public_key_map, &value).is_ok());
 | ||||
| /// ```
 | ||||
| pub fn verify_json(public_key_map: &SignatureMap, value: &Value) -> Result<(), Error> { | ||||
| pub fn verify_json(public_key_map: &PublicKeyMap, value: &Value) -> Result<(), Error> { | ||||
|     let map = match value { | ||||
|         Value::Object(ref map) => map, | ||||
|         _ => return Err(Error::new("JSON value must be a JSON object")), | ||||
| @ -431,7 +431,7 @@ pub fn reference_hash(value: &Value) -> Result<String, Error> { | ||||
| /// ).unwrap();
 | ||||
| ///
 | ||||
| /// // Hash and sign the JSON with the key pair.
 | ||||
| /// assert!(ruma_signatures::hash_and_sign_event("example.com", &key_pair, &mut value).is_ok());
 | ||||
| /// assert!(ruma_signatures::hash_and_sign_event("domain", &key_pair, &mut value).is_ok());
 | ||||
| /// ```
 | ||||
| ///
 | ||||
| /// This will modify the JSON from the structure shown to a structure like this:
 | ||||
| @ -549,18 +549,16 @@ where | ||||
| ///     }"#
 | ||||
| /// ).unwrap();
 | ||||
| ///
 | ||||
| /// // Create a map from key ID to public key.
 | ||||
| /// let mut example_server_keys = HashMap::new();
 | ||||
| /// example_server_keys.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string());
 | ||||
| ///
 | ||||
| /// // Insert the public keys into a map keyed by entity ID.
 | ||||
| /// // Create the `PublicKeyMap` that will inform `verify_json` which signatures to verify.
 | ||||
| /// let mut public_key_set = HashMap::new();
 | ||||
| /// public_key_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string());
 | ||||
| /// let mut public_key_map = HashMap::new();
 | ||||
| /// public_key_map.insert("domain".to_string(), example_server_keys);
 | ||||
| /// public_key_map.insert("domain".to_string(), public_key_set);
 | ||||
| ///
 | ||||
| /// // Verify at least one signature for each entity in `public_key_map`.
 | ||||
| /// assert!(ruma_signatures::verify_event(&public_key_map, &value).is_ok());
 | ||||
| /// ```
 | ||||
| pub fn verify_event(public_key_map: &SignatureMap, value: &Value) -> Result<Verified, Error> { | ||||
| pub fn verify_event(public_key_map: &PublicKeyMap, value: &Value) -> Result<Verified, Error> { | ||||
|     let redacted = redact(value)?; | ||||
| 
 | ||||
|     let map = match redacted { | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/keys.rs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/keys.rs
									
									
									
									
									
								
							| @ -1,6 +1,9 @@ | ||||
| //! Public and private key pairs.
 | ||||
| 
 | ||||
| use std::fmt::{Debug, Formatter, Result as FmtResult}; | ||||
| use std::{ | ||||
|     collections::HashMap, | ||||
|     fmt::{Debug, Formatter, Result as FmtResult}, | ||||
| }; | ||||
| 
 | ||||
| use ring::signature::Ed25519KeyPair as RingEd25519KeyPair; | ||||
| use untrusted::Input; | ||||
| @ -87,3 +90,13 @@ impl Debug for Ed25519KeyPair { | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A map from entity names to sets of public keys for that entity.
 | ||||
| ///
 | ||||
| /// "Entity" is generally a homeserver, e.g. "example.com".
 | ||||
| pub type PublicKeyMap = HashMap<String, PublicKeySet>; | ||||
| 
 | ||||
| /// A set of public keys for a single homeserver.
 | ||||
| ///
 | ||||
| /// This is represented as a map from key ID to Base64-encoded signature.
 | ||||
| pub type PublicKeySet = HashMap<String, String>; | ||||
|  | ||||
							
								
								
									
										30
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -104,8 +104,8 @@ pub use functions::{ | ||||
|     canonical_json, content_hash, hash_and_sign_event, redact, reference_hash, sign_json, | ||||
|     verify_event, verify_json, | ||||
| }; | ||||
| pub use keys::{Ed25519KeyPair, KeyPair}; | ||||
| pub use signatures::{Signature, SignatureMap, SignatureSet}; | ||||
| pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet}; | ||||
| pub use signatures::Signature; | ||||
| 
 | ||||
| mod functions; | ||||
| mod keys; | ||||
| @ -350,23 +350,23 @@ mod test { | ||||
| 
 | ||||
|         let mut value = from_str("{}").unwrap(); | ||||
| 
 | ||||
|         sign_json("example.com", &key_pair, &mut value).unwrap(); | ||||
|         sign_json("domain", &key_pair, &mut value).unwrap(); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             to_string(&value).unwrap(), | ||||
|             r#"{"signatures":{"example.com":{"ed25519:1":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}}"# | ||||
|             r#"{"signatures":{"domain":{"ed25519:1":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}}"# | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn verify_empty_json() { | ||||
|         let value = from_str(r#"{"signatures":{"example.com":{"ed25519:1":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}}"#).unwrap(); | ||||
|         let value = from_str(r#"{"signatures":{"domain":{"ed25519:1":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}}"#).unwrap(); | ||||
| 
 | ||||
|         let mut signature_set = HashMap::new(); | ||||
|         signature_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string()); | ||||
| 
 | ||||
|         let mut public_key_map = HashMap::new(); | ||||
|         public_key_map.insert("example.com".to_string(), signature_set); | ||||
|         public_key_map.insert("domain".to_string(), signature_set); | ||||
| 
 | ||||
|         assert!(verify_json(&public_key_map, &value).is_ok()); | ||||
|     } | ||||
| @ -407,39 +407,39 @@ mod test { | ||||
|         }; | ||||
| 
 | ||||
|         let mut alpha_value = to_value(alpha).expect("alpha should serialize"); | ||||
|         sign_json("example.com", &key_pair, &mut alpha_value).unwrap(); | ||||
|         sign_json("domain", &key_pair, &mut alpha_value).unwrap(); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             to_string(&alpha_value).unwrap(), | ||||
|             r#"{"one":1,"signatures":{"example.com":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|             r#"{"one":1,"signatures":{"domain":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|         ); | ||||
| 
 | ||||
|         let mut reverse_alpha_value = | ||||
|             to_value(reverse_alpha).expect("reverse_alpha should serialize"); | ||||
|         sign_json("example.com", &key_pair, &mut reverse_alpha_value).unwrap(); | ||||
|         sign_json("domain", &key_pair, &mut reverse_alpha_value).unwrap(); | ||||
| 
 | ||||
|         assert_eq!( | ||||
|             to_string(&reverse_alpha_value).unwrap(), | ||||
|             r#"{"one":1,"signatures":{"example.com":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|             r#"{"one":1,"signatures":{"domain":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn verify_minimal_json() { | ||||
|         let value = from_str( | ||||
|             r#"{"one":1,"signatures":{"example.com":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|             r#"{"one":1,"signatures":{"domain":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"two":"Two"}"# | ||||
|         ).unwrap(); | ||||
| 
 | ||||
|         let mut signature_set = HashMap::new(); | ||||
|         signature_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string()); | ||||
| 
 | ||||
|         let mut public_key_map = HashMap::new(); | ||||
|         public_key_map.insert("example.com".to_string(), signature_set); | ||||
|         public_key_map.insert("domain".to_string(), signature_set); | ||||
| 
 | ||||
|         assert!(verify_json(&public_key_map, &value).is_ok()); | ||||
| 
 | ||||
|         let reverse_value = from_str( | ||||
|             r#"{"two":"Two","signatures":{"example.com":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"one":1}"# | ||||
|             r#"{"two":"Two","signatures":{"domain":{"ed25519:1":"KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"}},"one":1}"# | ||||
|         ).unwrap(); | ||||
| 
 | ||||
|         assert!(verify_json(&public_key_map, &reverse_value).is_ok()); | ||||
| @ -447,13 +447,13 @@ mod test { | ||||
| 
 | ||||
|     #[test] | ||||
|     fn fail_verify_json() { | ||||
|         let value = from_str(r#"{"not":"empty","signatures":{"example.com":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}"#).unwrap(); | ||||
|         let value = from_str(r#"{"not":"empty","signatures":{"domain":"K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"}}"#).unwrap(); | ||||
| 
 | ||||
|         let mut signature_set = HashMap::new(); | ||||
|         signature_set.insert("ed25519:1".to_string(), PUBLIC_KEY.to_string()); | ||||
| 
 | ||||
|         let mut public_key_map = HashMap::new(); | ||||
|         public_key_map.insert("example.com".to_string(), signature_set); | ||||
|         public_key_map.insert("domain".to_string(), signature_set); | ||||
| 
 | ||||
|         assert!(verify_json(&public_key_map, &value).is_err()); | ||||
|     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user