Skip to main content

Export Key

Please refer to the Session creation section to learn how to create a new session.

Users can at any time request to "export" their keys into a private key (EOA) and stop using an MPC wallet.

warning

Once the private key is exported, the guarantees of MPC are lost.

info

Since this operation is a sensitive operations, we don't expose it directly in the SDK. Instead we provide an endpoint in the cloud node /v3/export that can be used to get the encrypted share of the cloud node. We provide a method in the client SDK to combine the client and server shares to recover the full private key.

It's the responsibility of the company using the SDK to expose this endpoint to the user in a secure way.

For e.g:

  • When the user requests to export the private key. The backend can request additional authentication from the user (e.g: 2FA) before exporting the private key.
  • Once the user is authenticated, the backend can get the encrypted share from the cloud node and pass it to the user.
  • The user can decrypt the share and recover the full private key using the ecdsaDuoKeyExport method.

Get the encrypted share of the cloud node by making a POST request to the /v3/export endpoint.

warning

The /v3/export endpoint is not exposed directly in the SDK. Here for the sake of simplicity, we will use the fetch method to make the request from the client. Do NOT expose this endpoint to the user directly in a production application.

Full Example

main.dart
import 'dart:convert';
import 'dart:io';
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
import 'package:http/http.dart' as http;

const port = 8080;
final nodeUri = Platform.isAndroid ? '10.0.2.2:$port' : '0.0.0.0:$port';

Future<String> exportKey(sdk.EcdsaSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final sdk.DklsKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');

// Export
final clientEncKeys = sdk.DklsEncryptionKey();
final exportUrl = 'http://$nodeUri/v3/ecdsa/export';
final response = await http.post(Uri.parse(exportUrl),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
"key_id": keyshare.keyIdHex,
"client_enc_pubkey": clientEncKeys.publicKeyHex,
}));
print('Response: ${response.body}');

final exportResponse = ExportResponse.fromJson(jsonDecode(response.body));
print('Export response: ${exportResponse.encServerShare} ${exportResponse.serverPublicKey} ${exportResponse.keyId} ${clientEncKeys.publicKeyHex}');

final privateKey = sdk.ecdsaDuoKeyExport(
keyshare: keyshare,
serverEncrptedKeyshare: exportResponse.encServerShare,
serverEncryptionPublicKey: exportResponse.serverPublicKey,
clientEncryptionKeys: clientEncKeys,
);
print('Exported private key: $privateKey');

return privateKey;
}

class ExportResponse {
final String serverPublicKey;
final String encServerShare;
final String keyId;

ExportResponse.fromJson(Map<String, dynamic> json)
: keyId = json['key_id'],
encServerShare = json['enc_server_share'],
serverPublicKey = json['server_public_key'];
}
  • The request body format is documented in the export endpoint.
    • key_id: The key ID of the keyshare. Unique identifier for a wallet, 32 byte base64 encoded string.
    • client_enc_pubkey: The encryption public key of the client. Base64 encoded string.
  • exportJson: The response from the export endpoint. It contains the encrypted share of the cloud node.
  • serverEncrptedKeyshare: The encrypted server share. (This is included in the response from the export endpoint)
  • serverEncryptionPublicKey: The server's encryption public key. (This is included in the response from the export endpoint)
  • clientEncryptionKeys: The DklsEncryptionKey for decrypting the server response.
  • privateKey: The expored private key in hex format.