Set Up Enterprise Challenge

Overview

Set up a static range-proof challenge to enable transaction signing for ECDSA assets (such as ETH and MATIC) from your self-managed hot TSS wallets. Once set up, all the wallets in your enterprise use the challenge during transaction signing, including both payment transactions and message transactions.

Challenges are an important security protocol that enable cosigners to verify critical invariants that protect their key shares during the TSS protocol. The BitGo JavaScript SDK generates challenges using large safe-prime numbers. Safe primes enable an extra layer of security against certain types of attacks, such as Pollard's p-1 algorithm and the quadratic sieve algorithm.

When you set up an enterprise challenge, you sign the enterprise-configuration file with your private key and BitGo verifies that you're an active enterprise administrator. When invoking the static challenge during signing, cosigners validate the admin signature is from an active administrator.

Prerequisites

Get Started

Steps

1. Set Up Script

  • SDK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /* The following examples are made using the following dependencies "dependencies": { ... "@bitgo/sdk-api": "1.11.2", "@bitgo/sdk-lib-mpc": "8.5.0", "@bitgo/sdk-coin-eth": "4.5.4", "@bitgo/sdk-core": "8.10.0", ... } */ import { BitGoAPI } from "@bitgo/sdk-api"; import { Enterprise, ECDSAUtils } from "@bitgo/sdk-core"; import { Eth } from "@bitgo/sdk-coin-eth"; import { EcdsaRangeProof, EcdsaTypes } from "@bitgo-beta/sdk-lib-mpc"; const enterpriseUserName = process.env.username!; const enterprisePassword = process.env.password!; const sdk = new BitGoAPI(); sdk.register('btc', Eth.createInstance); const baseCoin = sdk.coin('eth'); async function authenticate() { await sdk.authenticate({ username: enterpriseUserName, password: enterprisePassword, otp: "my OTP", }); }

2. Verify BitGo TSS Challenges

  • SDK
1 2 3 4 5 6 7 8 9 10 async function verifyBitgoChallenges(enterpriseId: string) { const enterprise = new Enterprise(sdk, baseCoin, { id: enterpriseId, name: "", }); const res = await enterprise.verifyEcdsaBitGoChallengeProofs(enterprisePassword); console.log(JSON.stringify(res)); return res } authenticate().then(() => {verifyBitgoChallenges('my enterprise id')});

Step Result

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { "bitgoInstHsmAdminSignature": { "type": "Buffer", "data": [ 202, 169, 45, 136, 228, 48, 41, 134, 67, 187, 57, 79, 185, 36, 14, 95, 243, 189, 18, 38, 51, 158, 145, 122, 248, 18, 18, 58, 240, 173, 151, 128, 56, 199, 159, 19, 113, 84, 251, 117, 30, 215, 110, 134, 166, 91, 127, 162, 1, 52, 174, 52, 32, 54, 226, 140, 109, 15, 187, 183, 64, 87, 110, 141 ] }, "bitgoNitroHsmAdminSignature": { "type": "Buffer", "data": [ 202, 169, 45, 136, 228, 48, 41, 134, 67, 187, 57, 79, 185, 36, 14, 95, 243, 189, 18, 38, 51, 158, 145, 122, 248, 18, 18, 58, 240, 173, 151, 128, 56, 199, 159, 19, 113, 84, 251, 117, 30, 215, 110, 134, 166, 91, 127, 162, 1, 52, 174, 52, 32, 54, 226, 140, 109, 15, 187, 183, 64, 87, 110, 141 ] } }

3. Create an Enterprise TSS Challenge

Generate a challenge on your local machine. This may take 30 seconds to 2 minutes, depending on your machine.

1 2 3 4 5 6 async function createEnterpriseChallenge() { const challenge = await EcdsaRangeProof.generateNtilde(); console.log(JSON.stringify(EcdsaTypes.serializeNtilde(challenge))); return challenge; } authenticate().then(() => {createEnterpriseChallenge()});

Step Result

Wallet users can resume signing transactions.

  • SDK
