mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-03 23:15:44 +01:00
Introduce core-models module.
Needed to share some key components with feature modules without having to depend on libsignal-service.
This commit is contained in:
committed by
jeffrey-signal
parent
abf32bf6ff
commit
706d89db87
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.core.util
|
||||
|
||||
import java.security.SecureRandom
|
||||
|
||||
object RandomUtil {
|
||||
|
||||
fun getSecureBytes(size: Int): ByteArray {
|
||||
val secret = ByteArray(size)
|
||||
SecureRandom().nextBytes(secret)
|
||||
return secret
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.core.util
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
fun UUID.toByteArray(): ByteArray = UuidUtil.toByteArray(this)
|
||||
127
core-util-jvm/src/main/java/org/signal/core/util/UuidUtil.kt
Normal file
127
core-util-jvm/src/main/java/org/signal/core/util/UuidUtil.kt
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
package org.signal.core.util
|
||||
|
||||
import okio.ByteString
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object UuidUtil {
|
||||
@JvmField
|
||||
val UNKNOWN_UUID: UUID = UUID(0, 0)
|
||||
val UNKNOWN_UUID_STRING: String = UNKNOWN_UUID.toString()
|
||||
|
||||
private val UUID_PATTERN: Pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", Pattern.CASE_INSENSITIVE)
|
||||
|
||||
fun parse(uuid: String?): Optional<UUID> {
|
||||
return Optional.ofNullable(parseOrNull(uuid))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parseOrNull(uuid: String?): UUID? {
|
||||
return uuid?.takeIf { isUuid(it) }?.let { parseOrThrow(it) }
|
||||
}
|
||||
|
||||
fun parseOrUnknown(uuid: String?): UUID {
|
||||
return parseOrNull(uuid) ?: UNKNOWN_UUID
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parseOrThrow(uuid: String): UUID {
|
||||
return UUID.fromString(uuid)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parseOrThrow(bytes: ByteArray): UUID {
|
||||
val byteBuffer = ByteBuffer.wrap(bytes)
|
||||
val high = byteBuffer.getLong()
|
||||
val low = byteBuffer.getLong()
|
||||
|
||||
return UUID(high, low)
|
||||
}
|
||||
|
||||
fun parseOrThrow(bytes: ByteString): UUID {
|
||||
return parseOrNull(bytes.toByteArray())!!
|
||||
}
|
||||
|
||||
fun isUuid(uuid: String?): Boolean {
|
||||
return uuid != null && UUID_PATTERN.matcher(uuid).matches()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toByteArray(uuid: UUID): ByteArray {
|
||||
val buffer = ByteBuffer.wrap(ByteArray(16))
|
||||
buffer.putLong(uuid.mostSignificantBits)
|
||||
buffer.putLong(uuid.leastSignificantBits)
|
||||
|
||||
return buffer.array()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toByteString(uuid: UUID): ByteString {
|
||||
return ByteString.of(*toByteArray(uuid))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromByteString(bytes: ByteString): UUID {
|
||||
return parseOrThrow(bytes.toByteArray())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromByteStringOrNull(bytes: ByteString?): UUID? {
|
||||
if (bytes == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return parseOrNull(bytes.toByteArray())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStringUUID(stringId: String?, bytes: ByteString?): String? {
|
||||
val uuid = parseOrNull(bytes)
|
||||
return uuid?.toString() ?: stringId
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromByteStringOrUnknown(bytes: ByteString?): UUID {
|
||||
val uuid = fromByteStringOrNull(bytes)
|
||||
return uuid ?: UNKNOWN_UUID
|
||||
}
|
||||
|
||||
fun parseOrNull(byteArray: ByteArray?): UUID? {
|
||||
return if (byteArray != null && byteArray.size == 16) parseOrThrow(byteArray) else null
|
||||
}
|
||||
|
||||
fun parseOrNull(byteString: ByteString?): UUID? {
|
||||
return if (byteString != null) parseOrNull(byteString.toByteArray()) else null
|
||||
}
|
||||
|
||||
fun fromByteStrings(byteStringCollection: Collection<ByteString>): List<UUID> {
|
||||
val result = ArrayList<UUID>(byteStringCollection.size)
|
||||
|
||||
for (byteString in byteStringCollection) {
|
||||
result.add(fromByteString(byteString))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep only UUIDs that are not the [.UNKNOWN_UUID].
|
||||
*/
|
||||
fun filterKnown(uuids: MutableCollection<UUID?>): MutableList<UUID?> {
|
||||
val result = ArrayList<UUID?>(uuids.size)
|
||||
|
||||
for (uuid in uuids) {
|
||||
if (UNKNOWN_UUID != uuid) {
|
||||
result.add(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.core.util;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.signal.libsignal.protocol.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class UuidUtilTest {
|
||||
|
||||
@Test
|
||||
public void toByteArray() throws IOException {
|
||||
UUID uuid = UUID.fromString("67dfd496-ea02-4720-b13d-83a462168b1d");
|
||||
|
||||
byte[] serialized = UuidUtil.toByteArray(uuid);
|
||||
|
||||
assertArrayEquals(Hex.fromStringCondensed("67dfd496ea024720b13d83a462168b1d"), serialized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toByteArray_alternativeValues() throws IOException {
|
||||
UUID uuid = UUID.fromString("b70df6ac-3b21-4b39-a514-613561f51e2a");
|
||||
|
||||
byte[] serialized = UuidUtil.toByteArray(uuid);
|
||||
|
||||
assertArrayEquals(Hex.fromStringCondensed("b70df6ac3b214b39a514613561f51e2a"), serialized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseOrThrow_from_byteArray() throws IOException {
|
||||
byte[] bytes = Hex.fromStringCondensed("3dc48790568b49c19bd6ab6604a5bc32");
|
||||
|
||||
UUID uuid = UuidUtil.parseOrThrow(bytes);
|
||||
|
||||
assertEquals("3dc48790-568b-49c1-9bd6-ab6604a5bc32", uuid.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseOrThrow_from_byteArray_alternativeValues() throws IOException {
|
||||
byte[] bytes = Hex.fromStringCondensed("b83dfb0b67f141aa992e030c167cd011");
|
||||
|
||||
UUID uuid = UuidUtil.parseOrThrow(bytes);
|
||||
|
||||
assertEquals("b83dfb0b-67f1-41aa-992e-030c167cd011", uuid.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void byte_string_round_trip() {
|
||||
UUID uuid = UUID.fromString("67dfd496-ea02-4720-b13d-83a462168b1d");
|
||||
|
||||
UUID result = UuidUtil.fromByteString(ByteString.of(UuidUtil.toByteArray(uuid)));
|
||||
|
||||
assertEquals(uuid, result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user