mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-28 05:27:15 +02:00
Send Private Zaps
This commit is contained in:
@@ -72,7 +72,7 @@ class LnZapEvent(
|
|||||||
|
|
||||||
enum class ZapType() {
|
enum class ZapType() {
|
||||||
PUBLIC,
|
PUBLIC,
|
||||||
PRIVATE, // not yet implemented
|
PRIVATE,
|
||||||
ANONYMOUS,
|
ANONYMOUS,
|
||||||
NONZAP
|
NONZAP
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,14 @@
|
|||||||
package com.vitorpamplona.amethyst.service.model
|
package com.vitorpamplona.amethyst.service.model
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.HexKey
|
import com.vitorpamplona.amethyst.model.*
|
||||||
import com.vitorpamplona.amethyst.model.toHexKey
|
import nostr.postr.Bech32
|
||||||
import nostr.postr.Utils
|
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(
|
class LnZapRequestEvent(
|
||||||
id: HexKey,
|
id: HexKey,
|
||||||
@@ -28,7 +33,7 @@ class LnZapRequestEvent(
|
|||||||
zapType: LnZapEvent.ZapType,
|
zapType: LnZapEvent.ZapType,
|
||||||
createdAt: Long = Date().time / 1000
|
createdAt: Long = Date().time / 1000
|
||||||
): LnZapRequestEvent {
|
): LnZapRequestEvent {
|
||||||
val content = message
|
var content = message
|
||||||
var privkey = privateKey
|
var privkey = privateKey
|
||||||
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
||||||
var tags = listOf(
|
var tags = listOf(
|
||||||
@@ -46,12 +51,65 @@ class LnZapRequestEvent(
|
|||||||
tags = tags + listOf(listOf("anon", ""))
|
tags = tags + listOf(listOf("anon", ""))
|
||||||
privkey = Utils.privkeyCreate()
|
privkey = Utils.privkeyCreate()
|
||||||
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
|
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 id = generateId(pubKey, createdAt, kind, tags, content)
|
||||||
val sig = Utils.sign(id, privkey)
|
val sig = Utils.sign(id, privkey)
|
||||||
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
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(
|
fun create(
|
||||||
userHex: String,
|
userHex: String,
|
||||||
relays: Set<String>,
|
relays: Set<String>,
|
||||||
@@ -60,7 +118,7 @@ class LnZapRequestEvent(
|
|||||||
zapType: LnZapEvent.ZapType,
|
zapType: LnZapEvent.ZapType,
|
||||||
createdAt: Long = Date().time / 1000
|
createdAt: Long = Date().time / 1000
|
||||||
): LnZapRequestEvent {
|
): LnZapRequestEvent {
|
||||||
val content = message
|
var content = message
|
||||||
var privkey = privateKey
|
var privkey = privateKey
|
||||||
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
||||||
var tags = listOf(
|
var tags = listOf(
|
||||||
@@ -68,18 +126,24 @@ class LnZapRequestEvent(
|
|||||||
listOf("relays") + relays
|
listOf("relays") + relays
|
||||||
)
|
)
|
||||||
if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
|
if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
|
||||||
tags = tags + listOf(listOf("anon", ""))
|
|
||||||
privkey = Utils.privkeyCreate()
|
privkey = Utils.privkeyCreate()
|
||||||
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
|
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 id = generateId(pubKey, createdAt, kind, tags, content)
|
||||||
val sig = Utils.sign(id, privkey)
|
val sig = Utils.sign(id, privkey)
|
||||||
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||||
|
@@ -67,6 +67,7 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
|||||||
|
|
||||||
val zapTypes = listOf(
|
val zapTypes = listOf(
|
||||||
Pair(LnZapEvent.ZapType.PUBLIC, "Public"),
|
Pair(LnZapEvent.ZapType.PUBLIC, "Public"),
|
||||||
|
Pair(LnZapEvent.ZapType.PRIVATE, "Private"),
|
||||||
Pair(LnZapEvent.ZapType.ANONYMOUS, "Anonymous"),
|
Pair(LnZapEvent.ZapType.ANONYMOUS, "Anonymous"),
|
||||||
Pair(LnZapEvent.ZapType.NONZAP, "Non-Zap")
|
Pair(LnZapEvent.ZapType.NONZAP, "Non-Zap")
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user