[**@sodot/sodot-react-native-sdk**](/rn/api-ref) • **Docs**

***

[@sodot/sodot-react-native-sdk](/rn/api-ref) / StatefulEcdsa

# Class: StatefulEcdsa

Class providing the functionality for the ECDSA protocol via the DKLs19 MPC protocol.
This class provides a Stateful API meaning that key material will be stored by the SDK on the device.

## Example

```ts
// Your server side creates a room for 3 parties using its API_KEY
// Creating a room uuid should always happen on the server side using your API_KEY
const N = 3;
const T = 2;
const ecdsa = new StatefulEcdsa();
const API_KEY = 'MY_API_KEY';
const keygenRoomUuid = await ecdsa.createRoom(N, API_KEY);
// All parties call initKeygen to get a keygenId
const keygenId = await ecdsa.initKeygen('myKeyName');
// All parties receive the keygenIds from all other parties
const keygenIds = [keygenId1, keygenId2];
// All parties join the keygen room
const publicKey = await ecdsa.keygen(keygenRoomUuid, N, T, 'myKeyName', keygenIds);

// Pick the derivation path of the public key you want to sign for
const derivationPath = new Uint32Array([44,60,0,0,0]);
// Get the public key for the derivation path
const derivedPubkey = await ecdsa.derivePubkey('myKeyName', derivationPath);
// To sign a message, create a signing room on the server side, using your API_KEY
const signingRoomUuid = await ecdsa.createRoom(T, API_KEY);
// Hash the message
const messageHash = MessageHash.sha256('my message');
// 2 parties join the signing room
const signature = await ecdsa.sign(signingRoomUuid, 'myKeyName', messageHash, derivationPath);
// This signature can now be verified against derivedPubkey

// Refreshing the secret key material
// Your server creates a room for 3 parties
const refreshRoomUuid = await ecdsa.createRoom(N, API_KEY);
// All parties join the refresh room
await ecdsa.refresh(refreshRoomUuid, 'myKeyName', 'myNewKeyName');

// Signing using the new secret key material
// The room is again created by the server
const signingRoomUuid2 = await ecdsa.createRoom(T, API_KEY);

// Hash the message
const messageHash2 = MessageHash.sha256('my new message');
const signature2 = await ecdsa.sign(signingRoomUuid2, 'myNewKeyName', messageHash2, derivationPath);
// This signature can now be verified against derivedPubkey
```

## Constructors

### new StatefulEcdsa()

> **new StatefulEcdsa**(`hostUrl`?): [`StatefulEcdsa`](/rn/api-ref/classes/StatefulEcdsa)

Constructs a new Ecdsa instance.

#### Parameters

• **hostUrl?**: `string`

#### Returns

[`StatefulEcdsa`](/rn/api-ref/classes/StatefulEcdsa)

## Methods

### createRoom()

> **createRoom**(`numParties`, `apiKey`): `Promise`\<`string`>

Creates a room for the given number of parties.
A room is a one time instance used to perform a single MPC operation(keygen/signing/refresh etc.) between parties

This function should be called in the backend so to not embed the API key in code that is distributed to the users.
After the backend calls this function, the other parties can join the room by calling the relevant keygen/signing/refresh/etc. operation.

#### Parameters

• **numParties**: `number`

The number of parties that will join the room. (an integer in range 1..65\_535)

• **apiKey**: `string`

An API key is required to create a room

#### Returns

`Promise`\<`string`>

The UUID of the created room.

***

### deletePrivateKeyShareFromDevice()

> **deletePrivateKeyShareFromDevice**(`keyName`): `Promise`\<`void`>

Delete the private key share associated with the given `keyName`.
**WARNING:** This completely deletes the secret share from the device.
This method should only be used either after a `refresh` operation to delete the old key share or as a way of removing a key from the device.
Deletion is **irreversible**.

#### Parameters

• **keyName**: `string`

The name of the keypair, this name was used when generating the keypair, the secret share of the keypair will be deleted from this device.

#### Returns

`Promise`\<`void`>

***

### derivePrivateKeyFromXpriv()

> **derivePrivateKeyFromXpriv**(`xpriv`, `derivationPath`?): `Promise`\<`string`>

Parses an `xpriv` string according to BIP-32 non-hardened, and returns the derived private key for a given BIP-32 non-hardened derivation path

#### Parameters

• **xpriv**: `string`

A valid secp256k1 xpriv string.

• **derivationPath?**: `Uint32Array`

The BIP-32 non-hardened derivation path to use for computing the private key.

