PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-core/src/bitgo/enterprise
Просмотр файла: enterprise.ts
/**
* @prettier
*/
import * as _ from 'lodash';
import { IBaseCoin } from '../baseCoin';
import { BitGoBase } from '../bitgoBase';
import { EnterpriseData, EnterpriseFeatureFlag, IEnterprise } from '../enterprise';
import { getFirstPendingTransaction } from '../internal';
import { ListWalletOptions, Wallet } from '../wallet';
import { BitGoProofSignatures, EcdsaUtils, SerializedNtildeWithVerifiers } from '../utils/tss/ecdsa';
import { EcdsaTypes } from '@bitgo/sdk-lib-mpc';
import { verifyEcdhSignature } from '../ecdh';
import { Buffer } from 'buffer';
import { EcdhDerivedKeypair } from '../keychain';
export class Enterprise implements IEnterprise {
private readonly bitgo: BitGoBase;
private readonly baseCoin: IBaseCoin;
public readonly id: string;
public readonly name: string;
public readonly _enterprise: EnterpriseData;
constructor(bitgo: BitGoBase, baseCoin: IBaseCoin, enterpriseData: EnterpriseData) {
this.bitgo = bitgo;
this.baseCoin = baseCoin;
if (!_.isObject(enterpriseData)) {
throw new Error('enterpriseData has to be an object');
}
if (!_.isString(enterpriseData.id)) {
throw new Error('enterprise id has to be a string');
}
if (!_.isString(enterpriseData.name)) {
throw new Error('enterprise name has to be a string');
}
this._enterprise = enterpriseData;
this.id = enterpriseData.id;
this.name = enterpriseData.name;
}
/**
* Enterprise URL for v1 methods, such as getting users
* @param query
*/
url(query = ''): string {
return this.bitgo.url(`/enterprise/${this.id}${query}`);
}
/**
* Enterprise URL for v2 methods, such as getting fee address balances
* @param query
*/
coinUrl(query = ''): string {
return this.baseCoin.url(`/enterprise/${this.id}${query}`);
}
/**
* Get the wallets associated with this Enterprise
* @param params
*/
async coinWallets(params: ListWalletOptions = {}): Promise<Wallet[]> {
if (params.skip && params.prevId) {
throw new Error('cannot specify both skip and prevId');
}
const walletData = (await this.bitgo
.get(this.baseCoin.url('/wallet/enterprise/' + this.id))
.query(params)
.result()) as any;
return walletData.wallets.map((w) => {
return new Wallet(this.bitgo, this.baseCoin, w);
});
}
/**
* Get the users associated with this Enterprise
* @param params
*/
async users(params: Record<string, never> = {}): Promise<any> {
return await this.bitgo.get(this.url('/user')).result();
}
/**
* Get the fee address balance for this Enterprise
* @param params
*/
async getFeeAddressBalance(params: Record<string, never> = {}): Promise<any> {
return await this.bitgo.get(this.coinUrl('/feeAddressBalance')).result();
}
/**
* Add a user to this Enterprise
* @param params
*/
async addUser(params: any = {}): Promise<any> {
return await this.bitgo.post(this.url('/user')).send(params).result();
}
/**
* Remove a user from this Enterprise
* @param params
*/
async removeUser(params: any = {}): Promise<any> {
return await this.bitgo.del(this.url('/user')).send(params).result();
}
/**
* Get the first pending transaction for this Enterprise
* @param params
*/
async getFirstPendingTransaction(params: Record<string, never> = {}): Promise<any> {
return getFirstPendingTransaction({ enterpriseId: this.id }, this.baseCoin, this.bitgo);
}
/**
* Verifies and signs bitgo proofs for the enterprise
* @param userPassword - enterprise admin's login password
*/
async verifyEcdsaBitGoChallengeProofs(userPassword: string): Promise<BitGoProofSignatures> {
return EcdsaUtils.getVerifyAndSignBitGoChallenges(this.bitgo, this.id, userPassword);
}
/**
* Manages all the challenges and signatures and uploads them to enable
* ECDSA signing on enterprise. Also generates a client side Ntilde challenge
* if not provided, but note that can take approx. a minute.
* @param userPassword
* @param bitgoInstChallengeProofSignature
* @param bitgoNitroChallengeProofSignature
* @param challenge
*/
async uploadAndEnableTssEcdsaSigning(
userPassword: string,
bitgoInstChallengeProofSignature: Buffer,
bitgoNitroChallengeProofSignature: Buffer,
openSSLBytes: Uint8Array,
challenge?: EcdsaTypes.DeserializedNtildeWithProofs
): Promise<void> {
await EcdsaUtils.initiateChallengesForEnterprise(
this.bitgo,
this.id,
userPassword,
bitgoInstChallengeProofSignature,
bitgoNitroChallengeProofSignature,
openSSLBytes,
challenge
);
}
/**
* Fetches the existing TSS ECDSA enterprise challenge if one exists.
* Can be used with uploadAndEnableTssEcdsaSigning to re-sign the
* enterprise challenge with new signatures.
*/
async getExistingTssEcdsaChallenge(): Promise<EcdsaTypes.DeserializedNtildeWithProofs> {
const urlPath = `/enterprise/${this.id}/tssconfig`;
const tssConfig = await this.bitgo.get(this.bitgo.url(urlPath, 2)).send().result();
const enterpriseChallenge = tssConfig?.ecdsa.challenge?.enterprise;
if (!enterpriseChallenge) {
throw new Error('No existing ECDSA challenge on the enterprise.');
}
if (!enterpriseChallenge.ntildeProof) {
throw new Error(
'Existing ECDSA challenge does not have a proof. Please contact your enterprise admin to set this up.'
);
}
return EcdsaTypes.deserializeNtildeWithProofs({
ntilde: enterpriseChallenge.ntilde,
h1: enterpriseChallenge.h1,
h2: enterpriseChallenge.h2,
ntildeProof: enterpriseChallenge.ntildeProof,
});
}
/**
* Resigns the enterprise and bitgo challenges with a new ECDH keychain.
* Verifies that the old keychain signed the challenges previously.
* @param oldEcdhKeypair - the old keychain that signed the challenges
* @param newEcdhKeypair - the new keychain that will sign the challenges
* @param entChallenge - existing signed enterprise challenge
* @param bitgoInstChallenge - existing signed bitgo institutional challenge
* @param bitgoNitroChallenge - existing signed bitgo nitro challenge
*/
async resignEnterpriseChallenges(
oldEcdhKeypair: EcdhDerivedKeypair,
newEcdhKeypair: EcdhDerivedKeypair,
entChallenge: SerializedNtildeWithVerifiers,
bitgoInstChallenge: SerializedNtildeWithVerifiers,
bitgoNitroChallenge: SerializedNtildeWithVerifiers
): Promise<void> {
// Verify all the challenges were signed by the old keypair
if (
!verifyEcdhSignature(
EcdsaUtils.getMessageToSignFromChallenge(entChallenge),
entChallenge.verifiers.adminSignature,
Buffer.from(oldEcdhKeypair.derivedPubKey, 'hex')
)
) {
throw new Error(`Cannot re-sign. The Enterprise TSS config was signed by another user.`);
}
if (
!verifyEcdhSignature(
EcdsaUtils.getMessageToSignFromChallenge(bitgoInstChallenge),
bitgoInstChallenge.verifiers.adminSignature,
Buffer.from(oldEcdhKeypair.derivedPubKey, 'hex')
)
) {
throw new Error(`Cannot re-sign. The BitGo Institutional TSS config was signed by another user.`);
}
if (
!verifyEcdhSignature(
EcdsaUtils.getMessageToSignFromChallenge(bitgoNitroChallenge),
bitgoNitroChallenge.verifiers.adminSignature,
Buffer.from(oldEcdhKeypair.derivedPubKey, 'hex')
)
) {
throw new Error(`Cannot re-sign. The BitGo Nitro TSS config was signed by another user.`);
}
// Once all the challenges are verified, we can re-sign them with the new keypair.
const signedEntChallenge = EcdsaUtils.signChallenge(
entChallenge,
newEcdhKeypair.xprv,
newEcdhKeypair.derivationPath
);
const signedBitGoInstChallenge = EcdsaUtils.signChallenge(
bitgoInstChallenge,
newEcdhKeypair.xprv,
newEcdhKeypair.derivationPath
);
const signedBitGoNitroChallenge = EcdsaUtils.signChallenge(
bitgoNitroChallenge,
newEcdhKeypair.xprv,
newEcdhKeypair.derivationPath
);
await EcdsaUtils.uploadChallengesToEnterprise(
this.bitgo,
this.id,
entChallenge,
signedEntChallenge.toString('hex'),
signedBitGoInstChallenge.toString('hex'),
signedBitGoNitroChallenge.toString('hex')
);
}
/**
* Check if the enterprise has a set of featureFlags
* @param flags
*/
hasFeatureFlags(flags: EnterpriseFeatureFlag[]): boolean {
return flags.every((targetFlag) => this._enterprise.featureFlags?.includes(targetFlag));
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!