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
App.tsx
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);
};
App.tsx
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
main.dart
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');
}
main.dart
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');
}
main.dart
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
Example.kt
suspend fun deriveChildPublicKeyUsingKeyshare(
keyId: String,
duoSession: DuoSession,
): ByteArray {
return withContext(Dispatchers.IO) {
//signature example for context
duoSession.sign(
keyId = keyId,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g. 'm/1/2'
).getOrThrow()
// child public key derivation runs on keyshare bytes — read them from your
// StorageClient by keyId.
val keyshare = (storageClient.read(keyId) as ReconcileStoreDao).currentKeyshare!!
SilentShard.ECDSA.deriveChildPublicKey(
keyshare = keyshare,
derivationPath = "m/1"
).getOrThrow()
}
}
Example.kt
suspend fun deriveChildPublicKeyUsingKeyshare(
keyId: String,
duoSession: DuoSession,
): ByteArray {
return withContext(Dispatchers.IO) {
//signature example for context
duoSession.sign(
keyId = keyId,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g. 'm/1/2'
).getOrThrow()
// child public key derivation runs on keyshare bytes — read them from your
// StorageClient by keyId.
val keyshare = (storageClient.read(keyId) as ReconcileStoreDao).currentKeyshare!!
SilentShard.EdDSA.deriveChildPublicKey(
keyshare = keyshare,
derivationPath = "m/1"
).getOrThrow()
}
}
- When duoSession.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.
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
Example.swift
// deriveChildPublicKey is a stateless helper that takes keyshare bytes, so first
// read the share from your StorageClient by its keyId (the SDK owns keyshare
// storage under the keyId model), then derive the child public key.
func deriveChildPublicKeyUsingKeyId(
keyId: String, storageClient: CustomStorageClient
) async -> Data? {
// Read the keyshare addressed by keyId from your own storage.
guard let dao = try? await storageClient.read(key: keyId),
let keyshare = dao.currentKeyshare else {
// no keyshare is stored for this keyId
return nil
}
// Derive the child public key at the desired path.
let result = await SilentShard.ECDSA.deriveChildPublicKey(
keyshare,
derivationPath: "m/1" // This is an example; use your desired path, e.g. "m/1/2"
)
// returns nil if operation fails or other flow you might have
switch result {
case .success(let childPublicKey):
// do something with the derived child public key bytes
Swift.print(childPublicKey)
return childPublicKey
case .failure(let error):
// show error to user or abort process
Swift.print(error)
return nil
}
}
Example.swift
// deriveChildPublicKey is a stateless helper that takes keyshare bytes, so first
// read the share from your StorageClient by its keyId (the SDK owns keyshare
// storage under the keyId model), then derive the child public key.
func deriveChildPublicKeyUsingKeyId(
keyId: String, storageClient: CustomStorageClient
) async -> Data? {
// Read the keyshare addressed by keyId from your own storage.
guard let dao = try? await storageClient.read(key: keyId),
let keyshare = dao.currentKeyshare else {
// no keyshare is stored for this keyId
return nil
}
// Derive the child public key at the desired path.
let result = await SilentShard.EdDSA.deriveChildPublicKey(
keyshare,
derivationPath: "m/1" // This is an example; use your desired path, e.g. "m/1/2"
)
// returns nil if operation fails or other flow you might have
switch result {
case .success(let childPublicKey):
// do something with the derived child public key bytes
Swift.print(childPublicKey)
return childPublicKey
case .failure(let error):
// show error to user or abort process
Swift.print(error)
return nil
}
}
- When duoSession.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.