1
1
//! Nostr MLS Key Packages
2
2
3
3
use nostr:: util:: hex;
4
- use nostr:: { Event , EventBuilder , Kind , NostrSigner , PublicKey , RelayUrl , Tag , TagKind } ;
4
+ use nostr:: { Event , Kind , PublicKey , RelayUrl , Tag , TagKind } ;
5
5
use nostr_mls_storage:: NostrMlsStorageProvider ;
6
6
use openmls:: key_packages:: KeyPackage ;
7
7
use openmls:: prelude:: * ;
@@ -18,20 +18,29 @@ where
18
18
{
19
19
/// Creates a key package for a Nostr event.
20
20
///
21
- /// This function generates a key package that can be used in a Nostr event to join an MLS group .
21
+ /// This function generates a hex-encoded key package that is used as the content field of a kind:443 Nostr event .
22
22
/// The key package contains the user's credential and capabilities required for MLS operations.
23
23
///
24
24
/// # Returns
25
25
///
26
- /// A hex-encoded string containing the serialized key package on success, or a KeyPackageError on failure.
26
+ /// A tuple containing:
27
+ /// * A hex-encoded string containing the serialized key package
28
+ /// * A tuple of tags for the Nostr event
27
29
///
28
30
/// # Errors
29
31
///
30
32
/// This function will return an error if:
31
33
/// * It fails to generate the credential and signature keypair
32
34
/// * It fails to build the key package
33
35
/// * It fails to serialize the key package
34
- fn create_key_package_for_event ( & self , public_key : & PublicKey ) -> Result < String , Error > {
36
+ pub fn create_key_package_for_event < I > (
37
+ & self ,
38
+ public_key : & PublicKey ,
39
+ relays : I ,
40
+ ) -> Result < ( String , [ Tag ; 5 ] ) , Error >
41
+ where
42
+ I : IntoIterator < Item = RelayUrl > ,
43
+ {
35
44
let ( credential, signature_keypair) = self . generate_credential_with_key ( public_key) ?;
36
45
37
46
let capabilities: Capabilities = self . capabilities ( ) ;
@@ -46,37 +55,20 @@ where
46
55
credential,
47
56
) ?;
48
57
49
- // serialize the key package, then encode it to hex and put it in the content field
50
58
let key_package_serialized = key_package_bundle. key_package ( ) . tls_serialize_detached ( ) ?;
51
59
52
- Ok ( hex:: encode ( key_package_serialized) )
53
- }
54
-
55
- /// Create key package [`Event`]
56
- pub async fn create_key_package < T , I > ( & self , signer : & T , relays : I ) -> Result < Event , Error >
57
- where
58
- T : NostrSigner ,
59
- I : IntoIterator < Item = RelayUrl > ,
60
- {
61
- let public_key: PublicKey = signer. get_public_key ( ) . await ?;
62
-
63
- let serialized_key_package: String = self . create_key_package_for_event ( & public_key) ?;
64
-
65
- let ciphersuite: String = self . ciphersuite_value ( ) . to_string ( ) ;
66
- let extensions: String = self . extensions_value ( ) ;
67
-
68
60
let tags = [
69
61
Tag :: custom ( TagKind :: MlsProtocolVersion , [ "1.0" ] ) ,
70
- Tag :: custom ( TagKind :: MlsCiphersuite , [ ciphersuite] ) ,
71
- Tag :: custom ( TagKind :: MlsExtensions , [ extensions] ) ,
62
+ Tag :: custom (
63
+ TagKind :: MlsCiphersuite ,
64
+ [ self . ciphersuite_value ( ) . to_string ( ) ] ,
65
+ ) ,
66
+ Tag :: custom ( TagKind :: MlsExtensions , [ self . extensions_value ( ) ] ) ,
72
67
Tag :: relays ( relays) ,
73
68
Tag :: protected ( ) ,
74
69
] ;
75
70
76
- let builder: EventBuilder =
77
- EventBuilder :: new ( Kind :: MlsKeyPackage , serialized_key_package) . tags ( tags) ;
78
-
79
- Ok ( builder. sign ( signer) . await ?)
71
+ Ok ( ( hex:: encode ( key_package_serialized) , tags) )
80
72
}
81
73
82
74
/// Parses and validates a hex-encoded key package.
@@ -196,10 +188,11 @@ mod tests {
196
188
let test_pubkey =
197
189
PublicKey :: from_hex ( "884704bd421671e01c13f854d2ce23ce2a5bfe9562f4f297ad2bc921ba30c3a6" )
198
190
. unwrap ( ) ;
191
+ let relays = vec ! [ RelayUrl :: parse( "wss://relay.example.com" ) . unwrap( ) ] ;
199
192
200
193
// Create key package
201
- let key_package_hex = nostr_mls
202
- . create_key_package_for_event ( & test_pubkey)
194
+ let ( key_package_hex, tags ) = nostr_mls
195
+ . create_key_package_for_event ( & test_pubkey, relays . clone ( ) )
203
196
. expect ( "Failed to create key package" ) ;
204
197
205
198
// Create new instance for parsing
@@ -212,6 +205,22 @@ mod tests {
212
205
213
206
// Verify the key package has the expected properties
214
207
assert_eq ! ( key_package. ciphersuite( ) , DEFAULT_CIPHERSUITE ) ;
208
+
209
+ assert_eq ! ( tags. len( ) , 5 ) ;
210
+ assert_eq ! ( tags[ 0 ] . kind( ) , TagKind :: MlsProtocolVersion ) ;
211
+ assert_eq ! ( tags[ 1 ] . kind( ) , TagKind :: MlsCiphersuite ) ;
212
+ assert_eq ! ( tags[ 2 ] . kind( ) , TagKind :: MlsExtensions ) ;
213
+ assert_eq ! ( tags[ 3 ] . kind( ) , TagKind :: Relays ) ;
214
+ assert_eq ! ( tags[ 4 ] . kind( ) , TagKind :: Protected ) ;
215
+
216
+ assert_eq ! (
217
+ tags[ 3 ] . content( ) . unwrap( ) ,
218
+ relays
219
+ . iter( )
220
+ . map( |r| r. to_string( ) )
221
+ . collect:: <Vec <_>>( )
222
+ . join( "," )
223
+ ) ;
215
224
}
216
225
217
226
#[ test]
@@ -221,9 +230,11 @@ mod tests {
221
230
PublicKey :: from_hex ( "884704bd421671e01c13f854d2ce23ce2a5bfe9562f4f297ad2bc921ba30c3a6" )
222
231
. unwrap ( ) ;
223
232
233
+ let relays = vec ! [ RelayUrl :: parse( "wss://relay.example.com" ) . unwrap( ) ] ;
234
+
224
235
// Create and parse key package
225
- let key_package_hex = nostr_mls
226
- . create_key_package_for_event ( & test_pubkey)
236
+ let ( key_package_hex, _ ) = nostr_mls
237
+ . create_key_package_for_event ( & test_pubkey, relays . clone ( ) )
227
238
. expect ( "Failed to create key package" ) ;
228
239
229
240
// Create new instance for parsing and deletion
0 commit comments