diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index 4a139e79f..605baddad 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -250,7 +250,12 @@ object LocalPreferences { val prefs = encryptedPreferences(account.userProfile().pubkeyNpub()) prefs.edit().apply { - account.keyPair.privKey?.let { putString(PrefKeys.NOSTR_PRIVKEY, it.toHexKey()) } + putBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, account.loginWithExternalSigner) + if (account.loginWithExternalSigner) { + remove(PrefKeys.NOSTR_PRIVKEY) + } else { + account.keyPair.privKey?.let { putString(PrefKeys.NOSTR_PRIVKEY, it.toHexKey()) } + } account.keyPair.pubKey.let { putString(PrefKeys.NOSTR_PUBKEY, it.toHexKey()) } putStringSet(PrefKeys.FOLLOWING_CHANNELS, account.followingChannels) putStringSet(PrefKeys.FOLLOWING_COMMUNITIES, account.followingCommunities) @@ -283,7 +288,6 @@ object LocalPreferences { } else { putBoolean(PrefKeys.SHOW_SENSITIVE_CONTENT, account.showSensitiveContent!!) } - putBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, account.loginWithExternalSigner) }.apply() } @@ -381,7 +385,8 @@ object LocalPreferences { return@withContext with(encryptedPreferences(npub)) { val pubKey = getString(PrefKeys.NOSTR_PUBKEY, null) ?: return@with null - val privKey = getString(PrefKeys.NOSTR_PRIVKEY, null) + val loginWithExternalSigner = getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false) + val privKey = if (loginWithExternalSigner) null else getString(PrefKeys.NOSTR_PRIVKEY, null) val followingChannels = getStringSet(PrefKeys.FOLLOWING_CHANNELS, null) ?: setOf() val followingCommunities = getStringSet(PrefKeys.FOLLOWING_COMMUNITIES, null) ?: setOf() val hiddenUsers = getStringSet(PrefKeys.HIDDEN_USERS, emptySet()) ?: setOf() @@ -453,7 +458,6 @@ object LocalPreferences { val useProxy = getBoolean(PrefKeys.USE_PROXY, false) val proxyPort = getInt(PrefKeys.PROXY_PORT, 9050) val proxy = HttpClient.initProxy(useProxy, "127.0.0.1", proxyPort) - val loginWithExternalSigner = getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false) val showSensitiveContent = if (contains(PrefKeys.SHOW_SENSITIVE_CONTENT)) { getBoolean(PrefKeys.SHOW_SENSITIVE_CONTENT, false) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 621854c88..2d71ed1be 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -1532,40 +1532,51 @@ class Account( val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null } val mentionsHex = mentions?.map { it.pubkeyHex } - var localMessage = message if (loginWithExternalSigner) { - ExternalSignerUtils.encrypt(localMessage, toUser, "encrypt") + ExternalSignerUtils.encrypt(message, toUser, "encrypt") val eventContent = ExternalSignerUtils.content["encrypt"] ?: "" if (eventContent.isBlank()) return - localMessage = eventContent ExternalSignerUtils.content.remove("encrypt") - } + val unsignedEvent = PrivateDmEvent.create( + recipientPubKey = toUser.hexToByteArray(), + publishedRecipientPubKey = toUser.hexToByteArray(), + msg = eventContent, + replyTos = repliesToHex, + mentions = mentionsHex, + zapReceiver = zapReceiver, + markAsSensitive = wantsToMarkAsSensitive, + zapRaiserAmount = zapRaiserAmount, + geohash = geohash, + keyPair = keyPair, + advertiseNip18 = false + ) - var signedEvent = PrivateDmEvent.create( - recipientPubKey = toUser.hexToByteArray(), - publishedRecipientPubKey = toUser.hexToByteArray(), - msg = localMessage, - replyTos = repliesToHex, - mentions = mentionsHex, - zapReceiver = zapReceiver, - markAsSensitive = wantsToMarkAsSensitive, - zapRaiserAmount = zapRaiserAmount, - geohash = geohash, - keyPair = keyPair, - advertiseNip18 = false - ) - - if (loginWithExternalSigner) { - ExternalSignerUtils.openSigner(signedEvent) - val eventContent = ExternalSignerUtils.content[signedEvent.id] ?: "" - if (eventContent.isBlank()) { + ExternalSignerUtils.openSigner(unsignedEvent) + val signature = ExternalSignerUtils.content[unsignedEvent.id] ?: "" + if (signature.isBlank()) { return } - signedEvent = PrivateDmEvent.create(signedEvent, eventContent) - } + val signedEvent = PrivateDmEvent.create(unsignedEvent, signature) + Client.send(signedEvent) + LocalCache.consume(signedEvent, null) + } else { + val signedEvent = PrivateDmEvent.create( + recipientPubKey = toUser.hexToByteArray(), + publishedRecipientPubKey = toUser.hexToByteArray(), + msg = message, + replyTos = repliesToHex, + mentions = mentionsHex, + zapReceiver = zapReceiver, + markAsSensitive = wantsToMarkAsSensitive, + zapRaiserAmount = zapRaiserAmount, + geohash = geohash, + keyPair = keyPair, + advertiseNip18 = false + ) - Client.send(signedEvent) - LocalCache.consume(signedEvent, null) + Client.send(signedEvent) + LocalCache.consume(signedEvent, null) + } } fun sendNIP24PrivateMessage( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index e0cbc2cca..61ffed82a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -55,16 +55,22 @@ class AccountStateViewModel() : ViewModel() { val pubKeyParsed = parsed?.hex?.hexToByteArray() val proxy = HttpClient.initProxy(useProxy, "127.0.0.1", proxyPort) + if (loginWithExternalSigner && pubKeyParsed == null) { + throw Exception("Invalid key while trying to login with external signer") + } + val account = - if (key.startsWith("nsec")) { - Account(KeyPair(privKey = key.bechToBytes()), proxy = proxy, proxyPort = proxyPort, loginWithExternalSigner = loginWithExternalSigner) + if (loginWithExternalSigner) { + Account(KeyPair(pubKey = pubKeyParsed), proxy = proxy, proxyPort = proxyPort, loginWithExternalSigner = true) + } else if (key.startsWith("nsec")) { + Account(KeyPair(privKey = key.bechToBytes()), proxy = proxy, proxyPort = proxyPort) } else if (pubKeyParsed != null) { - Account(KeyPair(pubKey = pubKeyParsed), proxy = proxy, proxyPort = proxyPort, loginWithExternalSigner = loginWithExternalSigner) + Account(KeyPair(pubKey = pubKeyParsed), proxy = proxy, proxyPort = proxyPort) } else if (EMAIL_PATTERN.matcher(key).matches()) { // Evaluate NIP-5 - Account(KeyPair(), proxy = proxy, proxyPort = proxyPort, loginWithExternalSigner = loginWithExternalSigner) + Account(KeyPair(), proxy = proxy, proxyPort = proxyPort) } else { - Account(KeyPair(Hex.decode(key)), proxy = proxy, proxyPort = proxyPort, loginWithExternalSigner = loginWithExternalSigner) + Account(KeyPair(Hex.decode(key)), proxy = proxy, proxyPort = proxyPort) } LocalPreferences.updatePrefsForLogin(account) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt index 261ed0f4c..02af9953a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/PrivateDmEvent.kt @@ -130,6 +130,49 @@ class PrivateDmEvent( return PrivateDmEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") } + fun createWithoutSignature( + msg: String, + replyTos: List? = null, + mentions: List? = null, + zapReceiver: List? = null, + keyPair: KeyPair, + createdAt: Long = TimeUtils.now(), + publishedRecipientPubKey: ByteArray? = null, + advertiseNip18: Boolean = true, + markAsSensitive: Boolean, + zapRaiserAmount: Long?, + geohash: String? = null + ): PrivateDmEvent { + val message = if (advertiseNip18) { nip18Advertisement } else { "" } + msg + val content = message + val tags = mutableListOf>() + publishedRecipientPubKey?.let { + tags.add(listOf("p", publishedRecipientPubKey.toHexKey())) + } + replyTos?.forEach { + tags.add(listOf("e", it)) + } + mentions?.forEach { + tags.add(listOf("p", it)) + } + zapReceiver?.forEach { + tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) + } + if (markAsSensitive) { + tags.add(listOf("content-warning", "")) + } + zapRaiserAmount?.let { + tags.add(listOf("zapraiser", "$it")) + } + geohash?.let { + tags.add(listOf("g", it)) + } + + val pubKey = keyPair.pubKey.toHexKey() + val id = generateId(pubKey, createdAt, kind, tags, content) + return PrivateDmEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") + } + fun create( unsignedEvent: PrivateDmEvent, signature: String,