Import Key
Import an existing private key into an MPC wallet. The key is split into two shares, one on the device, one on the Duo Server, so that after import it is never held in one place again. This is a common use case when onboarding existing EOA wallets into MPC custody.
Importing means the original private key existed in full at some point, so it does not carry the same "never assembled" guarantee as a key generated with keygen. The MPC security guarantees only apply after the import is complete. Handle the source key carefully.
- ECDSA
- EdDSA
import { type EcdsaSession } from '@silencelaboratories/silent-shard-sdk/ecdsa';
export const importKey = async (
session: EcdsaSession,
privateKey: string = '<PRIVATE_KEY_YOU_WANT_TO_IMPORT_IN_HEX>',
rootChainCode: string = '<BIP32 ROOT CHAIN CODE>'
) => {
const importConfig = {
privateKey,
rootChainCode,
};
const importedKeyshare = await session.import(importConfig);
console.log('Imported keyshare: ', importedKeyshare.keyIdHex);
};
import { type EddsaSession } from '@silencelaboratories/silent-shard-sdk/eddsa';
export const importKey = async (
session: EddsaSession,
// The private key to be imported. It's a 32-byte hex string.
privateKey: string = '<PRIVATE_KEY_YOU_WANT_TO_IMPORT_IN_HEX>'
) => {
const importConfig = {
privateKey,
};
const importedKeyshare = await session.import(importConfig);
console.log('Imported keyshare: ', importedKeyshare.publicKeyHex);
};
Please refer to the Session creation guide to learn how to create a session.
session.import()takes animportConfig(an EcdsaImportConfig) object withprivateKeyandrootChainCode.privateKeyis the hex string of the private key to import (32 bytes).rootChainCodeis the BIP32 root chain code as a 32-byte hex string. If you don't have one, use a cryptographically secure random 32 bytes.- Returns a new keyshare (an Keyshare) representing the client's share of the now-split MPC wallet.
- ECDSA
- EdDSA
- Taproot
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<sdk.DklsKeyshare> importKey(
sdk.EcdsaSession session,
String privateKey, // PRIVATE_KEY_YOU_WANT_TO_IMPORT_IN_HEX
String? rootChainCode // BIP32 ROOT CHAIN CODE
) async {
final sdk.DklsKeyshare keyshare = await session.import(
privateKey: privateKey,
rootChainCode: rootChainCode,
);
print(
'Imported private key and created keyshare, public key: ${keyshare.publicKeyHex}');
return keyshare;
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> importKey(
sdk.EddsaSession session,
String privateKey, // PRIVATE_KEY_YOU_WANT_TO_IMPORT_IN_HEX
) async {
final keyshare = await session.import(
privateKey: privateKey,
);
print(
'Imported private key and created keyshare, public key: ${keyshare.publicKeyHex}');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<sdk.TaprootKeyshare> importKey(
sdk.TaprootSession session,
String privateKey, // PRIVATE_KEY_YOU_WANT_TO_IMPORT_IN_HEX
) async {
final sdk.TaprootKeyshare keyshare = await session.import(
privateKey: privateKey,
);
print(
'Imported private key and created keyshare, public key: ${keyshare.publicKeyHex}');
return keyshare;
}
Please refer to the Session creation guide to learn how to create a session.
session.import()takes an import config withprivateKeyandrootChainCode.privateKeyis the hex string of the private key to import (32 bytes).rootChainCodeis the BIP32 root chain code as a 32-byte hex string. If you don't have one, use a cryptographically secure random 32 bytes.- Returns a new keyshare (a DklsKeyshare) representing the client's share of the now-split MPC wallet.
// import brings an existing private key under two-party MPC and returns the new
// keyId. The keyshare is persisted to your StorageClient — keep the keyId to
// address it in later operations (sign, refresh, export, delete, …).
suspend fun performKeyImport(keysharePrivateKey: ByteArray, duoSession: DuoSession): String {
return withContext(Dispatchers.IO) {
duoSession.import(
keysharePrivateKey = keysharePrivateKey, rootChainCode = getRootChainCode(),
).getOrThrow()
}
}
Please refer to the Session creation guide to learn how to create a session.
- Call duoSession.import() with
keysharePrivateKeyandrootChainCode, both asByteArray. keysharePrivateKeyis the private key to import (32 bytes).rootChainCodeis the BIP32 root chain code (32 bytes). If you don't have one, use a cryptographically secure random 32 bytes.- The result is a
Resulttype:Successwith the newkeyId(aString), orFailurewith anException. The imported keyshare is persisted to your StorageClient and addressed by thatkeyId.
// import brings a raw private key back under two-party MPC and returns a new
// keyId (a String). The resulting keyshare is persisted to your StorageClient;
// keep the keyId to address it in later operations.
func performImport(keysharePrivateKey: Data, duoSession: DuoSession) async -> String? {
let result = await duoSession.import(
keysharePrivateKey: keysharePrivateKey,
rootChainCode: getRootChainCode()
)
// returns nil if the operation fails, or handle it however your flow needs
switch result {
case .success(let keyId):
// do something with the keyId
Swift.print(keyId)
return keyId
case .failure(let error):
// show the error to the user or abort the process
Swift.print(error)
return nil
}
}
Please refer to the Session creation guide to learn how to create a session.
- Call duoSession.import() with
privateKeyandrootChainCode, both asData. privateKeyis the private key to import (32 bytes).rootChainCodeis the BIP32 root chain code (32 bytes). If you don't have one, use a cryptographically secure random 32 bytes.- The result is a
Resulttype:Successwith the newkeyId(aString), orFailurewith an error. The imported keyshare is persisted to your StorageClient and addressed by thatkeyId.