Refactoring dependency path to center in CryptoUtils

This commit is contained in:
Vitor Pamplona
2023-07-24 11:34:16 -04:00
parent 7923f5d854
commit 87990026ea
8 changed files with 29 additions and 28 deletions
@@ -22,7 +22,7 @@ import kotlin.jvm.JvmStatic
* Bech32 works with 5 bits values, we use this type to make it explicit: whenever you see Int5 it means 5 bits values, * Bech32 works with 5 bits values, we use this type to make it explicit: whenever you see Int5 it means 5 bits values,
* and whenever you see Byte it means 8 bits values. * and whenever you see Byte it means 8 bits values.
*/ */
public typealias Int5 = Byte private typealias Int5 = Byte
/** /**
* Bech32 and Bech32m address formats. * Bech32 and Bech32m address formats.
@@ -2,6 +2,7 @@ package com.vitorpamplona.amethyst.service
import fr.acinq.secp256k1.Hex import fr.acinq.secp256k1.Hex
import fr.acinq.secp256k1.Secp256k1 import fr.acinq.secp256k1.Secp256k1
import java.security.MessageDigest
import java.security.SecureRandom import java.security.SecureRandom
import java.util.Base64 import java.util.Base64
import javax.crypto.Cipher import javax.crypto.Cipher
@@ -9,6 +10,9 @@ import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
object CryptoUtils { object CryptoUtils {
private val secp256k1 = Secp256k1.get()
private val random = SecureRandom()
/** /**
* Provides a 32B "private key" aka random number * Provides a 32B "private key" aka random number
*/ */
@@ -54,15 +58,24 @@ object CryptoUtils {
return String(cipher.doFinal(encryptedMsg)) return String(cipher.doFinal(encryptedMsg))
} }
fun verifySignature(
signature: ByteArray,
hash: ByteArray,
pubKey: ByteArray
): Boolean {
return secp256k1.verifySchnorr(signature, hash, pubKey)
}
fun sha256(data: ByteArray): ByteArray {
// Creates a new buffer every time
return MessageDigest.getInstance("SHA-256").digest(data)
}
/** /**
* @return 32B shared secret * @return 32B shared secret
*/ */
fun getSharedSecret(privateKey: ByteArray, pubKey: ByteArray): ByteArray = fun getSharedSecret(privateKey: ByteArray, pubKey: ByteArray): ByteArray =
secp256k1.pubKeyTweakMul(Hex.decode("02") + pubKey, privateKey).copyOfRange(1, 33) secp256k1.pubKeyTweakMul(Hex.decode("02") + pubKey, privateKey).copyOfRange(1, 33)
private val secp256k1 = Secp256k1.get()
private val random = SecureRandom()
} }
fun Int.toByteArray(): ByteArray { fun Int.toByteArray(): ByteArray {
@@ -6,7 +6,6 @@ import android.util.Log
import com.vitorpamplona.amethyst.model.toHexKey import com.vitorpamplona.amethyst.model.toHexKey
import com.vitorpamplona.amethyst.ui.actions.ImageDownloader import com.vitorpamplona.amethyst.ui.actions.ImageDownloader
import io.trbl.blurhash.BlurHash import io.trbl.blurhash.BlurHash
import java.security.MessageDigest
import kotlin.math.roundToInt import kotlin.math.roundToInt
class FileHeader( class FileHeader(
@@ -45,9 +44,7 @@ class FileHeader(
onError: () -> Unit onError: () -> Unit
) { ) {
try { try {
val sha256 = MessageDigest.getInstance("SHA-256") val hash = CryptoUtils.sha256(data).toHexKey()
val hash = sha256.digest(data).toHexKey()
val size = data.size val size = data.size
val (blurHash, dim) = if (mimeType?.startsWith("image/") == true) { val (blurHash, dim) = if (mimeType?.startsWith("image/") == true) {
@@ -13,7 +13,6 @@ import fr.acinq.secp256k1.Hex
import fr.acinq.secp256k1.Secp256k1 import fr.acinq.secp256k1.Secp256k1
import java.lang.reflect.Type import java.lang.reflect.Type
import java.math.BigDecimal import java.math.BigDecimal
import java.security.MessageDigest
import java.util.* import java.util.*
@Immutable @Immutable
@@ -157,14 +156,14 @@ open class Event(
""".trimIndent() """.trimIndent()
) )
} }
if (!secp256k1.verifySchnorr(Hex.decode(sig), Hex.decode(id), Hex.decode(pubKey))) { if (!CryptoUtils.verifySignature(Hex.decode(sig), Hex.decode(id), Hex.decode(pubKey))) {
throw Exception("""Bad signature!""") throw Exception("""Bad signature!""")
} }
} }
override fun hasValidSignature(): Boolean { override fun hasValidSignature(): Boolean {
return try { return try {
id.contentEquals(generateId()) && secp256k1.verifySchnorr(Hex.decode(sig), Hex.decode(id), Hex.decode(pubKey)) id.contentEquals(generateId()) && CryptoUtils.verifySignature(Hex.decode(sig), Hex.decode(id), Hex.decode(pubKey))
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Event", "Fail checking if event $id has a valid signature", e) Log.e("Event", "Fail checking if event $id has a valid signature", e)
false false
@@ -182,7 +181,7 @@ open class Event(
.replace("\\u2028", "\u2028") .replace("\\u2028", "\u2028")
.replace("\\u2029", "\u2029") .replace("\\u2029", "\u2029")
return MessageDigest.getInstance("SHA-256").digest(rawEventJson.toByteArray()).toHexKey() return CryptoUtils.sha256(rawEventJson.toByteArray()).toHexKey()
} }
private class EventDeserializer : JsonDeserializer<Event> { private class EventDeserializer : JsonDeserializer<Event> {
@@ -336,7 +335,7 @@ open class Event(
.replace("\\u2028", "\u2028") .replace("\\u2028", "\u2028")
.replace("\\u2029", "\u2029") .replace("\\u2029", "\u2029")
return MessageDigest.getInstance("SHA-256").digest(rawEventJson.toByteArray()) return CryptoUtils.sha256(rawEventJson.toByteArray())
} }
fun create(privateKey: ByteArray, kind: Int, tags: List<List<String>> = emptyList(), content: String = "", createdAt: Long = TimeUtils.now()): Event { fun create(privateKey: ByteArray, kind: Int, tags: List<List<String>> = emptyList(), content: String = "", createdAt: Long = TimeUtils.now()): Event {
@@ -5,7 +5,6 @@ import com.vitorpamplona.amethyst.model.HexKey
import com.vitorpamplona.amethyst.model.TimeUtils import com.vitorpamplona.amethyst.model.TimeUtils
import com.vitorpamplona.amethyst.model.toHexKey import com.vitorpamplona.amethyst.model.toHexKey
import com.vitorpamplona.amethyst.service.CryptoUtils import com.vitorpamplona.amethyst.service.CryptoUtils
import java.security.MessageDigest
@Immutable @Immutable
class HTTPAuthorizationEvent( class HTTPAuthorizationEvent(
@@ -27,11 +26,9 @@ class HTTPAuthorizationEvent(
privateKey: ByteArray, privateKey: ByteArray,
createdAt: Long = TimeUtils.now() createdAt: Long = TimeUtils.now()
): HTTPAuthorizationEvent { ): HTTPAuthorizationEvent {
val sha256 = MessageDigest.getInstance("SHA-256")
var hash = "" var hash = ""
body?.let { body?.let {
hash = sha256.digest(it.toByteArray()).toHexKey() hash = CryptoUtils.sha256(it.toByteArray()).toHexKey()
} }
val tags = listOfNotNull( val tags = listOfNotNull(
@@ -5,7 +5,6 @@ import com.vitorpamplona.amethyst.model.*
import com.vitorpamplona.amethyst.service.Bech32 import com.vitorpamplona.amethyst.service.Bech32
import com.vitorpamplona.amethyst.service.CryptoUtils import com.vitorpamplona.amethyst.service.CryptoUtils
import java.nio.charset.Charset import java.nio.charset.Charset
import java.security.MessageDigest
import java.security.SecureRandom import java.security.SecureRandom
import javax.crypto.BadPaddingException import javax.crypto.BadPaddingException
import javax.crypto.Cipher import javax.crypto.Cipher
@@ -133,7 +132,7 @@ class LnZapRequestEvent(
fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray { fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray {
var str = privkey + id + createdAt.toString() var str = privkey + id + createdAt.toString()
var strbyte = str.toByteArray(Charset.forName("utf-8")) var strbyte = str.toByteArray(Charset.forName("utf-8"))
return MessageDigest.getInstance("SHA-256").digest(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 {
@@ -13,9 +13,9 @@ import coil.fetch.Fetcher
import coil.fetch.SourceResult import coil.fetch.SourceResult
import coil.request.ImageRequest import coil.request.ImageRequest
import coil.request.Options import coil.request.Options
import com.vitorpamplona.amethyst.service.CryptoUtils
import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.checkNotInMainThread
import okio.Buffer import okio.Buffer
import java.security.MessageDigest
private fun toHex(color: Color): String { private fun toHex(color: Color): String {
val argb = color.toArgb() val argb = color.toArgb()
@@ -35,7 +35,7 @@ private fun bytesToRGB(b1: Byte, b2: Byte, b3: Byte): Color {
private fun svgString(msg: String): String { private fun svgString(msg: String): String {
checkNotInMainThread() checkNotInMainThread()
val hash = MessageDigest.getInstance("SHA-256").digest(msg.toByteArray()) val hash = CryptoUtils.sha256(msg.toByteArray())
val hashHex = hash.joinToString(separator = "") { b -> "%02x".format(b) } val hashHex = hash.joinToString(separator = "") { b -> "%02x".format(b) }
val bgColor = bytesToRGB(hash[0], hash[1], hash[2]) val bgColor = bytesToRGB(hash[0], hash[1], hash[2])
val fgColor = bytesToRGB(hash[3], hash[4], hash[5]) val fgColor = bytesToRGB(hash[3], hash[4], hash[5])
@@ -69,6 +69,7 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.toHexKey import com.vitorpamplona.amethyst.model.toHexKey
import com.vitorpamplona.amethyst.service.BlurHashRequester import com.vitorpamplona.amethyst.service.BlurHashRequester
import com.vitorpamplona.amethyst.service.CryptoUtils
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.actions.CloseButton
import com.vitorpamplona.amethyst.ui.actions.LoadingAnimation import com.vitorpamplona.amethyst.ui.actions.LoadingAnimation
@@ -91,7 +92,6 @@ import kotlinx.coroutines.launch
import net.engawapg.lib.zoomable.rememberZoomState import net.engawapg.lib.zoomable.rememberZoomState
import net.engawapg.lib.zoomable.zoomable import net.engawapg.lib.zoomable.zoomable
import java.io.File import java.io.File
import java.security.MessageDigest
@Immutable @Immutable
abstract class ZoomableContent( abstract class ZoomableContent(
@@ -697,11 +697,7 @@ private fun verifyHash(content: ZoomableUrlContent, context: Context): Boolean?
if (content.hash == null) return null if (content.hash == null) return null
context.imageLoader.diskCache?.get(content.url)?.use { snapshot -> context.imageLoader.diskCache?.get(content.url)?.use { snapshot ->
val imageFile = snapshot.data.toFile() val hash = CryptoUtils.sha256(snapshot.data.toFile().readBytes()).toHexKey()
val bytes = imageFile.readBytes()
val sha256 = MessageDigest.getInstance("SHA-256")
val hash = sha256.digest(bytes).toHexKey()
Log.d("Image Hash Verification", "$hash == ${content.hash}") Log.d("Image Hash Verification", "$hash == ${content.hash}")