Send Private Zaps

This commit is contained in:
Believethehype 2023-04-13 00:15:36 +02:00
parent eab202f721
commit ff490a2b14
3 changed files with 74 additions and 9 deletions

View File

@ -72,7 +72,7 @@ class LnZapEvent(
enum class ZapType() {
PUBLIC,
PRIVATE, // not yet implemented
PRIVATE,
ANONYMOUS,
NONZAP
}

View File

@ -1,9 +1,14 @@
package com.vitorpamplona.amethyst.service.model
import com.vitorpamplona.amethyst.model.HexKey
import com.vitorpamplona.amethyst.model.toHexKey
import com.vitorpamplona.amethyst.model.*
import nostr.postr.Bech32
import nostr.postr.Utils
import java.util.Date
import java.nio.charset.Charset
import java.security.SecureRandom
import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
class LnZapRequestEvent(
id: HexKey,
@ -28,7 +33,7 @@ class LnZapRequestEvent(
zapType: LnZapEvent.ZapType,
createdAt: Long = Date().time / 1000
): LnZapRequestEvent {
val content = message
var content = message
var privkey = privateKey
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
var tags = listOf(
@ -46,12 +51,65 @@ class LnZapRequestEvent(
tags = tags + listOf(listOf("anon", ""))
privkey = Utils.privkeyCreate()
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
var enc_prkey = create_private_key(privateKey, originalNote.id(), createdAt)
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
var privreq = encrypt_privatezap_message(noteJson, enc_prkey, originalNote.pubKey().toByteArray())
tags = tags + listOf(listOf("anon", privreq))
content = ""
privkey = enc_prkey
pubKey = Utils.pubkeyCreate(enc_prkey).toHexKey()
}
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = Utils.sign(id, privkey)
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
}
fun create_private_key(privkey: ByteArray, id: String, createdAt: Long): ByteArray {
var str = privkey.toHexKey() + id + createdAt.toString()
var strbyte = str.toByteArray(Charset.forName("utf-8"))
return sha256.digest(strbyte)
}
fun encrypt_privatezap_message(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
var sharedSecret = Utils.getSharedSecret(privkey, pubkey)
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
val keySpec = SecretKeySpec(sharedSecret, "AES")
val ivSpec = IvParameterSpec(iv)
var utf8_message = msg.toByteArray(Charset.forName("utf-8"))
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
val encryptedMsg = cipher.doFinal(utf8_message)
val encryptedMsgBech32 = Bech32.encode("pzap", Bech32.eight2five(encryptedMsg), Bech32.Encoding.Bech32)
val ivBech32 = Bech32.encode("iv", Bech32.eight2five(iv), Bech32.Encoding.Bech32)
return encryptedMsgBech32 + "_" + ivBech32
}
fun decrypt_privatezap_message(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
var sharedSecret = Utils.getSharedSecret(privkey, pubkey)
val parts = msg.split("_")
val iv = parts[1].run { Bech32.decode(this) }
val encryptedMsg = parts.first().run { Bech32.decode(this) }
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(Bech32.five2eight(iv.second, 0)))
return String(cipher.doFinal(Bech32.five2eight(encryptedMsg.second, 0)))
}
fun test_decrypt(privateKey: ByteArray, event: Event): String {
val anonTag = event.tags.firstOrNull { t -> t.count() >= 2 && t[0] == "anon" }
var encnote = anonTag?.elementAt(1)
if (encnote != null) {
var enc_prkey2 = create_private_key(privateKey, event.id(), event.createdAt)
return decrypt_privatezap_message(encnote, enc_prkey2, event.pubKey().toByteArray())
} else {
return ""
}
}
fun create(
userHex: String,
relays: Set<String>,
@ -60,7 +118,7 @@ class LnZapRequestEvent(
zapType: LnZapEvent.ZapType,
createdAt: Long = Date().time / 1000
): LnZapRequestEvent {
val content = message
var content = message
var privkey = privateKey
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
var tags = listOf(
@ -68,18 +126,24 @@ class LnZapRequestEvent(
listOf("relays") + relays
)
if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
tags = tags + listOf(listOf("anon", ""))
privkey = Utils.privkeyCreate()
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
tags = tags + listOf(listOf("anon", ""))
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
var enc_prkey = create_private_key(privateKey, userHex, createdAt)
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
var privreq = encrypt_privatezap_message(noteJson, enc_prkey, userHex.toByteArray())
tags = tags + listOf(listOf("anon", privreq))
content = ""
privkey = enc_prkey
pubKey = Utils.pubkeyCreate(enc_prkey).toHexKey()
}
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = Utils.sign(id, privkey)
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
}
}
}
/*
{
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",

View File

@ -67,6 +67,7 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
val zapTypes = listOf(
Pair(LnZapEvent.ZapType.PUBLIC, "Public"),
Pair(LnZapEvent.ZapType.PRIVATE, "Private"),
Pair(LnZapEvent.ZapType.ANONYMOUS, "Anonymous"),
Pair(LnZapEvent.ZapType.NONZAP, "Non-Zap")
)