11use anyhow:: { Context , Result , anyhow} ;
22use auths_sdk:: attestation:: create_signed_attestation;
33use auths_sdk:: attestation:: create_signed_revocation;
4- use auths_sdk:: crypto:: decrypt_keypair;
54use auths_sdk:: identity:: DidResolver ;
65use auths_sdk:: identity:: initialize_registry_identity;
76use chrono:: { DateTime , Utc } ;
@@ -439,7 +438,7 @@ pub fn handle_org(
439438 serde_json:: from_str ( & payload_str) . context ( "Invalid JSON in payload file" ) ?;
440439
441440 let key_storage = get_platform_keychain ( ) ?;
442- let ( stored_did, _role, encrypted_key ) = key_storage
441+ let ( stored_did, _role, _encrypted_key ) = key_storage
443442 . load_key ( & signer_alias)
444443 . with_context ( || format ! ( "Failed to load signer key '{}'" , signer_alias) ) ?;
445444
@@ -452,13 +451,6 @@ pub fn handle_org(
452451 ) ) ;
453452 }
454453
455- let passphrase = passphrase_provider. get_passphrase ( & format ! (
456- "Enter passphrase for org identity key '{}':" ,
457- signer_alias
458- ) ) ?;
459- let _pkcs8_bytes = decrypt_keypair ( & encrypted_key, & passphrase)
460- . context ( "Failed to decrypt signer key (invalid passphrase?)" ) ?;
461-
462454 #[ allow( clippy:: disallowed_methods) ]
463455 // INVARIANT: subject_did accepts both did:key and did:keri
464456 let subject_device_did = DeviceDID :: new_unchecked ( subject_did. clone ( ) ) ;
@@ -538,17 +530,6 @@ pub fn handle_org(
538530 let controller_did = managed_identity. controller_did ;
539531 let rid = managed_identity. storage_id ;
540532
541- let encrypted_key = get_platform_keychain ( ) ?
542- . load_key ( & signer_alias)
543- . context ( "Failed to load signer key" ) ?
544- . 2 ;
545- let pass = passphrase_provider. get_passphrase ( & format ! (
546- "Enter passphrase for identity key '{}':" ,
547- signer_alias
548- ) ) ?;
549- let _pkcs8_bytes =
550- decrypt_keypair ( & encrypted_key, & pass) . context ( "Failed to decrypt identity key" ) ?;
551-
552533 #[ allow( clippy:: disallowed_methods) ] // INVARIANT: accepts both did:key and did:keri
553534 let subject_device_did = DeviceDID :: new_unchecked ( subject_did. clone ( ) ) ;
554535
@@ -965,13 +946,30 @@ pub fn handle_org(
965946 Ok ( ( ) )
966947 }
967948
968- OrgSubcommand :: Join { code, registry } => handle_join ( & code, & registry) ,
949+ OrgSubcommand :: Join { code, registry } => {
950+ handle_join ( & code, & registry, passphrase_provider. as_ref ( ) )
951+ }
969952 }
970953}
971954
972955/// Handles the `org join` subcommand by looking up and accepting an invite
973956/// via the registry HTTP API.
974- fn handle_join ( code : & str , registry : & str ) -> Result < ( ) > {
957+ ///
958+ /// Args:
959+ /// * `code`: Invite code to redeem.
960+ /// * `registry`: Base URL of the registry HTTP API.
961+ /// * `passphrase_provider`: Injected provider used to unlock the signing key
962+ /// when producing the bearer token; respects SE-backed and P-256 keys.
963+ ///
964+ /// Usage:
965+ /// ```ignore
966+ /// handle_join(&code, ®istry, ctx.passphrase_provider.as_ref())?;
967+ /// ```
968+ fn handle_join (
969+ code : & str ,
970+ registry : & str ,
971+ passphrase_provider : & dyn auths_sdk:: signing:: PassphraseProvider ,
972+ ) -> Result < ( ) > {
975973 let rt = tokio:: runtime:: Runtime :: new ( ) ?;
976974 let client = reqwest:: Client :: new ( ) ;
977975 let base = registry. trim_end_matches ( '/' ) ;
@@ -1024,30 +1022,21 @@ fn handle_join(code: &str, registry: &str) -> Result<()> {
10241022
10251023 let key_storage = get_platform_keychain ( ) ?;
10261024 let primary_alias = KeyAlias :: new_unchecked ( "main" ) ;
1027- let ( _stored_did, _role, encrypted_key) = key_storage
1028- . load_key ( & primary_alias)
1029- . context ( "failed to load signing key — run `auths init` first" ) ?;
1030-
1031- let passphrase =
1032- rpassword:: prompt_password ( "Enter passphrase: " ) . context ( "failed to read passphrase" ) ?;
1033- let pkcs8_bytes = decrypt_keypair ( & encrypted_key, & passphrase) . context ( "wrong passphrase" ) ?;
10341025
1035- let pkcs8 = auths_crypto:: Pkcs8Der :: new ( & pkcs8_bytes[ ..] ) ;
1036- let seed = auths_sdk:: crypto:: extract_seed_from_pkcs8 ( & pkcs8)
1037- . context ( "failed to extract seed from key material" ) ?;
1038-
1039- // Create a signed bearer payload: { did, timestamp, signature }
10401026 #[ allow( clippy:: disallowed_methods) ] // CLI is the presentation boundary
10411027 let timestamp = Utc :: now ( ) . to_rfc3339 ( ) ;
10421028 let message = format ! ( "{}\n {}" , did, timestamp) ;
1043- let signature = {
1044- use ring:: signature:: Ed25519KeyPair ;
1045- let kp = Ed25519KeyPair :: from_seed_unchecked ( seed. as_bytes ( ) )
1046- . map_err ( |e| anyhow ! ( "invalid key: {e}" ) ) ?;
1047- let sig = kp. sign ( message. as_bytes ( ) ) ;
1048- use base64:: Engine ;
1049- base64:: engine:: general_purpose:: STANDARD . encode ( sig. as_ref ( ) )
1050- } ;
1029+
1030+ let ( sig_bytes, _pubkey, _curve) = auths_sdk:: keychain:: sign_with_key (
1031+ key_storage. as_ref ( ) ,
1032+ & primary_alias,
1033+ passphrase_provider,
1034+ message. as_bytes ( ) ,
1035+ )
1036+ . context ( "failed to sign invite bearer token" ) ?;
1037+
1038+ use base64:: Engine ;
1039+ let signature = base64:: engine:: general_purpose:: STANDARD . encode ( & sig_bytes) ;
10511040
10521041 let bearer_payload = serde_json:: json!( {
10531042 "did" : did,
0 commit comments