From 500ae0c72ee9e81504b056c091a1b842fe8d8dbf Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Sat, 8 Jul 2023 11:21:12 -0400 Subject: [PATCH] Add Spinner support for kyber keys. --- .../thoughtcrime/securesms/util/Base64.java | 4 ++++ .../securesms/SpinnerApplicationContext.kt | 3 ++- .../securesms/database/KyberKeyTransformer.kt | 23 +++++++++++++++++++ spinner/lib/src/main/assets/browse.hbs | 2 +- spinner/lib/src/main/assets/query.hbs | 2 +- .../java/org/signal/spinner/SpinnerServer.kt | 6 ++--- 6 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java b/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java index 31baaa4bc0..99f545734a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java @@ -22,6 +22,10 @@ public final class Base64 { return org.whispersystems.util.Base64.encodeBytes(source); } + public static @NonNull String encodeBytesWithoutPadding(@NonNull byte[] source) { + return org.whispersystems.util.Base64.encodeBytesWithoutPadding(source); + } + public static @NonNull byte[] decodeOrThrow(@NonNull String s) { try { return org.whispersystems.util.Base64.decode(s); diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt b/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt index 91e6a96aa5..f59efe82e4 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt @@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.database.GV2UpdateTransformer import org.thoughtcrime.securesms.database.IsStoryTransformer import org.thoughtcrime.securesms.database.JobDatabase import org.thoughtcrime.securesms.database.KeyValueDatabase +import org.thoughtcrime.securesms.database.KyberKeyTransformer import org.thoughtcrime.securesms.database.LocalMetricsDatabase import org.thoughtcrime.securesms.database.LogDatabase import org.thoughtcrime.securesms.database.MegaphoneDatabase @@ -51,7 +52,7 @@ class SpinnerApplicationContext : ApplicationContext() { linkedMapOf( "signal" to DatabaseConfig( db = { SignalDatabase.rawDatabase }, - columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer, TimestampTransformer, ProfileKeyCredentialTransformer, MessageRangesTransformer) + columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer, TimestampTransformer, ProfileKeyCredentialTransformer, MessageRangesTransformer, KyberKeyTransformer) ), "jobmanager" to DatabaseConfig(db = { JobDatabase.getInstance(this).sqlCipherDatabase }), "keyvalue" to DatabaseConfig(db = { KeyValueDatabase.getInstance(this).sqlCipherDatabase }), diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt new file mode 100644 index 0000000000..ab877a7a90 --- /dev/null +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database + +import android.database.Cursor +import org.signal.core.util.requireBlob +import org.signal.libsignal.protocol.state.KyberPreKeyRecord +import org.signal.spinner.ColumnTransformer +import org.thoughtcrime.securesms.util.Base64 + +object KyberKeyTransformer : ColumnTransformer { + override fun matches(tableName: String?, columnName: String): Boolean { + return tableName == KyberPreKeyTable.TABLE_NAME && columnName == KyberPreKeyTable.SERIALIZED + } + + override fun transform(tableName: String?, columnName: String, cursor: Cursor): String? { + val record = KyberPreKeyRecord(cursor.requireBlob(columnName)) + return "ID: ${record.id}\nTimestamp: ${record.timestamp}\nPublicKey: ${Base64.encodeBytesWithoutPadding(record.keyPair.publicKey.serialize())}\nPrivateKey: ${Base64.encodeBytesWithoutPadding(record.keyPair.secretKey.serialize())}\nSignature: ${Base64.encodeBytesWithoutPadding(record.signature)}" + } +} diff --git a/spinner/lib/src/main/assets/browse.hbs b/spinner/lib/src/main/assets/browse.hbs index 6bb54a3a24..532911df8f 100644 --- a/spinner/lib/src/main/assets/browse.hbs +++ b/spinner/lib/src/main/assets/browse.hbs @@ -47,7 +47,7 @@ {{#each queryResult.rows}} {{#each this}} -
{{#if (eq this null)}} null {{else}} {{{this}}} {{/if}}
+
{{#if (eq this null)}}null{{else}}{{{this}}}{{/if}}
{{/each}} {{/each}} diff --git a/spinner/lib/src/main/assets/query.hbs b/spinner/lib/src/main/assets/query.hbs index ac57a3e096..f9ee672b23 100644 --- a/spinner/lib/src/main/assets/query.hbs +++ b/spinner/lib/src/main/assets/query.hbs @@ -38,7 +38,7 @@ {{#each queryResult.rows}} {{#each this}} -
{{#if (eq this null)}} null {{else}} {{{this}}} {{/if}}
+
{{#if (eq this null)}}null{{else}}{{{this}}}{{/if}}
{{/each}} {{/each}} diff --git a/spinner/lib/src/main/java/org/signal/spinner/SpinnerServer.kt b/spinner/lib/src/main/java/org/signal/spinner/SpinnerServer.kt index 1d11e91d33..b89166d3c2 100644 --- a/spinner/lib/src/main/java/org/signal/spinner/SpinnerServer.kt +++ b/spinner/lib/src/main/java/org/signal/spinner/SpinnerServer.kt @@ -144,7 +144,7 @@ internal class SpinnerServer( } val query = "select * from $table limit $pageSize offset ${pageSize * pageIndex}" - val queryResult = dbConfig.db().query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers) } + val queryResult = dbConfig.db().query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers, table = table) } return renderTemplate( "browse", @@ -264,14 +264,14 @@ internal class SpinnerServer( ) } - private fun Cursor.toQueryResult(queryStartTimeNanos: Long = 0, columnTransformers: List = emptyList()): QueryResult { + private fun Cursor.toQueryResult(queryStartTimeNanos: Long = 0, columnTransformers: List = emptyList(), table: String? = null): QueryResult { val numColumns = this.columnCount val columns = mutableListOf() val transformers = mutableListOf() for (i in 0 until numColumns) { val columnName = getColumnName(i) - val customTransformer: ColumnTransformer? = columnTransformers.find { it.matches(null, columnName) } + val customTransformer: ColumnTransformer? = columnTransformers.find { it.matches(table, columnName) } columns += if (customTransformer != null) { "$columnName *"