BIP32 Support
Please refer to the Session creation section to learn how to create a new session.
We support generating signatures for a BIP32 child key. Perform keygen once, and generate signatures for all BIP32 child keys!
Full example:
- ECDSA
- EdDSA
import { type EcdsaSession } from '@silencelaboratories/silent-shard-sdk/ecdsa';
const messageHash = 'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
// We will MPC functions here
export const keyDerivation = async (session: EcdsaSession) => {
// Keygen
const keyshare = await session.keygen();
console.log('Generated keyshare: ', keyshare.keyIdHex);
const signConfig = {
keyshare,
messageHash,
derivationPath: 'm', // This is the default, use your desired path here. For e.g., 'm/1/2'
};
const signature = await session.sign(signConfig);
console.log('Signature:', signature);
// Get public key of newly generated wallet
const publicKey = keyshare.publicKeyHex;
console.log('Public key:', publicKey);
// Derive a child public key from keyshare
const derivedPublicKey = await keyshare.deriveChildPublicKey('m');
console.log('Derived public key:', derivedPublicKey);
};
import { type EddsaSession } from '@silencelaboratories/silent-shard-sdk/eddsa';
const messageHash = 'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
// We will MPC functions here
export const keyDerivation = async (session: EddsaSession) => {
// Keygen
const keyshare = await session.keygen();
console.log('Generated keyshare: ', keyshare.keyIdHex);
const signConfig = {
keyshare,
messageHash,
derivationPath: 'm', // This is the default, use your desired path here. For e.g., 'm/1/2'
};
const signature = await session.sign(signConfig);
console.log('Signature:', signature);
// Get public key of newly generated wallet
const publicKey = keyshare.publicKeyHex;
console.log('Public key:', publicKey);
// Derive a child public key from keyshare
const derivedPublicKey = await keyshare.deriveChildPublicKey('m');
console.log('Derived public key:', derivedPublicKey);
};
- When
session.sign(signConfig)(EcdsaSignConfig) is called with aderivationPath, the signature is generated for the specified BIP32 derivation path. derivationPathis a string that specifies the path to the child key. It defaults to 'm' (no derivation) if not provided.
Please refer to the Session creation section to learn how to create a new session.
We support generating signatures for a BIP32 child key. Perform keygen once, and generate signatures for all BIP32 child keys!
Full example:
- ECDSA
- EdDSA
- Taproot
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
Future<void> keyDerivation(sdk.EcdsaSession session) async {
// Keygen
final sdk.DklsKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final signature = await session.sign(
keyId: keyshare.keyId,
messageHash: messageHash,
derivationPath:
'm', // This is the default, use your desired path here. For e.g 'm/1/2'
);
print('Signature: $signature');
final publicKey = keyshare.publicKeyHex;
print('Public key: $publicKey');
final derivedPublicKey = keyshare.deriveChildPublicKeyHex('m');
print('Derived public key: $derivedPublicKey');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
Future<void> keyDerivation(sdk.EddsaSession session) async {
// Keygen
final sdk.SchnorrKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final signature = await session.sign(
keyId: await keyshare.keyId,
messageHash: messageHash,
derivationPath:
'm', // This is the default, use your desired path here. For e.g 'm/1/2'
);
print('Signature: $signature');
final publicKey = keyshare.publicKeyHex;
print('Public key: $publicKey');
final derivedPublicKey = keyshare.deriveChildPublicKeyHex('m');
print('Derived public key: $derivedPublicKey');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
Future<void> keyDerivation(sdk.TaprootSession session) async {
// Keygen
final sdk.TaprootKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final signature = await session.sign(
keyId: keyshare.keyId,
messageHash: messageHash,
);
print('Signature: $signature');
final derivedPublicKey = keyshare.deriveChildPublicKeyHex('m/86/0/0/0/0');
print('Derived public key: $derivedPublicKey');
}
- When
session.sign()is called with aderivationPath, the signature is generated for the specified BIP32 derivation path. derivationPathis a string that specifies the path to the child key. It defaults to 'm' (no derivation) if not provided.
We support generating signatures for a BIP32 child key. Perform keygen once, and generate signatures for all BIP32 child keys!
Perform Derive Child Public-Key
- Call SilentShard.ECDSA.deriveChildPublicKey() or SilentShard.EdDSA.deriveChildPublicKey() which returns Result of Success with Child Public-Key ByteArray or Failure with exception.
Example
- ECDSA
- EdDSA
suspend fun deriveChildPublicKeyUsingKeyshare(
keyId: String,
trioSession: TrioSession,
storageClient: StorageClient,
): ByteArray {
return withContext(Dispatchers.IO) {
//signature example for context
trioSession.sign(
keyId = keyId,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g. 'm/1/2'
).getOrThrow()
// Read the keyshare bytes from your StorageClient by keyId.
val keyshare = (storageClient.read(keyId) as ReconcileStoreDao).currentKeyshare!!
// child public key derivation
SilentShard.ECDSA.deriveChildPublicKey(
keyshare = keyshare,
derivationPath = "m/1"
).getOrThrow()
}
}
suspend fun deriveChildPublicKeyUsingKeyshare(
keyId: String,
trioSession: TrioSession,
storageClient: StorageClient,
): ByteArray {
return withContext(Dispatchers.IO) {
//signature example for context
trioSession.sign(
keyId = keyId,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g. 'm/1/2'
).getOrThrow()
// Read the keyshare bytes from your StorageClient by keyId.
val keyshare = (storageClient.read(keyId) as ReconcileStoreDao).currentKeyshare!!
// child public key derivation
SilentShard.EdDSA.deriveChildPublicKey(
keyshare = keyshare,
derivationPath = "m/1"
).getOrThrow()
}
}
- When trioSession.sign() is called with a
derivationPath, the signature is generated for the specified BIP32 derivation path. derivationPathis a string that specifies the path to the child key. It defaults to 'm' (no derivation) if not provided.
The derivation above computes a child public key from your existing key. For ECDSA sessions, hardDerivation(keyId, derivationPath) performs an MPC hardened derivation and returns a new child keyId that you can sign with directly.
We support generating signatures for a BIP32 child key. Perform keygen once, and generate signatures for all BIP32 child keys!
Perform Derive Child Public-Key
- Call SilentShard.ECDSA.deriveChildPublicKey() or SilentShard.EdDSA.deriveChildPublicKey() which returns
ResultofSuccesswith Child Public-Key bytes asDataor Failure witherror.
Example
- ECDSA
- EdDSA
// deriveChildPublicKey computes a child public key locally, without any MPC round.
// It takes keyshare bytes, which you read from your own StorageClient by keyId
// (the SDK owns keyshare storage). This is a public-key-only derivation — for a
// signable child keyshare use trioSession.hardDerivation(keyId:derivationPath:).
func deriveChildPublicKey(keyshare: Data) async -> Data? {
let result = await SilentShard.ECDSA.deriveChildPublicKey(
keyshare,
derivationPath: "m/1" // your desired BIP32 path
)
// returns nil if the operation fails, or handle it however your flow needs
switch result {
case .success(let childPublicKey):
// do something with the child public-key bytes
Swift.print(childPublicKey)
return childPublicKey
case .failure(let error):
// show the error to the user or abort the process
Swift.print(error)
return nil
}
}
// deriveChildPublicKey computes a child public key locally, without any MPC round.
// It takes keyshare bytes, which you read from your own StorageClient by keyId
// (the SDK owns keyshare storage).
func deriveChildPublicKey(keyshare: Data) async -> Data? {
let result = await SilentShard.EdDSA.deriveChildPublicKey(
keyshare,
derivationPath: "m/1" // your desired BIP32 path
)
// returns nil if the operation fails, or handle it however your flow needs
switch result {
case .success(let childPublicKey):
// do something with the child public-key bytes
Swift.print(childPublicKey)
return childPublicKey
case .failure(let error):
// show the error to the user or abort the process
Swift.print(error)
return nil
}
}
- When trioSession.sign() is called with a
derivationPath, the signature is generated for the specified BIP32 derivation path. derivationPathis a string that specifies the path to the child key. It defaults to 'm' (no derivation) if not provided.