#### Returns

`Promise`\<`string`>

The derived private key of the xpriv.

***

### derivePubkey()

> **derivePubkey**(`keyName`, `derivationPath`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

Returns the derived public key for `keyName` for a given BIP-32 non-hardened derivation path

#### Parameters

• **keyName**: `string`

The name of the keypair, this name was used when generating the keypair.

• **derivationPath**: `Uint32Array` = `...`

The BIP-32 non-hardened derivation path to use for computing the public key.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The derived public key of the keypair.

***

### exportFullPrivateKey()

> **exportFullPrivateKey**(`roomUuid`, `keyName`, `toExportID`): `Promise`\<`string`>

Combine all secret shares and export the full private key to a single party.
Requires a threshold amount of parties to participate.

#### Parameters

• **roomUuid**: `string`

The UUID of the export room.

• **keyName**: `string`

The name of the keypair, the name that was used when generating the keypair.

• **toExportID**: `string`

The exportID outputs from `exportID()` of the party that will receive the private key, this must match between all parties, and the receiving party must participate.

#### Returns

`Promise`\<`string`>

The party being exported to will receive a `string` containing the full xpriv, while the rest will receive `undefined`.

***

### exportID()

> **exportID**(`keyName`): `Promise`\<`string`>

The party that expects to receive the private key needs to call this function before `exportFullPrivatekey`.
It must then transmit the ID to threshold-1 parties, this can be done in an untrusted channel (as if the parties use different keys this will break)
Once the parties have the exportID of the party they want to export the private key to, the party and the threshold-1 participants need to call `exportFullPrivatekey` with that ID.

#### Parameters

• **keyName**: `string`

The name of the keypair that will be generated later. This name will be used to retrieve a private key associated with the keygenId that is necessary for the keygen operation.

#### Returns

`Promise`\<`string`>

A string that contains a base58 string exportID.

***

### getAllStoredKeyNames()

> **getAllStoredKeyNames**(): `Promise`\<`string`\[]>

#### Returns

`Promise`\<`string`\[]>

A list of all the key names stored on the device.

***

### importPrivateKeyImporter()

> **importPrivateKeyImporter**(`roomUuid`, `threshold`, `privateKey`, `keyName`, `keygenIds`, `chaincode`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

WARNING: Private key import is an **advanced** feature of the SDK.
We strongly advise consulting with the Sodot team **before** using it, due to a full private key being imported from a different system.
Secret shares generated from imported private keys will always have the risk of the private key having been compromised in the past or in the future in case the private key is not deleted after the import operation.

Importing a **full private key**, and sharing into a `T-of-N` sharing, the resultant key shares will be of the exact **same** public key as the full private key.

This is the method that an importing party (meaning one the party in possesion of the private key) should use for receiving a key share in the new `T-of-N` quorum.

#### Parameters

• **roomUuid**: `string`

The UUID of the import room.

• **threshold**: `number`

The threshold of the keypair of the new quorum. (an integer in range 1..65\_535)

• **privateKey**: `string`

The private key to be imported. (a hex string of length 64)

• **keyName**: `string`

The name of the keypair. This must be the **same** name used in initKeygen and will later be used to retrieve the private key share from the secure storage when signing a message.

• **keygenIds**: `string`\[]

The keygenId outputs from `initKeygen()`, of all other parties we wish to be part of the new quorum with, `keygenId`s from all parties must be received through an authenticated communication channel.

• **chaincode**: `string` = `''`

(Optional) The chaincode that will be used for further key derivation to be used for the import operation. (a hex string of length 64)

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key for the new quorum, same as the pubkey of the imported key.

#### Example

```ts
const N = 3;
const T = 2;
// A private key is created in some external system.
// const privateKey = "b3ac...0d71"; // hex string with 64 hex chars
// Some time passes...
// Now this party wishes to be part of a new quorum of `2-of-3` sharing of the private key.

// The app server creates a room for N(= 3) parties.
const importRoomUuid = await ecdsa.createRoom(N, API_KEY);
// The other parties must join the import room using the `importPrivateKeyRecipient` method.
const keygenId = await ecdsa.initKeygen('myKeyName'); // This the importing party
// This importing party will send its `keygenId` to all other parties.
// This party will also receive the `keygenId`s of all other parties of the new quorum.
const keygenIds = [keygenId1, keygenId2, keygenId3]; // Note that here we must include our own `keygenId` as well, the order of the ids doesn't matter.
const importPubkey = await ecdsa.importPrivateKeyImporter(importRoomUuid, T, privateKey, 'myKeyName', keygenIds);
// 'myKeyName' can now be used for signing under the T(= 2) threshold with the same public key
```

***

### importPrivateKeyRecipient()

> **importPrivateKeyRecipient**(`roomUuid`, `threshold`, `keyName`, `keygenIds`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

WARNING: Private key import is an **advanced** feature of the SDK.
We strongly advise consulting with the Sodot team **before** using it, due to a full private key being imported from a different system.
Secret shares generated from imported private keys will always have the risk of the private key having been compromised in the past or in the future in case the private key is not deleted after the import operation.

Importing a **full private key**, and sharing into a `T-of-N` sharing, the resultant key shares will be of the exact **same** public key as the full private key.

This is the method that a new party (meaning one that does not currently have the private key) should use for receiving a key share in the new `T-of-N` quorum.
The method takes the same input parameters as `keygen` since for a new party joining the quorum the `import` operation is very similar to a `keygen` operation.

#### Parameters

• **roomUuid**: `string`

The UUID of the import room.

• **threshold**: `number`

The threshold of the keypair of the new quorum. (an integer in range 1..65\_535)

• **keyName**: `string`

The name of the keypair. This must be the **same** name used in initKeygen and will later be used to retrieve the private key share from the secure storage when signing a message.

• **keygenIds**: `string`\[]

The keygenId outputs from `initKeygen()`, of all other parties we wish to be part of the new quorum with, `keygenId`s from all parties must be received through an authenticated communication channel.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key for the new quorum, same as the pubkey of the imported key.

#### Example

```ts
const N = 3;
const T = 2;
// A private key is created in some external system.
// Some time passes...
// Now this party wishes to be part of a new quorum of `2-of-3` sharing of the private key.

// The app server creates a room for N(= 3) parties.
const importRoomUuid = await ecdsa.createRoom(N, API_KEY);
// The party with the private key must join the import room using the `importPrivateKeyImporter` method.
const keygenId = await ecdsa.initKeygen('myKeyName'); // This is a new party
// This new party will send its `keygenId` to all other parties.
// This party will also receive the `keygenId`s of all other parties of the new quorum.
const keygenIds = [keygenId1, keygenId2, keygenId3]; // Note that here we must include our own `keygenId` as well, the order of the ids doesn't matter.
const importPubkey = await ecdsa.importPrivateKeyRecipient(importRoomUuid, T, 'myKeyName', keygenIds);
// 'myKeyName' can now be used for signing under the T(= 2) threshold with the same public key
```

***

### importPrivateKeyShareData()

> **importPrivateKeyShareData**(`keyName`, `secretShareHex`): `Promise`\<`void`>

This function will store a secret share given to it (should be a result of calling `retrievePrivateKeyShareForBackup`) under a given key name.

#### Parameters

• **keyName**: `string`

The name that the key will be stored as.

• **secretShareHex**: `string`

A hex string that represents a private key share, should be the output of `retrievePrivateKeyShareForBackup`.

#### Returns

`Promise`\<`void`>

The private key share of the keypair.

***

### initKeygen()

> **initKeygen**(`keyName`): `Promise`\<`string`>

All parties must call this function **before** calling keygen.
The keyName for the key that will be generated during keygen (and later used for signing as well) is set here.
All parties receive a keygenId as an output from this function.
This keygenId must be sent through an authenticated communication channel to all other devices we wish to perform keygen with.
Once we have the keygenId-s of all parties, then keygen can be called with the **same** keyName as was given here.

#### Parameters

• **keyName**: `string`

The name of the keypair that will be generated later. This name will be used to retrieve a private key associated with the keygenId that is necessary for the keygen operation.

#### Returns

`Promise`\<`string`>

A base58 string that represents a keygenId.

***

### keygen()

> **keygen**(`roomUuid`, `numParties`, `threshold`, `keyName`, `keygenIds`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

Generate a keypair for the given number of parties and threshold.
This function will return the public key of the keypair.
The private key is stored in the secure storage of the device and will be used to sign messages.

#### Parameters

• **roomUuid**: `string`

The UUID of the keygen room.

• **numParties**: `number`

The number of parties that will join the keygen room. (an integer in range 1..65\_535)

• **threshold**: `number`

The threshold of the keypair that will be generated. (an integer in range 1..65\_535)

• **keyName**: `string`

The name of the keypair. This must be the **same** name used in initKeygen and will later be used to retrieve the private key share from the secure storage when signing a message.

• **keygenIds**: `string`\[]

The keygenId outputs from initKeygen of all other parties we wish to perform keygen with, these must have been received through an authenticated communication channel.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key of the generated keypair.

#### Example

```ts
// Your server side creates a room for 5 parties using its API_KEY
// Creating a room uuid should always happen on the server side using your API_KEY
const N = 5;
const T = 3;
const ecdsa = new StatefulEcdsa();
const API_KEY = 'MY_API_KEY';
const keygenRoomUuid = await ecdsa.createRoom(N, API_KEY);
// All parties call initKeygen to get a keygenId
const keygenId = await Ecdsa.initKeygen('myKeyName');
// All parties receive the keygenIds from all other parties
const keygenIds = [keygenId1, keygenId2, keygenId3, keygenId4];
// All parties join the keygen room
const publicKey = await ecdsa.keygen(keygenRoomUuid, N, T, 'myKeyName', keygenIds);
// publicKey is now distributed between all 5 parties, such that each 3 parties can sign a message.
```

***

### offlineExportFullPrivateKey()

> **offlineExportFullPrivateKey**(`keygenResults`): `Promise`\<`string`>

Receives as input an array of `threshold` `EcdsaKeygenResult`s and locally computes the full private key (xpriv).
The main use case for this function is in an offline recovery setting where keygen results are collected manually and used to recover the full private key on an air-gapped server/device.
In order to use key shares exported using `retrievePrivateKeyShareForBackup`, run `new EcdsaKeygenResult(undefined!, await ecdsa.retrievePrivateKeyShareForBackup('myKeyName'))` to create a `EcdsaKeygenResult`.

#### Parameters

• **keygenResults**: [`EcdsaKeygenResult`](/rn/api-ref/classes/EcdsaKeygenResult)\[]

An array of `threshold` `EcdsaKeygenResult`s that each contain a secret share of the private key to be locally extracted

#### Returns

`Promise`\<`string`>

A `string` containing the full xpriv.

***

### ~~pubkeyForKeyName()~~

> **pubkeyForKeyName**(`keyName`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

Retrieve the public key associated with the given keyName.

#### Parameters

• **keyName**: `string`

The name of the keypair, this name was used when generating the keypair.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key of the keypair.

#### Deprecated

It is recommended to use BIP-32 non-hardened derivation instead of the master secret shares when signing.

***

### refresh()

> **refresh**(`roomUuid`, `keyName`, `newKeyName`): `Promise`\<`void`>

Used for refreshing the **secret** material of all parties without altering the public key at all.
Takes a `keyName` and `newKeyName` as input and stores the fresh key material under `newKeyName`.
Be careful to delete the old `keyName` share before it is certain that all devices have properly stored
the fresh secret material under `newKeyName`.
Note that the new secret materials may only be used with each other, attempting to use older secret materials
with newer ones for signing will result in failure.
The motivation for using refresh is to enhance security by switching the secret key material frequently, this means that an adversary will
need to compromise multiple devices **at the same time** in order to compromise the private key.

#### Parameters

• **roomUuid**: `string`

The UUID the refresh room.

• **keyName**: `string`

The name of the key that will be refreshed.

• **newKeyName**: `string`

The new name of the key used to store the fresh secret material.

#### Returns

`Promise`\<`void`>

#### Example

```ts
const N = 5;
const T = 3;
const ecdsa = new StatefulEcdsa();
const API_KEY = 'MY_API_KEY';
// Refreshing the secret key material
// Your server creates a room for 5 parties
const refreshRoomUuid = await ecdsa.createRoom(N, API_KEY);
// All parties now join the refresh room using their current secret key material
await ecdsa.refresh(refreshRoomUuid, 'myKeyName', 'myNewKeyName');
// 'myNewKeyName' can now be used for signing under the same T threshold, as well as be refreshed again
```

***

### reshareNewParty()

> **reshareNewParty**(`roomUuid`, `oldThreshold`, `newThreshold`, `keyName`, `keygenIds`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

WARNING: Key resharing is an **advanced** feature of the SDK.
We strongly advise consulting with the Sodot team **before** using it, as incorrect usage might lead to the **detriment** of the private key **security**.
To use the feature correctly, developers using this feature must make sure that at least `n - t + 1` parties of the `t-of-n` signing quorum delete their current shares before using the resharing of the private key.
Also, after resharing, the resharing operation must not be considered complete until such deletion has occurred.
Since deleting a share **cannot** be guaranteed cryptographically, it **must** be guaranteed by the software architecture (hence, by the developers using the SDK).

Resharing the **private key** of the `t-of-n` quorum of signers, the resultant key shares will be of the exact **same** public key as the previous quorum.
Resharing should be used in cases where we aim to modify the current `t-of-n` quorum with a new quorum with `newT-of-newN` signers for the same public key.

This is the method that a new party (meaning one that does not currently have a key share) should use for receiving a key share in the new `newT-of-newN` quorum.
The method takes the same input parameters as `keygen` since for a new party joining the quorum the `reshare` operation is very similar to a `keygen` operation.
In order to receive the `keygenId`s of parties that are already a part of the quorum, those parties will need to call `exportID()` and send the result to the parties in the new quorum.

#### Parameters

• **roomUuid**: `string`

The UUID of the reshare room.

• **oldThreshold**: `number`

The threshold of the existing quorum. (an integer in range 1..65\_535)

• **newThreshold**: `number`

The threshold of the keypair of the new quorum. (an integer in range 1..65\_535)

• **keyName**: `string`

The name of the keypair. This must be the **same** name used in initKeygen and will later be used to retrieve the private key share from the secure storage when signing a message.

• **keygenIds**: `string`\[]

The keygenId outputs from `initKeygen()` - for new parties / `exportID()` - for parties remaining in the quorum, of all other parties we wish to be part of the new quorum with, `keygenId`s from all parties must be received through an authenticated communication channel.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key for the new quorum, same as the old pubkey.

#### Example

```ts
const N = 5;
const T = 3;
const newN = 6;
const newT = 5;
// A signing quorum of `3-of-5` is set up without this party.
// Some time passes...
// Now this party wishes to be part of a new quorum of `5-of-6`.

// The app server creates a room for newN(= 6) parties.
const reshareRoomUuid = await ecdsa.createRoom(newN, API_KEY);
// At least T(= 3) parties now join the reshare room using the current secret key material (this will be done using `reshareRemainingParty`), all new parties will then join the reshare room using their `initKeygenResult` using `reshareNewParty`.
const keygenId = await ecdsa.initKeygen('myKeyName'); // This is a new party
// This new party will send its `keygenId` to all other parties.
// This party will also receive the `keygenId`s of all other parties of the new quorum.
const keygenIds = [keygenId1, keygenId2, ..., keygenId6]; // Note that here we must include our own `keygenId` as well, the order of the ids doesn't matter.
const reshareKeygenPubkey = await ecdsa.reshareNewParty(reshareRoomUuid, T, newT, 'myKeyName', keygenIds);
// 'myKeyName' can now be used for signing under the newT(= 5) threshold with the same public key, as well as be reshared again
```

***

### reshareRemainingParty()

> **reshareRemainingParty**(`roomUuid`, `newThreshold`, `oldKeyName`, `newKeyName`, `keygenIds`): `Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

WARNING: Key resharing is an **advanced** feature of the SDK.
We strongly advise consulting with the Sodot team **before** using it, as incorrect usage might lead to the **detriment** of the private key **security**.
To use the feature correctly, developers using this feature must make sure that at least `n - t + 1` parties of the `t-of-n` signing quorum delete their current shares before using the resharing of the private key.
Also, after resharing, the resharing operation must not be considered complete until such deletion has occurred.
Since deleting a share **cannot** be guaranteed cryptographically, it **must** be guaranteed by the software architecture (hence, by the developers using the SDK).

Resharing the **private key** of the `t-of-n` quorum of signers, the resultant key shares will be of the exact **same** public key as the previous quorum.
Resharing should be used in cases where we aim to modify the current `t-of-n` quorum with a new quorum with `newT-of-newN` signers for the same public key.

This is the method that a remaining party (meaning one that does currently have a key share) should use for receiving a new key share in the new `newT-of-newN` quorum.
The method takes the same input parameters as `reshareNewParty` except that it will use its existing `Ed25519KeygenResult` instead of a new `Ed25519InitKeygenResult`.
In order to receive the `keygenId`s of parties that are already a part of the quorum, those parties will need to call `exportID()` and send the result to the parties in the new quorum.

#### Parameters

• **roomUuid**: `string`

The UUID of the reshare room.

• **newThreshold**: `number`

The threshold of the keypair of the new quorum. (an integer in range 1..65\_535)

• **oldKeyName**: `string`

The name of the keypair. This must be the **same** name used in the original `keygen`.

• **newKeyName**: `string`

The name of the new keypair for the new quorum.

• **keygenIds**: `string`\[]

The keygenId outputs from `initKeygen()` - for new parties / `exportID()` - for parties remaining in the quorum, of all other parties we wish to be part of the new quorum with, `keygenId`s from new parties must be received through an authenticated communication channel, `keygenId`s from remaining parties in the quorum can be sent through any communication channel.

#### Returns

`Promise`\<[`EcdsaPublicKey`](/rn/api-ref/classes/EcdsaPublicKey)>

The public key for the new quorum, same as the old pubkey.

#### Example

```ts
const N = 5;
const T = 3;
const newN = 6;
const newT = 5;
// A signing quorum of `3-of-5` is set up with this party.
ecdsa.keygen(..., 'myOldKeyName', ...);
// Some time passes...
// Now this party wishes to be part of a new quorum of `5-of-6`.

// The app server creates a room for newN(= 6) parties.
const reshareRoomUuid = await ecdsa.createRoom(newN, API_KEY);
// At least T(= 3) parties now join the reshare room using the current secret key material (this will be done using `reshareRemainingParty`), all new parties will then join the reshare room using their `initKeygenResult` using `reshareNewParty`.
const keygenId = await ecdsa.exportID('myOldKeyName'); // This is a remaining party
// This remaining party will send its `keygenId` to all other parties (new - via an authenticated channel and remaining - via any channel).
// This party will also receive the `keygenId`s of all other parties of the new quorum (new - via an authenticated channel and remaining - via any channel).
const keygenIds = [keygenId1, keygenId2, ..., keygenId6]; // Note that here we must include our own `keygenId` as well, the order of the ids doesn't matter.
const reshareKeygenPubkey = await ecdsa.reshareRemainingParty(reshareRoomUuid, newT, 'myOldKeyName', 'myNewKeyName', keygenIds);
// 'myNewKeyName' can now be used for signing under the newT(= 5) threshold with the same public key, as well as be reshared again
```

***

### retrievePrivateKeyShareForBackup()

> **retrievePrivateKeyShareForBackup**(`keyName`): `Promise`\<`string`>

Retrieve the private key share associated with the given keyName.
The returned value is a hex string that encodes the key material.
**Notice:** This value must be kept **secret**!
In case you wish to use the `offlineExportFullPrivateKey` method that requires an `EcdsaKeygenResult` as input, this may be constructed by running: `new EcdsaKeygenResult(undefined!, await ecdsa.retrievePrivateKeyShareForBackup('myKeyName'))`.

#### Parameters

• **keyName**: `string`

The name of the keypair, this name was used when generating the keypair.

#### Returns

`Promise`\<`string`>

The private key share of the keypair.

***

### sign()

> **sign**(`roomUuid`, `keyName`, `msgHash`, `derivationPath`): `Promise`\<[`EcdsaSignature`](/rn/api-ref/classes/EcdsaSignature)>

Sign a message with the secret share associated with the given keyName.
The secret share is stored in the secure storage of the device.
The message must be hashed before signing, this can be done using the [MessageHash](/rn/api-ref/classes/MessageHash) class.

#### Parameters

• **roomUuid**: `string`

The UUID of the sign room.

• **keyName**: `string`

The name of the keypair, this name was used when generating the keypair.

• **msgHash**: [`MessageHash`](/rn/api-ref/classes/MessageHash)

The hash of the message that will be signed.

• **derivationPath**: `Uint32Array` = `...`

The BIP-32 non-hardened derivation path to use for signing `msgHash`.

#### Returns

`Promise`\<[`EcdsaSignature`](/rn/api-ref/classes/EcdsaSignature)>

The signature of the message, this signature can be verified using the public key of the keypair.

#### Example

```ts
// To sign a message, create a signing room on the server side, using your API_KEY
const N = 5;
const T = 3;
const ecdsa = new StatefulEcdsa();
const API_KEY = 'MY_API_KEY';
const signingRoomUuid = await ecdsa.createRoom(T, API_KEY);

// Pick the derivation path of the public key you want to sign for
const derivationPath = new Uint32Array([44,60,0,0,0]);
// Get the public key for the derivation path
const derivedPubkey = await ecdsa.derivePubkey('myKeyName', derivationPath);
// Hash the message
const messageHash = MessageHash.sha256('my message');
// 3 parties join the signing room
const signature = await ecdsa.sign(signingRoomUuid, 'myKeyName', messageHash, derivationPath);
// This signature can now be verified against derivedPubkey
```