1 2 3 4 5 { "ntilde": "ee49fff1b2da7b3a7ea9ab2ac488530757af57b6f2666f433861f79f34e2866766e6ba50df6032ab4f3183b95a16f3235252bb3e25806a9ef1465746a82f356b0cdae4dbc225e253d683bfa9395aa50ab9dfbd5155122f3217ef51684bd31461b16e5bac223a648785db29af10d2a93020547cf08f9bc7eeed8dd090b4b5c7974699bc9f30828a3c285d39bc96bce24aa0479bfa3855402f08606772f3ad3d89bdb7d9a19561df8b894022f4691121cc2d4465d54d3c31d96870be10197288482be9b8af714dc030306159fa94b4ad6bc85c733040d91ce00362e59621eb905e640fe9befc0b903e67a05791c7bccff587fa52093cd19195c958c7eda4f130db636117b7903faa979a2b5ed12880f65170956dc4cfb7a9000b2497bb801ce9558ee002c8fb1b5e56e1a56b0a315d7ce89e96b6eb87b2e16961661a34fa0ce235d8a6fd17f91a498009cc8144795ffc5ebb98afff0588f3a6823b27a5ea260e3cc79b648bd320dfa29b5d272b2d2f0d7da864403af623a2556d8edece6fce42c9", "h1": "5c6c4f3a6d45df1da8f20bb11d293f2c97b4ed28125b4224c75081fb7bbb1545f9424a9f8da3aaf1c98684fe4520bdb77e4bb93a50892f4108faf46757ee5dcb9d444163eb9ae934883e6152a3db470c9df11568baf370d6515a9459c6492e5d42da6207acc30a64e6220efb739189c0a181e5950a18ad4930b6aa148a2e3f4984071628895fe251fdaf9e1bc044d32991df4f979b801a69d2531ebae32acc091cb5fa8bf5f2f4eca8825b539ef523f2515297fd35c50c21ff1048a83188877f3f38388e53b61b20079ec75a746d3665a3f7e48765f1c6f43761ce4b09746d99b1f976e76d599dc4d13c1fa9f68343ee667fa6b03f6009c63590f79f662a4753fd7a4d793de44c921a7131c9adb2764a1b96b222644c43eee5519c0a3fb46755b209869ccd1426250203378ad2a1dbc742cda7b601d094cf6dd096777e3813cfcc1e1cc5880c0dc6a2c9985f88420d0d3f3b8a77475f6c842980cec022d44d7d15c90b398f1340d0934e8248829e484d36498fe190106bfbb6a8ed20aef816af", "h2": "a5a312eafe5578043c70cd7e8b6d33704aac428dea0a5e2b0c4f196f7a30537f104333ba7824e5b87ca4f205c0a5ac457e086f9375b807140fb6b56d51c8a96f2d66f0a144cbbc8b59133bee488c8bf1527c34fb65266b4f2b3b42a6dab587d9cbd8dd896b14d8a09986778eed83781db309c2a4df86100a3a8c81fc2329676f033e551335d35a2a1b530e55d14c323bcba08a9dbf600aa566d4f7adb8225f6c74435138a464bf273646df3c862e2ad1ad1597b9df796ee3654c306134273384eaa863e6ca27c2c629529318edf11eaf65a28104f63ebe8c3430df58d8a664b726c5eb4e66538d7b5fdac17113ce75df5a3e43336619d902ede00eadb45385503e2812d7adab071774425f13eb99d70bbbcf8c46e7d26e9592874923e18e482c7dfe90cc963e1af93e0754f5f2acf599599252b84035440704f7edf9b83079e7966390261a35b008fcc7a515535be34ec07eaa816696a165e225f37a805526d8258e020ce85d2e7bda7eee9be0dd620de9d6aa58ffb2862c98e1fd2e6eb54197" }

4. Upload Enterprise Challenges

  • SDK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 async function initializeEcdsaOnEnterprise( enterpriseId: string, verifiedBitgoChallenges: ECDSAUtils.BitGoProofSignatures, enterpriseChallenges: EcdsaTypes.DeserializedNtildeWithProofs ) { const enterprise = new Enterprise(sdk, baseCoin, { id: enterpriseId, name: "", }); await enterprise.uploadAndEnableTssEcdsaSigning( enterprisePassword, verifiedBitgoChallenges.bitgoInstHsmAdminSignature, verifiedBitgoChallenges.bitgoNitroHsmAdminSignature, enterpriseChallenges ); } authenticate().then(() => {initializeEcdsaOnEnterprise("my enterprise id", step1Result, step2Result)});

Step Result

Your wallet users can sign transactions for TSS wallets.

Final Script

Your final script should look similar to the follow:

  • SDK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import { BitGoAPI } from "@bitgo/sdk-api"; import { Enterprise, ECDSAUtils } from "@bitgo/sdk-core"; import { Eth } from "@bitgo/sdk-coin-eth"; import { EcdsaRangeProof, EcdsaTypes } from "@bitgo-beta/sdk-lib-mpc"; const enterpriseUserName = process.env.username!; const enterprisePassword = process.env.password!; const sdk = new BitGoAPI({}); sdk.register("btc", Eth.createInstance); const baseCoin = sdk.coin("eth"); async function authenticate() { await sdk.authenticate({ username: enterpriseUserName, password: enterprisePassword, otp: "my OTP", }); } async function verifyBitgoChallenges(enterpriseId: string) { const enterprise = new Enterprise(sdk, baseCoin, { id: enterpriseId, name: "", }); const res = await enterprise.verifyEcdsaBitGoChallengeProofs( enterprisePassword ); console.log(JSON.stringify(res)); return res; } async function createEnterpriseChallenge() { const challenge = await EcdsaRangeProof.generateNtilde(); console.log(JSON.stringify(EcdsaTypes.serializeNtilde(challenge))); return challenge; } async function initializeEcdsaOnEnterprise( enterpriseId: string, verifiedBitgoChallenges: ECDSAUtils.BitGoProofSignatures, enterpriseChallenges: EcdsaTypes.DeserializedNtildeWithProofs ) { const enterprise = new Enterprise(sdk, baseCoin, { id: enterpriseId, name: "", }); await enterprise.uploadAndEnableTssEcdsaSigning( enterprisePassword, verifiedBitgoChallenges.bitgoInstHsmAdminSignature, verifiedBitgoChallenges.bitgoNitroHsmAdminSignature, enterpriseChallenges ); } authenticate().then(() => { verifyBitgoChallenges("my enterprise id").then((verifiedChallenges) => { createEnterpriseChallenge().then((enterpriseChallenges) => { initializeEcdsaOnEnterprise( "my enterprise id", verifiedChallenges, enterpriseChallenges ).then(() => { console.log("Done!"); }); }); }); });

Next

See Also