Refactoring dependency path to center in CryptoUtils
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
+1
-4
@@ -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}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user