Ecdsa

class Ecdsa(hostUrl: String = SODOT_RELAY_URL) : Scheme

ECDSA scheme implementation providing functionality for the DKLs19 MPC protocol.

This class handles cryptographic operations using ECDSA keys, including:

  • Key generation via multi-party computation (MPC)

  • Distributed signing of messages

  • Secret share refreshing

  • Key resharing

  • Key import/export

  • Key derivation with BIP-32 compatibility

Example Usage

/// Server side creates a room for 3 parties using API_KEY
/// Creating a room UUID should always happen on the server side
val numParties = 3
val threshold = 2
val apiKey = "MY_API_KEY"
val keygenRoomUuid = createRoom(numParties, apiKey)

/// All parties call initKeygen to get key generation IDs
val keygenInitResult = initKeygen()

/// All parties receive keygenIds from other parties
val keygenIds = listOf("keygenId1", "keygenId2")

/// All parties join the keygen room
val keygenResult = keygen(
keygenRoomUuid,
numParties,
threshold,
keygenInitResult.keygenSecret,
keygenIds
)

/// Pick the derivation path for the public key you want to sign for
val derivationPath = intArrayOf(44, 60, 0, 0, 0)

/// Option 1: Derive public key using the secret share from keygenResult
val pubkey = derivePubkey(keygenResult.secretShare, derivationPath)

/// Option 2: Derive public key using Xpub for more flexibility
val xpub = getXpub(keygenResult.secretShare)
val pubkeyFromXpub = derivePubkeyFromXpub(xpub, derivationPath)

/// To sign a message, create a signing room on the server side
val signingRoomUuid = createRoom(threshold, apiKey)

/// Hash the message before signing (required for ECDSA)
val messageHash = hashMessage("my message") // Compute SHA-256 hash

/// Threshold parties join the signing room
val signature = sign(signingRoomUuid, keygenResult.secretShare, messageHash, derivationPath)
/// This signature can now be verified against pubkey

/// Refreshing the secret key material
val refreshRoomUuid = createRoom(numParties, apiKey)
/// All parties join the refresh room
val refreshResult = refresh(refreshRoomUuid, keygenResult.secretShare)
/// Note: refreshResult.pubkey == keygenResult.pubkey

/// Signing using the new secret key material
val signingRoomUuid2 = createRoom(threshold, apiKey)
val messageHash2 = hashMessage("my new message")
val signature2 = sign(signingRoomUuid2, refreshResult.secretShare, messageHash2, derivationPath)
/// This signature can now be verified against pubkey

Constructors

Link copied to clipboard
constructor(hostUrl: String = SODOT_RELAY_URL)

Functions

Link copied to clipboard
suspend fun createRoom(numParties: Int, apiKey: String): RoomUUID

Creates a room for multi-party computation.

Link copied to clipboard
fun derivePrivateKeyFromXpriv(xpriv: String, derivationPath: IntArray): PrivateKey

Derives a private key from an extended private key (Xpriv).

Link copied to clipboard
fun derivePubkey(secretShare: EcdsaSecretShare, derivationPath: IntArray): EcdsaPublicKey

Derives a public key from an ECDSA secret share.

Link copied to clipboard
fun derivePubkeyFromXpub(xpub: String, derivationPath: IntArray): EcdsaPublicKey

Derives a public key from an extended public key (Xpub).

Link copied to clipboard
suspend fun exportFullPrivateKey(roomUuid: RoomUUID, secretShare: EcdsaSecretShare, toExportID: String): String?

Exports a full ECDSA private key(xpriv according to BIP-32).

Link copied to clipboard

Gets an export ID from an ECDSA secret share.

Link copied to clipboard
fun getXpub(secretShare: EcdsaSecretShare): String

Gets an extended public key (Xpub) from an ECDSA secret share.

Link copied to clipboard
suspend fun importPrivateKeyImporter(roomUuid: RoomUUID, threshold: Int, privateKey: ByteArray, keygenInitKeypair: KeygenPrivateKey, keygenIds: Array<KeygenID>, chaincode: ByteArray?): Pair<EcdsaPublicKey, EcdsaSecretShare>

Imports an ECDSA private key (importer).

Link copied to clipboard
suspend fun importPrivateKeyRecipient(roomUuid: RoomUUID, threshold: Int, keygenInitKeypair: KeygenPrivateKey, keygenIds: Array<KeygenID>): Pair<EcdsaPublicKey, EcdsaSecretShare>

Imports an ECDSA private key (recipient).

Link copied to clipboard

Initializes key generation for MPC protocols.

Link copied to clipboard
suspend fun keygen(roomUuid: RoomUUID, numParties: Int, threshold: Int, keygenInitKeypair: KeygenPrivateKey, keygenIds: Array<KeygenID>): Pair<EcdsaPublicKey, EcdsaSecretShare>

Generates ECDSA keys using multi-party computation.

Link copied to clipboard

Exports a full ECDSA private key offline(xpriv according to BIP-32).

Link copied to clipboard
suspend fun refresh(roomUuid: RoomUUID, secretShare: EcdsaSecretShare): Pair<EcdsaPublicKey, EcdsaSecretShare>

Refreshes the ECDSA secret share.

Link copied to clipboard
suspend fun reshareNewParty(roomUuid: RoomUUID, oldThreshold: Int, newThreshold: Int, keygenInitKeypair: KeygenPrivateKey, keygenIds: Array<KeygenID>): Pair<EcdsaPublicKey, EcdsaSecretShare>

Reshares an ECDSA key for a new party.

Link copied to clipboard
suspend fun reshareRemainingParty(roomUuid: RoomUUID, newThreshold: Int, secretShare: EcdsaSecretShare, keygenIds: Array<KeygenID>): Pair<EcdsaPublicKey, EcdsaSecretShare>

Reshares an ECDSA key for a remaining party.

Link copied to clipboard
suspend fun sign(roomUuid: RoomUUID, secretShare: EcdsaSecretShare, msgHash: MessageHash, derivationPath: IntArray): EcdsaSignature

Signs a message using ECDSA and multi-party computation.