support for sending and receiving nip 44 dms

This commit is contained in:
greenart7c3
2023-09-06 18:53:11 -03:00
parent a7aa3705ef
commit 6303573dd9
16 changed files with 399 additions and 85 deletions
@@ -5,6 +5,7 @@ import androidx.compose.runtime.Stable
import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.toImmutableSet
@@ -61,7 +62,7 @@ class ChatMessageEvent(
markAsSensitive: Boolean = false,
zapRaiserAmount: Long? = null,
geohash: String? = null,
privateKey: ByteArray,
keyPair: KeyPair,
createdAt: Long = TimeUtils.now()
): ChatMessageEvent {
val content = msg
@@ -91,10 +92,17 @@ class ChatMessageEvent(
tags.add(listOf("subject", it))
}
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
val pubKey = keyPair.pubKey.toHexKey()
val id = generateId(pubKey, createdAt, ClassifiedsEvent.kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey)
return ChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return ChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
}
fun create(
unsignedEvent: ChatMessageEvent,
signature: String
): ChatMessageEvent {
return ChatMessageEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature)
}
}
}
@@ -36,6 +36,19 @@ class GiftWrapEvent(
return myInnerEvent
}
fun cachedGift(pubKey: ByteArray, decryptedContent: String): Event? {
val hex = pubKey.toHexKey()
if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex]
val myInnerEvent = unwrap(decryptedContent)
if (myInnerEvent is WrappedEvent) {
myInnerEvent.host = this
}
cachedInnerEvent = cachedInnerEvent + Pair(hex, myInnerEvent)
return myInnerEvent
}
fun unwrap(privKey: ByteArray) = try {
plainContent(privKey)?.let { fromJson(it) }
} catch (e: Exception) {
@@ -43,6 +56,13 @@ class GiftWrapEvent(
null
}
fun unwrap(decryptedContent: String) = try {
plainContent(decryptedContent)?.let { fromJson(it) }
} catch (e: Exception) {
// Log.e("UnwrapError", "Couldn't Decrypt the content", e)
null
}
private fun plainContent(privKey: ByteArray): String? {
if (content.isEmpty()) return null
@@ -60,6 +80,11 @@ class GiftWrapEvent(
}
}
private fun plainContent(decryptedContent: String): String? {
if (decryptedContent.isEmpty()) return null
return decryptedContent
}
fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.get(1)
companion object {
@@ -9,7 +9,7 @@ class NIP24Factory {
fun createMsgNIP24(
msg: String,
to: List<HexKey>,
from: ByteArray,
keyPair: KeyPair,
subject: String? = null,
replyTos: List<String>? = null,
mentions: List<String>? = null,
@@ -18,12 +18,12 @@ class NIP24Factory {
zapRaiserAmount: Long? = null,
geohash: String? = null
): List<GiftWrapEvent> {
val senderPublicKey = CryptoUtils.pubkeyCreate(from).toHexKey()
val senderPublicKey = keyPair.pubKey.toHexKey()
val senderMessage = ChatMessageEvent.create(
msg = msg,
to = to,
privateKey = from,
keyPair = keyPair,
subject = subject,
replyTos = replyTos,
mentions = mentions,
@@ -38,7 +38,7 @@ class NIP24Factory {
event = SealedGossipEvent.create(
event = senderMessage,
encryptTo = it,
privateKey = from
privateKey = keyPair.privKey!!
),
recipientPubKey = it
)
@@ -46,7 +46,7 @@ class NIP24Factory {
}
fun createReactionWithinGroup(content: String, originalNote: EventInterface, to: List<HexKey>, from: KeyPair): List<GiftWrapEvent> {
val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey()
val senderPublicKey = from.pubKey.toHexKey()
val senderReaction = ReactionEvent.create(
content,
@@ -59,7 +59,7 @@ class NIP24Factory {
event = SealedGossipEvent.create(
event = senderReaction,
encryptTo = it,
privateKey = from.privKey
privateKey = from.privKey!!
),
recipientPubKey = it
)
@@ -67,7 +67,7 @@ class NIP24Factory {
}
fun createReactionWithinGroup(emojiUrl: EmojiUrl, originalNote: EventInterface, to: List<HexKey>, from: KeyPair): List<GiftWrapEvent> {
val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey()
val senderPublicKey = from.pubKey.toHexKey()
val senderReaction = ReactionEvent.create(
emojiUrl,
@@ -80,7 +80,7 @@ class NIP24Factory {
event = SealedGossipEvent.create(
event = senderReaction,
encryptTo = it,
privateKey = from.privKey
privateKey = from.privKey!!
),
recipientPubKey = it
)
@@ -38,6 +38,20 @@ class SealedGossipEvent(
return event
}
fun cachedGossip(pubKey: ByteArray, decryptedContent: String): Event? {
val hex = pubKey.toHexKey()
if (cachedInnerEvent.contains(hex)) return cachedInnerEvent[hex]
val gossip = unseal(decryptedContent)
val event = gossip?.mergeWith(this)
if (event is WrappedEvent) {
event.host = host ?: this
}
cachedInnerEvent = cachedInnerEvent + Pair(hex, event)
return event
}
fun unseal(privKey: ByteArray): Gossip? = try {
plainContent(privKey)?.let { Gossip.fromJson(it) }
} catch (e: Exception) {
@@ -45,6 +59,18 @@ class SealedGossipEvent(
null
}
fun unseal(decryptedContent: String): Gossip? = try {
plainContent(decryptedContent)?.let { Gossip.fromJson(it) }
} catch (e: Exception) {
Log.w("GossipEvent", "Fail to decrypt or parse Gossip", e)
null
}
private fun plainContent(decryptedContent: String): String? {
if (decryptedContent.isEmpty()) return null
return decryptedContent
}
private fun plainContent(privKey: ByteArray): String? {
if (content.isEmpty()) return null
@@ -95,6 +121,23 @@ class SealedGossipEvent(
val sig = CryptoUtils.sign(id, privateKey)
return SealedGossipEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
}
fun create(
encryptedContent: String,
pubKey: HexKey,
createdAt: Long = TimeUtils.randomWithinAWeek()
): SealedGossipEvent {
val tags = listOf<List<String>>()
val id = generateId(pubKey, createdAt, kind, tags, encryptedContent)
return SealedGossipEvent(id.toHexKey(), pubKey, createdAt, tags, encryptedContent, "")
}
fun create(
unsignedEvent: SealedGossipEvent,
signature: String
): SealedGossipEvent {
return SealedGossipEvent(unsignedEvent.id, unsignedEvent.pubKey, unsignedEvent.createdAt, unsignedEvent.tags, unsignedEvent.content, signature)
}
}
}