# Key Lifecycle

Once we have already generated our key shares, we can refresh and also export them.
We show how to do this below.

## Key Refresh

Key Refresh (sometimes referred to as "Key Rotation") is a protocol that allows the devices to compute entirely **new** secret shares of the **same public key**.
Refreshing the key material frequently is considered a best practice for enhanced security, as it adds an element of time to the security setting.
Since even if one secret share was compromised, then after Key Refresh the compromised secret share will no longer be useful.
Below is an example of how to use Key Refresh:

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ecdsa;

    // Assume we have N parties with T threshold
    ushort N = 3;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);

    // Create a room for refreshing the key
    var refreshRoomUuid = await ecdsa.CreateRoom(N, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await ecdsa.Keygen(/*...*/);

    // All parties now join the refresh room using their current secret share
    var (refreshedPubkey, refreshedSecretShare) = await ecdsa.Refresh(refreshRoomUuid, secretShare);

    // Note: The public key remains the same
    // Store refreshedSecretShare securely for future use
    // It can now be used for signing under the same threshold, as well as be refreshed again
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    // Assume we have N parties with T threshold
    ushort N = 3;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);

    // Create a room for refreshing the key
    var refreshRoomUuid = await ed25519.CreateRoom(N, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await ed25519.Keygen(/*...*/);

    // All parties now join the refresh room using their current secret share
    var (refreshedPubkey, refreshedSecretShare) = await ed25519.Refresh(refreshRoomUuid, secretShare);

    // Note: The public key remains the same
    // Store refreshedSecretShare securely for future use
    // It can now be used for signing under the same threshold, as well as be refreshed again
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    // Assume we have N parties with T threshold
    ushort N = 3;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);

    // Create a room for refreshing the key
    var refreshRoomUuid = await bip340.CreateRoom(N, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await bip340.Keygen(/*...*/);

    // All parties now join the refresh room using their current secret share
    var (refreshedPubkey, refreshedSecretShare) = await bip340.Refresh(refreshRoomUuid, secretShare);

    // Note: The public key remains the same
    // Store refreshedSecretShare securely for future use
    // It can now be used for signing under the same threshold, as well as be refreshed again
    ```
  </Tab>
</Tabs>

## Key Reshare

Key Resharing is a protocol that allows changing the threshold parameters of the distributed key.
This can be useful when adding or removing participants, or when changing the threshold value.

There are two roles in the resharing process:

* **Remaining Parties**: Participants who already have a secret share
* **New Parties**: Participants who will receive a new secret share

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ecdsa;

    // Change from T=2 of N=3 to T'=3 of N'=5
    ushort oldThreshold = 2;
    ushort newThreshold = 3;
    ushort newN = 5;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);

    // Create a room for resharing the key
    var reshareRoomUuid = await ecdsa.CreateRoom(newN, myApiKey);

    // The keygenIds of all the parties that will have a secret share after resharing
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3"), new KeygenId("keygenId4"), new KeygenId("keygenId5") };

    // For remaining parties (those who already have a secret share):
    var (_, secretShare) = await ecdsa.Keygen(/*...*/);

    var (pubkey, newSecretShare) = await ecdsa.ReshareRemainingParty(reshareRoomUuid, newThreshold, secretShare, keygenIds);

    // For new parties:
    var (keygenId, keygenSecret) = ecdsa.InitKeygen();

    var (newPartyPubkey, newPartySecretShare) = await ecdsa.ReshareNewParty(reshareRoomUuid, newThreshold, keygenSecret, keygenIds);

    // Both remaining and new parties should store their new secret shares
    // These can now be used with the new threshold parameters
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    // Change from T=2 of N=3 to T'=3 of N'=5
    ushort oldThreshold = 2;
    ushort newThreshold = 3;
    ushort newN = 5;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);

    // Create a room for resharing the key
    var reshareRoomUuid = await ed25519.CreateRoom(newN, myApiKey);

    // The keygenIds of all the parties that will have a secret share after resharing
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3"), new KeygenId("keygenId4"), new KeygenId("keygenId5") };

    // For remaining parties (those who already have a secret share):
    var (_, secretShare) = await ed25519.Keygen(/*...*/);

    var (pubkey, newSecretShare) = await ed25519.ReshareRemainingParty(reshareRoomUuid, newThreshold, secretShare, keygenIds);

    // For new parties:
    var (keygenId, keygenSecret) = ed25519.InitKeygen();

    var (newPartyPubkey, newPartySecretShare) = await ed25519.ReshareNewParty(reshareRoomUuid, newThreshold, keygenSecret, keygenIds);

    // Both remaining and new parties should store their new secret shares
    // These can now be used with the new threshold parameters
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    // Change from T=2 of N=3 to T'=3 of N'=5
    ushort oldThreshold = 2;
    ushort newThreshold = 3;
    ushort newN = 5;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);

    // Create a room for resharing the key
    var reshareRoomUuid = await bip340.CreateRoom(newN, myApiKey);

    // The keygenIds of all the parties that will have a secret share after resharing
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3"), new KeygenId("keygenId4"), new KeygenId("keygenId5") };

    // For remaining parties (those who already have a secret share):
    var (_, secretShare) = await bip340.Keygen(/*...*/);

    var (pubkey, newSecretShare) = await bip340.ReshareRemainingParty(reshareRoomUuid, newThreshold, secretShare, keygenIds);

    // For new parties:
    var (keygenId, keygenSecret) = bip340.InitKeygen();

    var (newPartyPubkey, newPartySecretShare) = await bip340.ReshareNewParty(reshareRoomUuid, newThreshold, keygenSecret, keygenIds);

    // Both remaining and new parties should store their new secret shares
    // These can now be used with the new threshold parameters
    ```
  </Tab>
</Tabs>

## Key Export

In certain scenarios, you might need to export the full private key from the distributed key shares.
This should be used with caution as it negates some of the security benefits of MPC.

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ecdsa;

    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);
    var (_, secretShare) = await ecdsa.Keygen(/*...*/);

    // Only 1 party will receive the full private key
    // Get the export ID from the secret share of the party that will receive the full private key
    var exportID = await ecdsa.GetExportId(secretShare);

    // Create a room for the export process
    var exportRoomUuid = await ecdsa.CreateRoom(T, myApiKey);

    // Export the full private key (requires threshold number of participants)
    // All parties must specify the same export ID
    var fullPrivateKey = await ecdsa.ExportFullPrivateKey(exportRoomUuid, secretShare, exportID);

    // Handle the full private key with extreme care
    // This key should be securely stored or used immediately and then discarded

    // Alternatively, if you already have collected all secret shares offline:
    var secretShares = new[] { secretShare1, secretShare2 }; // secretShare1, secretShare2: shares collected from at least T parties
    var offlinePrivateKey = await ecdsa.OfflineExportFullPrivateKey(secretShares);
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);
    var (_, secretShare) = await ed25519.Keygen(/*...*/);

    // Only 1 party will receive the full private key
    // Get the export ID from the secret share of the party that will receive the full private key
    var exportID = await ed25519.GetExportId(secretShare);

    // Create a room for the export process
    var exportRoomUuid = await ed25519.CreateRoom(T, myApiKey);

    // Export the full private key (requires threshold number of participants)
    // All parties must specify the same export ID
    var fullPrivateKey = await ed25519.ExportFullPrivateKey(exportRoomUuid, secretShare, exportID);

    // Handle the full private key with extreme care
    // This key should be securely stored or used immediately and then discarded

    // Alternatively, if you already have collected all secret shares offline:
    var secretShares = new[] { secretShare1, secretShare2 }; // secretShare1, secretShare2: shares collected from at least T parties
    var offlinePrivateKey = await ed25519.OfflineExportFullPrivateKey(secretShares);
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);
    var (_, secretShare) = await bip340.Keygen(/*...*/);

    // Only 1 party will receive the full private key
    // Get the export ID from the secret share of the party that will receive the full private key
    var exportID = await bip340.GetExportId(secretShare);

    // Create a room for the export process
    var exportRoomUuid = await bip340.CreateRoom(T, myApiKey);

    // Export the full private key (requires threshold number of participants)
    // All parties must specify the same export ID
    var fullPrivateKey = await bip340.ExportFullPrivateKey(exportRoomUuid, secretShare, exportID);

    // Handle the full private key with extreme care
    // This key should be securely stored or used immediately and then discarded

    // Alternatively, if you already have collected all secret shares offline:
    var secretShares = new[] { secretShare1, secretShare2 }; // secretShare1, secretShare2: shares collected from at least T parties
    var offlinePrivateKey = await bip340.OfflineExportFullPrivateKey(secretShares);
    ```
  </Tab>
</Tabs>

## Key Import

You can also import an existing private key into the MPC system to create distributed shares.
This is useful for migrating existing keys to the MPC framework.

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ecdsa;

    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);

    string privateKey = "aabbccddeeff..."; // The private key to import as a hex string

    // Create a room for the import process
    var importRoomUuid = await ecdsa.CreateRoom(N, myApiKey);

    // All parties initialize key generation
    var (keygenId, keygenSecret) = ecdsa.InitKeygen();

    // All parties exchange their keygenIds
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3") };

    // For the party importing the key (the importer):
    var (pubkey, secretShare) = await ecdsa.ImportPrivateKeyImporter(importRoomUuid, T, privateKey, keygenSecret, keygenIds);

    // For all other parties (the recipients):
    var (recipientPubkey, recipientSecretShare) = await ecdsa.ImportPrivateKeyRecipient(importRoomUuid, T, keygenSecret, keygenIds);

    // All parties now have a secret share of the imported key
    // Store the secret share for future use
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);

    string privateKey = "aabbccddeeff..."; // The private key to import as a hex string

    // Create a room for the import process
    var importRoomUuid = await ed25519.CreateRoom(N, myApiKey);

    // All parties initialize key generation
    var (keygenId, keygenSecret) = ed25519.InitKeygen();

    // All parties exchange their keygenIds
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3") };

    // For the party importing the key (the importer):
    // isPrivateKeyRaw indicates whether privateKey is a raw scalar (true) or a seed (false)
    var (pubkey, secretShare) = await ed25519.ImportPrivateKeyImporter(importRoomUuid, T, privateKey, keygenSecret, keygenIds, isPrivateKeyRaw: false);

    // For all other parties (the recipients):
    var (recipientPubkey, recipientSecretShare) = await ed25519.ImportPrivateKeyRecipient(importRoomUuid, T, keygenSecret, keygenIds);

    // All parties now have a secret share of the imported key
    // Store the secret share for future use
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL
    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);

    string privateKey = "aabbccddeeff..."; // The private key to import as a hex string

    // Create a room for the import process
    var importRoomUuid = await bip340.CreateRoom(N, myApiKey);

    // All parties initialize key generation
    var (keygenId, keygenSecret) = bip340.InitKeygen();

    // All parties exchange their keygenIds
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId2"), new KeygenId("keygenId3") };

    // For the party importing the key (the importer):
    var (pubkey, secretShare) = await bip340.ImportPrivateKeyImporter(importRoomUuid, T, privateKey, keygenSecret, keygenIds);

    // For all other parties (the recipients):
    var (recipientPubkey, recipientSecretShare) = await bip340.ImportPrivateKeyRecipient(importRoomUuid, T, keygenSecret, keygenIds);

    // All parties now have a secret share of the imported key
    // Store the secret share for future use
    ```
  </Tab>
</Tabs>
