Session creation
High level flow of DuoSession
- Configure/Implement transport layer NetworkClient
- Configure/Implement storage layer StorageClient
- Configure/Implement MessageSigner
- Create DuoSession
- Perform MPC actions
DuoSession is the main object which will be used to perform all of the MPC operations supported. To create DuoSession please follow the steps below.
Step 1 : Add library to your Project
-
Create new android studio project if you haven't.
-
Add SilentShard-Duo SDK using the instructions from the Installation Guide
Step 2 : Create new session
- We can Create DuoSession by calling SilentShard.ECDSA.duoInitiator() or SilentShard.EdDSA.duoInitiator() (whichever applies) by providing the following four parameters
- Provide websocket client by using any of the below options :
- Providing WebsocketConfig object to let SDK use default Network Client i.e. DuoNetworkClient.
- Providing custom NetworkClient overriding(extending) DuoNetworkClient to override existing connect, read or write, etc. methods to add your own logic/configuration or additional process.
- Provide cloud/server public key.
- Provide storage client. (You need to implement the interface StorageClient).
- Provide Message Signer (You need to implement the interface MessageSigner).
Example
- ECDSA
- EdDSA
MainActivity.kt
import com.silencelaboratories.silentshard.duo.DuoSession
import com.silencelaboratories.silentshard.duo.SilentShard
import com.silencelaboratories.silentshard.network.websocket.WebsocketConfig
import com.silencelaboratories.silentshard.storage.KeyType
import com.silencelaboratories.silentshard.storage.StorageClient
import com.silencelaboratories.silentshard.storage.StorageDao
import com.silencelaboratories.silentshard.storage.silentshard.ReconcileStoreDao
import com.silencelaboratories.silentshard.utils.MessageSigner
object Constants {
// Replace with your own
const val CLOUD_NODE_URI = "demo-server.silencelaboratories.com"
// Replace with your own
const val PORT = 443
}
// Other party verifying-key/public-key. Replace with your own Verifying Key.
val cloudPublicKey = "cfa1ff5424d14eb60614d7ddf65a32243d26ddf7000d10007853d7336395efe4"
// Create websocketConfig to let SilentShard use the default WebsocketClient.
val websocketConfig = WebsocketConfig(url = Constants.CLOUD_NODE_URI, port = Constants.PORT, isSecure = true)
// Create a storageClient to persist keyshares. The SDK owns keyshare storage and
// addresses every share by its keyId — your code never holds raw keyshare bytes.
val storageClient = object : StorageClient {
// The algorithm family this client stores keyshares for. Provide a separate
// client (with a matching keyType) per algorithm if you run more than one.
override val keyType = KeyType.ECDSA
/**
* An in-memory database. In the real world this should be a SQL-based DB,
* secure storage, or custom hardware — it is up to the implementing app.
*/
private val entries = mutableMapOf<String, ReconcileStoreDao>()
override suspend fun write(dao: StorageDao) {
require(dao is ReconcileStoreDao) { "Expected ReconcileStoreDao" }
// Persist the whole snapshot, including any null fields.
entries[dao.keyId] = dao
}
override suspend fun read(key: String): StorageDao? = entries[key]
}
// Create a messageSigner backed by your secure key storage (TEE / Keystore).
val messageSigner = object : MessageSigner {
override val verifyingKey: ByteArray
get() = TODO("Public key of secure key (Secure Environment - TEE)")
override val keyType: MessageSigner.KeyType
get() = TODO("Type of secure key (Secure Environment - TEE)")
override suspend fun sign(data: ByteArray): ByteArray {
TODO("Sign data using secure key (Secure Environment - TEE) and return the signature")
}
}
// For quick-start you can use the test message signer. Do not use it in production.
val testMessageSigner = SilentShard.ECDSA.TestMessageSigner
// Create a DuoSession for the ECDSA algorithm
val duoSession: DuoSession = SilentShard.ECDSA.duoInitiator(
// pass your messageSigner instance in production; do not use testMessageSigner
testMessageSigner, cloudPublicKey, websocketConfig, storageClient
)
// Or create a DuoSession with your own network client by extending DuoNetworkClient:
// val duoSession: DuoSession = SilentShard.ECDSA.duoInitiator(
// testMessageSigner, cloudPublicKey, CustomDuoNetworkClient(), storageClient
// )
MainActivity.kt
import com.silencelaboratories.silentshard.duo.DuoSession
import com.silencelaboratories.silentshard.duo.SilentShard
import com.silencelaboratories.silentshard.network.websocket.WebsocketConfig
import com.silencelaboratories.silentshard.storage.KeyType
import com.silencelaboratories.silentshard.storage.StorageClient
import com.silencelaboratories.silentshard.storage.StorageDao
import com.silencelaboratories.silentshard.storage.silentshard.ReconcileStoreDao
import com.silencelaboratories.silentshard.utils.MessageSigner
object Constants {
// Replace with your own
const val CLOUD_NODE_URI = "demo-server.silencelaboratories.com"
// Replace with your own
const val PORT = 443
}
// Other party verifying-key/public-key. Replace with your own Verifying Key.
val cloudPublicKey = "cfa1ff5424d14eb60614d7ddf65a32243d26ddf7000d10007853d7336395efe4"
// Create websocketConfig to let SilentShard use the default WebsocketClient.
val websocketConfig = WebsocketConfig(url = Constants.CLOUD_NODE_URI, port = Constants.PORT, isSecure = true)
// Create a storageClient to persist keyshares. The SDK owns keyshare storage and
// addresses every share by its keyId — your code never holds raw keyshare bytes.
val storageClient = object : StorageClient {
// The algorithm family this client stores keyshares for. Provide a separate
// client (with a matching keyType) per algorithm if you run more than one.
override val keyType = KeyType.EdDSA
/**
* An in-memory database. In the real world this should be a SQL-based DB,
* secure storage, or custom hardware — it is up to the implementing app.
*/
private val entries = mutableMapOf<String, ReconcileStoreDao>()
override suspend fun write(dao: StorageDao) {
require(dao is ReconcileStoreDao) { "Expected ReconcileStoreDao" }
// Persist the whole snapshot, including any null fields.
entries[dao.keyId] = dao
}
override suspend fun read(key: String): StorageDao? = entries[key]
}
// Create a messageSigner backed by your secure key storage (TEE / Keystore).
val messageSigner = object : MessageSigner {
override val verifyingKey: ByteArray
get() = TODO("Public key of secure key (Secure Environment - TEE)")
override val keyType: MessageSigner.KeyType
get() = TODO("Type of secure key (Secure Environment - TEE)")
override suspend fun sign(data: ByteArray): ByteArray {
TODO("Sign data using secure key (Secure Environment - TEE) and return the signature")
}
}
// For quick-start you can use the test message signer. Do not use it in production.
val testMessageSigner = SilentShard.EdDSA.TestMessageSigner
// Create a DuoSession for the EdDSA algorithm
val duoSession: DuoSession = SilentShard.EdDSA.duoInitiator(
// pass your messageSigner instance in production; do not use testMessageSigner
testMessageSigner, cloudPublicKey, websocketConfig, storageClient
)
// Or create a DuoSession with your own network client by extending DuoNetworkClient:
// val duoSession: DuoSession = SilentShard.EdDSA.duoInitiator(
// testMessageSigner, cloudPublicKey, CustomDuoNetworkClient(), storageClient
// )
CLOUD_NODE_URIis the URI of the cloud node.cloudPublicKeyis the cloud verifying key (Ed25519 public key).- This public key is used to verify the server's signature on each message
- See example here
- SilentShard Provides API for creating MPC DuoSession (Two-Party) using ECDSA algorithm.
- ECDSA Provides factory methods for creating MPC session using ECDSA algorithm.
- DuoSession Represents a two-party computation session that lets you perform MPC operations using SilentShard protocol.
You have now successfully set up the session and are ready to start performing MPC actions! 🎉