mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-04 18:02:39 +02:00
Small refactoring to create the PrivateZap Event
This commit is contained in:
@@ -41,9 +41,6 @@ class EventFactory {
|
|||||||
ContactListEvent.kind -> ContactListEvent(id, pubKey, createdAt, tags, content, sig)
|
ContactListEvent.kind -> ContactListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
DeletionEvent.kind -> DeletionEvent(id, pubKey, createdAt, tags, content, sig)
|
DeletionEvent.kind -> DeletionEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
|
||||||
// Will never happen.
|
|
||||||
// DirectMessageEvent.kind -> DirectMessageEvent(createdAt, tags, content)
|
|
||||||
|
|
||||||
EmojiPackEvent.kind -> EmojiPackEvent(id, pubKey, createdAt, tags, content, sig)
|
EmojiPackEvent.kind -> EmojiPackEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
EmojiPackSelectionEvent.kind -> EmojiPackSelectionEvent(id, pubKey, createdAt, tags, content, sig)
|
EmojiPackSelectionEvent.kind -> EmojiPackSelectionEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
SealedGossipEvent.kind -> SealedGossipEvent(id, pubKey, createdAt, tags, content, sig)
|
SealedGossipEvent.kind -> SealedGossipEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
@@ -59,6 +56,7 @@ class EventFactory {
|
|||||||
LnZapEvent.kind -> LnZapEvent(id, pubKey, createdAt, tags, content, sig)
|
LnZapEvent.kind -> LnZapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
LnZapPaymentRequestEvent.kind -> LnZapPaymentRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
LnZapPaymentRequestEvent.kind -> LnZapPaymentRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
LnZapPaymentResponseEvent.kind -> LnZapPaymentResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
LnZapPaymentResponseEvent.kind -> LnZapPaymentResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
LnZapPrivateEvent.kind -> LnZapPrivateEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
LnZapRequestEvent.kind -> LnZapRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
LnZapRequestEvent.kind -> LnZapRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
LongTextNoteEvent.kind -> LongTextNoteEvent(id, pubKey, createdAt, tags, content, sig)
|
LongTextNoteEvent.kind -> LongTextNoteEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
MetadataEvent.kind -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
MetadataEvent.kind -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
@@ -0,0 +1,43 @@
|
|||||||
|
package com.vitorpamplona.quartz.events
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||||
|
import com.vitorpamplona.quartz.encoders.Bech32
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import com.vitorpamplona.quartz.encoders.LnInvoiceUtil
|
||||||
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import javax.crypto.BadPaddingException
|
||||||
|
import javax.crypto.Cipher
|
||||||
|
import javax.crypto.spec.IvParameterSpec
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class LnZapPrivateEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: List<List<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey
|
||||||
|
) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val kind = 9733
|
||||||
|
|
||||||
|
fun create(
|
||||||
|
privateKey: ByteArray,
|
||||||
|
tags: List<List<String>> = emptyList(),
|
||||||
|
content: String = "",
|
||||||
|
createdAt: Long = TimeUtils.now()
|
||||||
|
): Event {
|
||||||
|
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
|
||||||
|
val id = generateId(pubKey, createdAt, kind, tags, content)
|
||||||
|
val sig = CryptoUtils.sign(id, privateKey).toHexKey()
|
||||||
|
return Event(id.toHexKey(), pubKey, createdAt, kind, tags, content, sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -86,9 +86,9 @@ class LnZapRequestEvent(
|
|||||||
privkey = CryptoUtils.privkeyCreate()
|
privkey = CryptoUtils.privkeyCreate()
|
||||||
pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey()
|
pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey()
|
||||||
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
||||||
var encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), originalNote.id(), createdAt)
|
val encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), originalNote.id(), createdAt)
|
||||||
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
|
val noteJson = (LnZapPrivateEvent.create(privkey, listOf(tags[0], tags[1]), message)).toJson()
|
||||||
var encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, originalNote.pubKey().hexToByteArray())
|
val encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, originalNote.pubKey().hexToByteArray())
|
||||||
tags = tags + listOf(listOf("anon", encryptedContent))
|
tags = tags + listOf(listOf("anon", encryptedContent))
|
||||||
content = "" // make sure public content is empty, as the content is encrypted
|
content = "" // make sure public content is empty, as the content is encrypted
|
||||||
privkey = encryptionPrivateKey // sign event with generated privkey
|
privkey = encryptionPrivateKey // sign event with generated privkey
|
||||||
@@ -119,9 +119,9 @@ class LnZapRequestEvent(
|
|||||||
pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey()
|
pubKey = CryptoUtils.pubkeyCreate(privkey).toHexKey()
|
||||||
tags = tags + listOf(listOf("anon", ""))
|
tags = tags + listOf(listOf("anon", ""))
|
||||||
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
||||||
var encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), userHex, createdAt)
|
val encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), userHex, createdAt)
|
||||||
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
|
val noteJson = LnZapPrivateEvent.create(privkey, listOf(tags[0], tags[1]), message).toJson()
|
||||||
var encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, userHex.hexToByteArray())
|
val encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, userHex.hexToByteArray())
|
||||||
tags = tags + listOf(listOf("anon", encryptedContent))
|
tags = tags + listOf(listOf("anon", encryptedContent))
|
||||||
content = ""
|
content = ""
|
||||||
privkey = encryptionPrivateKey
|
privkey = encryptionPrivateKey
|
||||||
@@ -132,21 +132,22 @@ class LnZapRequestEvent(
|
|||||||
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray {
|
fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray {
|
||||||
var str = privkey + id + createdAt.toString()
|
val str = privkey + id + createdAt.toString()
|
||||||
var strbyte = str.toByteArray(Charset.forName("utf-8"))
|
val strbyte = str.toByteArray(Charset.forName("utf-8"))
|
||||||
return CryptoUtils.sha256(strbyte)
|
return CryptoUtils.sha256(strbyte)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun encryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
private fun encryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
||||||
var sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey)
|
val sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey)
|
||||||
val iv = ByteArray(16)
|
val iv = ByteArray(16)
|
||||||
SecureRandom().nextBytes(iv)
|
SecureRandom().nextBytes(iv)
|
||||||
|
|
||||||
val keySpec = SecretKeySpec(sharedSecret, "AES")
|
val keySpec = SecretKeySpec(sharedSecret, "AES")
|
||||||
val ivSpec = IvParameterSpec(iv)
|
val ivSpec = IvParameterSpec(iv)
|
||||||
|
|
||||||
var utf8message = msg.toByteArray(Charset.forName("utf-8"))
|
val utf8message = msg.toByteArray(Charset.forName("utf-8"))
|
||||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
|
||||||
val encryptedMsg = cipher.doFinal(utf8message)
|
val encryptedMsg = cipher.doFinal(utf8message)
|
||||||
@@ -158,7 +159,7 @@ class LnZapRequestEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun decryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
private fun decryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
||||||
var sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey)
|
val sharedSecret = CryptoUtils.getSharedSecretNIP04(privkey, pubkey)
|
||||||
if (sharedSecret.size != 16 && sharedSecret.size != 32) {
|
if (sharedSecret.size != 16 && sharedSecret.size != 32) {
|
||||||
throw IllegalArgumentException("Invalid shared secret size")
|
throw IllegalArgumentException("Invalid shared secret size")
|
||||||
}
|
}
|
||||||
@@ -170,8 +171,10 @@ class LnZapRequestEvent(
|
|||||||
val encryptedMsg = parts.first().run { Bech32.decode(this).second }
|
val encryptedMsg = parts.first().run { Bech32.decode(this).second }
|
||||||
val encryptedBytes = Bech32.five2eight(encryptedMsg, 0)
|
val encryptedBytes = Bech32.five2eight(encryptedMsg, 0)
|
||||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||||
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(
|
cipher.init(
|
||||||
Bech32.five2eight(iv, 0)))
|
Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(
|
||||||
|
Bech32.five2eight(iv, 0))
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val decryptedMsgBytes = cipher.doFinal(encryptedBytes)
|
val decryptedMsgBytes = cipher.doFinal(encryptedBytes)
|
||||||
|
Reference in New Issue
Block a user