mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 05:25:20 +00:00
fix nip-17 (#305)
* NIP-59 stuff * nip-17 ios to androing works, android to ios still wip * fix impl * ios compat * default relays for DMs * delivery ack works * delivery ack --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
This commit is contained in:
@@ -14,46 +14,42 @@ object NostrProtocol {
|
||||
private val gson = Gson()
|
||||
|
||||
/**
|
||||
* Create a NIP-17 private message
|
||||
* Returns gift-wrapped event ready for relay broadcast
|
||||
* Create NIP-17 private message gift-wrap (receiver copy only per iOS)
|
||||
* Returns a single gift-wrapped event ready for relay broadcast
|
||||
*/
|
||||
fun createPrivateMessage(
|
||||
content: String,
|
||||
recipientPubkey: String,
|
||||
senderIdentity: NostrIdentity
|
||||
): NostrEvent {
|
||||
Log.v(TAG, "Creating private message for recipient: ${recipientPubkey.take(16)}...")
|
||||
): List<NostrEvent> {
|
||||
Log.d(TAG, "Creating private message for recipient: ${recipientPubkey.take(16)}...")
|
||||
|
||||
// 1. Create the rumor (unsigned event)
|
||||
val rumor = NostrEvent(
|
||||
// 1. Create the rumor (unsigned kind 14) with p-tag
|
||||
val rumorBase = NostrEvent(
|
||||
pubkey = senderIdentity.publicKeyHex,
|
||||
createdAt = (System.currentTimeMillis() / 1000).toInt(),
|
||||
kind = NostrKind.TEXT_NOTE,
|
||||
tags = emptyList(),
|
||||
kind = NostrKind.DIRECT_MESSAGE,
|
||||
tags = listOf(listOf("p", recipientPubkey)),
|
||||
content = content
|
||||
)
|
||||
val rumorId = rumorBase.computeEventIdHex()
|
||||
val rumor = rumorBase.copy(id = rumorId)
|
||||
|
||||
// 2. Create ephemeral key for this message
|
||||
val (ephemeralPrivateKey, ephemeralPublicKey) = NostrCrypto.generateKeyPair()
|
||||
Log.v(TAG, "Created ephemeral key for seal")
|
||||
|
||||
// 3. Seal the rumor (encrypt to recipient)
|
||||
// 2. Seal the rumor (kind 13) signed by sender, timestamp randomized up to 2 days
|
||||
val sealedEvent = createSeal(
|
||||
rumor = rumor,
|
||||
recipientPubkey = recipientPubkey,
|
||||
senderPrivateKey = ephemeralPrivateKey,
|
||||
senderPublicKey = ephemeralPublicKey
|
||||
senderPrivateKey = senderIdentity.privateKeyHex,
|
||||
senderPublicKey = senderIdentity.publicKeyHex
|
||||
)
|
||||
|
||||
// 4. Gift wrap the sealed event (encrypt to recipient again)
|
||||
val giftWrap = createGiftWrap(
|
||||
// 3. Gift wrap to recipient (kind 1059)
|
||||
val giftWrapToRecipient = createGiftWrap(
|
||||
seal = sealedEvent,
|
||||
recipientPubkey = recipientPubkey
|
||||
)
|
||||
|
||||
Log.v(TAG, "Created gift wrap with id: ${giftWrap.id.take(16)}...")
|
||||
|
||||
return giftWrap
|
||||
Log.d(TAG, "Created gift wrap: toRecipient=${giftWrapToRecipient.id.take(16)}...")
|
||||
return listOf(giftWrapToRecipient)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +83,7 @@ object NostrProtocol {
|
||||
|
||||
Triple(rumor.content, rumor.pubkey, rumor.createdAt)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ Failed to decrypt private message: ${e.message}")
|
||||
Log.w(TAG, "Failed to decrypt private message: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -143,7 +139,7 @@ object NostrProtocol {
|
||||
|
||||
val seal = NostrEvent(
|
||||
pubkey = senderPublicKey,
|
||||
createdAt = NostrCrypto.randomizeTimestamp(),
|
||||
createdAt = NostrCrypto.randomizeTimestampUpToPast(),
|
||||
kind = NostrKind.SEAL,
|
||||
tags = emptyList(),
|
||||
content = encrypted
|
||||
@@ -172,7 +168,7 @@ object NostrProtocol {
|
||||
|
||||
val giftWrap = NostrEvent(
|
||||
pubkey = wrapPublicKey,
|
||||
createdAt = NostrCrypto.randomizeTimestamp(),
|
||||
createdAt = NostrCrypto.randomizeTimestampUpToPast(),
|
||||
kind = NostrKind.GIFT_WRAP,
|
||||
tags = listOf(listOf("p", recipientPubkey)), // Tag recipient
|
||||
content = encrypted
|
||||
@@ -186,7 +182,7 @@ object NostrProtocol {
|
||||
giftWrap: NostrEvent,
|
||||
recipientPrivateKey: String
|
||||
): NostrEvent? {
|
||||
Log.v(TAG, "Unwrapping gift wrap")
|
||||
Log.d(TAG, "Unwrapping gift wrap; content prefix='${giftWrap.content.take(3)}' length=${giftWrap.content.length}")
|
||||
|
||||
return try {
|
||||
val decrypted = NostrCrypto.decryptNIP44(
|
||||
@@ -215,7 +211,7 @@ object NostrProtocol {
|
||||
Log.v(TAG, "Unwrapped seal with kind: ${seal.kind}")
|
||||
seal
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to unwrap gift wrap: ${e.message}")
|
||||
Log.w(TAG, "Failed to unwrap gift wrap: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -248,7 +244,7 @@ object NostrProtocol {
|
||||
sig = jsonObject.get("sig")?.asString
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to open seal: ${e.message}")
|
||||
Log.w(TAG, "Failed to open seal: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user