# 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 Go">
    ```go
    import "github.com/sodot-rs/sodot-go-sdk"

    const N = 3
    const API_KEY = "MY_API_KEY"
    // An EcdsaSecretShare was generated using Keygen
    // secretShare, pk, err := ecdsa.Keygen(...)
    var secretShare sodot.EcdsaSecretShare
    // Some time passes ...
    // We now refresh the secret key material of our public key
    ecdsa := sodot.NewEcdsa("")
    // Your server creates a room for 3 parties
    refreshRoomUuid, err := ecdsa.CreateRoom(N, API_KEY)
    if err != nil {
        panic(err)
    }

    // All parties join the refresh room
    // Note: the public key returned here is the same as the one returned by the keygen
    refreshedShare, _, err := ecdsa.Refresh(refreshRoomUuid, secretShare)
    if err != nil {
        panic(err)
    }
    // refreshedShare can now be used for signing under the same T threshold, as well as be refreshed again
    _ = refreshedShare
    ```

    :::tip[API reference]
    Full details can be found [here](/go/api-ref#func-ecdsa-refresh).
    :::
  </Tab>

  <Tab title="Ed25519 Go">
    ```go
    import "github.com/sodot-rs/sodot-go-sdk"

    const N = 3
    const API_KEY = "MY_API_KEY"
    // An Ed25519SecretShare was generated using Keygen
    // secretShare, pk, err := ed25519.Keygen(...)
    var secretShare sodot.Ed25519SecretShare
    // Some time passes ...
    // We now refresh the secret key material of our public key
    ed25519 := sodot.NewEd25519("")
    // Your server creates a room for 3 parties
    refreshRoomUuid, err := ed25519.CreateRoom(N, API_KEY)
    if err != nil {
        panic(err)
    }

    // All parties join the refresh room
    // Note: the public key returned here is the same as the one returned by the keygen
    refreshedShare, _, err := ed25519.Refresh(refreshRoomUuid, secretShare)
    if err != nil {
        panic(err)
    }
    // refreshedShare can now be used for signing under the same T threshold, as well as be refreshed again
    _ = refreshedShare
    ```

    :::tip[API reference]
    Full details can be found [here](/go/api-ref#func-ed25519-refresh).
    :::
  </Tab>
</Tabs>

## Key Export

In the case that we want to stop using the MPC SDK for a specific set of keys, it is possible to export the **full private key** out of the system to be used elsewhere.\
Note that by running Key Export we break the security model defined by splitting the private key into key shares. This operation is supported strictly in order to **prevent vendor-lock** and provide an exit strategy from using the SDK.\
Keys that have undergone Key Export should never again be used as key shares in the context of the SDK.\
Note that by design only **one** party will receive the full private key.
Below is an example of how to use Key Export:

<Tabs>
  <Tab title="ECDSA Go">
    ```go
    import "github.com/sodot-rs/sodot-go-sdk"

    const N = 3
    const T = 2
    const API_KEY = "MY_API_KEY"
    // An EcdsaSecretShare was generated using Keygen
    // secretShare, pk, err := ecdsa.Keygen(...)
    var secretShare sodot.EcdsaSecretShare
    ecdsa := sodot.NewEcdsa("")
    exportRoomUuid, err := ecdsa.CreateRoom(N, API_KEY)
    if err != nil {
        panic(err)
    }

    // Only one of the parties will receive the full private key, this party will retrieve its exportID:
    exportTo, err := ecdsa.ExportID(secretShare)
    if err != nil {
        panic(err)
    }
    // It will then propagate this KeygenID to the other parties
    // Threshold (t) parties will now need to join the export room
    privkey, err := ecdsa.ExportFullPrivateKey(exportRoomUuid, secretShare, exportTo)
    if err != nil {
        panic(err)
    }

    // privkey is "" except for the party with exportTo as its KeygenID
    // For the exporting party it will be a normal base58 string xpriv - more details in the link below
    // It is most likely that importing the key elsewhere will only be supported for specific derivation paths
    // Hence, it is possible to get the derived private key as well as public key for any derivation path
    derivationPath := []uint32{44, 60, 0, 0, 0}
    derivedPrivateKey, err := ecdsa.DerivePrivateKeyFromXpriv(privkey, derivationPath)
    if err != nil {
        panic(err)
    }
    derivedPubKey, err := ecdsa.DerivePubkey(secretShare, derivationPath)
    if err != nil {
        panic(err)
    }
    // derivedPrivateKey is the private key for derivedPubKey and can now be imported into any non-MPC based ECDSA signing software
    _, _ = derivedPrivateKey, derivedPubKey
    ```

    :::tip[API reference]
    Full details can be found [here](/go/api-ref#func-ecdsa-exportfullprivatekey).
    :::
  </Tab>

  <Tab title="Ed25519 Go">
    ```go
    import "github.com/sodot-rs/sodot-go-sdk"

    const N = 3
    const T = 2
    const API_KEY = "MY_API_KEY"
    // An Ed25519SecretShare was generated using Keygen
    // secretShare, pk, err := ed25519.Keygen(...)
    var secretShare sodot.Ed25519SecretShare
    ed25519 := sodot.NewEd25519("")
    exportRoomUuid, err := ed25519.CreateRoom(N, API_KEY)
    if err != nil {
        panic(err)
    }

    // Only one of the parties will receive the full private key, this party will retrieve its exportID:
    exportTo, err := ed25519.ExportID(secretShare)
    if err != nil {
        panic(err)
    }
    // It will then propagate this KeygenID to the other parties
    // Threshold (t) parties will now need to join the export room
    privkey, err := ed25519.ExportFullPrivateKey(exportRoomUuid, secretShare, exportTo)
    if err != nil {
        panic(err)
    }

    // privkey is "" except for the party with exportTo as its KeygenID
    // For the exporting party it will be an extended private key in a custom format (spriv) - more details in the link below
    // It is most likely that importing the key elsewhere will only be supported for specific derivation paths
    // Hence, it is possible to get the derived private key as well as public key for any derivation path
    derivationPath := []uint32{44, 60, 0, 0, 0}
    derivedPrivateKey, err := ed25519.DerivePrivateKeyFromSpriv(privkey, derivationPath)
    if err != nil {
        panic(err)
    }
    derivedPubKey, err := ed25519.DerivePubkey(secretShare, derivationPath)
    if err != nil {
        panic(err)
    }
    // derivedPrivateKey is the private key for derivedPubKey and can now be imported into any non-MPC based Ed25519 signing software
    _, _ = derivedPrivateKey, derivedPubKey
    ```

    :::tip[API reference]
    Full details can be found [here](/go/api-ref#func-ed25519-exportfullprivatekey).
    :::
  </Tab>
</Tabs>
