PHP WebShell
Текущая директория: /opt/BitGoJS/modules/express/test/unit/clientRoutes
Просмотр файла: signPayload.ts
import * as sinon from 'sinon';
import 'should-http';
import 'should-sinon';
import 'should';
import * as fs from 'fs';
import { Request } from 'express';
import { BitGo, Coin, BaseCoin, Wallet, Wallets } from 'bitgo';
import '../../lib/asserts';
import { handleV2OFCSignPayload, handleV2OFCSignPayloadInExtSigningMode } from '../../../src/clientRoutes';
describe('Sign an arbitrary payload with trading account key', function () {
const coin = 'ofc';
const payload = {
this: {
is: {
a: 'payload',
},
},
};
const signature = 'signedPayload123';
const walletId = 'myWalletId';
const walletStub = sinon.createStubInstance(Wallet as any, {
id: walletId,
coin: sinon.stub().returns(coin),
toTradingAccount: sinon.stub().returns({
signPayload: sinon.stub().returns(signature),
}),
});
const walletsStub = sinon.createStubInstance(Wallets as any, {
get: sinon.stub().resolves(walletStub),
});
const coinStub = sinon.createStubInstance(BaseCoin as any, { wallets: sinon.stub().returns(walletsStub) });
const bitGoStub = sinon.createStubInstance(BitGo as any, { coin: sinon.stub().returns(coinStub) });
before(() => {
process.env['WALLET_myWalletId_PASSPHRASE'] = 'mypass';
});
it('should return a signed payload', async function () {
// TODO(GO-1015): unskip test
return;
// eslint-disable-next-line no-unreachable
const expectedResponse = {
payload: JSON.stringify(payload),
signature,
};
const req = {
bitgo: bitGoStub,
body: {
payload,
walletId,
},
query: {},
} as unknown as Request;
await handleV2OFCSignPayload(req).should.be.resolvedWith(expectedResponse);
});
});
describe('With the handler to sign an arbitrary payload in external signing mode', () => {
let bitgo: BitGo;
const walletId = '61f039aad587c2000745c687373e0fa9';
const walletPassword = 'wDX058%c4plL1@pP';
const secret =
'xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2';
const validPrv =
'{"61f039aad587c2000745c687373e0fa9":"{\\"iv\\":\\"+1u1Y9cvsYuRMeyH2slnXQ==\\",\\"v\\":1,\\"iter\\":10000,\\"ks\\":256,\\"ts\\":64,\\"mode\\":\\"ccm\\",\\"adata\\":\\"\\",\\"cipher\\":\\"aes\\",\\"salt\\":\\"54kOXTqJ9mc=\\",\\"ct\\":\\"JF5wQ82wa1dYyFxFlbHCvK4a+A6MTHdhOqc5uXsz2icWhkY2Lin/3Ab8ZwvwDaR1JYKmC/g1gXIGwVZEOl1M/bRHY420h7sDtmTS6Ebse5NWbF0ItfUJlk6HVATGa+C6mkbaVxJ4kQW/ehnT3riqzU069ATPz8E=\\"}"}';
const payload = {
this: {
is: {
a: 'payload',
},
},
};
before(() => {
bitgo = new BitGo({ env: 'test' });
});
it('should return a payload signed with trading account key read from the local file system', async () => {
const stubbedSignature = Buffer.from('mysign');
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
const envStub = sinon
.stub(process, 'env')
.value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword });
const signMessageStub = sinon.stub(Coin.Ofc.prototype, 'signMessage').resolves(stubbedSignature);
const stubbedSigHex = stubbedSignature.toString('hex');
const expectedResponse = {
payload: JSON.stringify(payload),
signature: stubbedSigHex,
};
const req = {
bitgo,
body: {
walletId,
payload,
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.resolvedWith(expectedResponse);
readFileStub.should.be.calledOnceWith('signerFileSystemPath');
signMessageStub.should.be.calledOnceWith(
sinon.match({
prv: secret,
})
);
readFileStub.restore();
envStub.restore();
signMessageStub.restore();
});
it('should use wallet passphrase from request body', async () => {
const stubbedSignature = Buffer.from('mysign');
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
const signMessageStub = sinon.stub(Coin.Ofc.prototype, 'signMessage').resolves(stubbedSignature);
const stubbedSigHex = stubbedSignature.toString('hex');
const expectedResponse = {
payload: JSON.stringify(payload),
signature: stubbedSigHex,
};
const req = {
bitgo,
body: {
walletId,
payload,
walletPassphrase: walletPassword,
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.resolvedWith(expectedResponse);
readFileStub.should.be.calledOnceWith('signerFileSystemPath');
signMessageStub.should.be.calledOnceWith(
sinon.match({
prv: secret,
})
);
readFileStub.restore();
signMessageStub.restore();
});
it('should prioritize request body passphrase over environment variable', async () => {
const stubbedSignature = Buffer.from('mysign');
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
const envStub = sinon
.stub(process, 'env')
.value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword });
const signMessageStub = sinon.stub(Coin.Ofc.prototype, 'signMessage').resolves(stubbedSignature);
const stubbedSigHex = stubbedSignature.toString('hex');
const expectedResponse = {
payload: JSON.stringify(payload),
signature: stubbedSigHex,
};
const req = {
bitgo,
body: {
walletId,
payload,
walletPassphrase: walletPassword,
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.resolvedWith(expectedResponse);
readFileStub.should.be.calledOnceWith('signerFileSystemPath');
signMessageStub.should.be.calledOnceWith(
sinon.match({
prv: secret,
})
);
readFileStub.restore();
envStub.restore();
signMessageStub.restore();
});
describe('With invalid setup', () => {
const invalidPrv = '{"61f039aad587c2000745c687373e0fa9":"invalid"}';
it('should throw an error with missing wallet passphrase in env', async () => {
const req = {
bitgo,
body: {
walletId,
payload,
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith(
'Could not find wallet passphrase WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE in environment'
);
});
it('should throw an error with undefined signerFileSystemPath in env', async () => {
const envStub = sinon
.stub(process, 'env')
.value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword });
const req = {
bitgo,
body: {
walletId,
payload,
},
config: {
signerFileSystemPath: undefined,
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith(
'Missing required configuration: signerFileSystemPath'
);
envStub.restore();
});
it('should throw error when trying to decrypt with invalid private key', async () => {
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(invalidPrv);
const envStub = sinon
.stub(process, 'env')
.value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword });
const req = {
bitgo,
body: {
walletId,
payload,
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith(
"Error when trying to decrypt private key: INVALID: json decode: this isn't json!"
);
readFileStub.restore();
envStub.restore();
});
it('should throw error when trying to decrypt with invalid wallet passphrase key', async () => {
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
const envStub = sinon
.stub(process, 'env')
.value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: 'invalidPassphrase' });
const req = {
bitgo,
body: {
walletId,
payload,
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith(
"Error when trying to decrypt private key: CORRUPT: password error - ccm: tag doesn't match"
);
readFileStub.restore();
envStub.restore();
});
it('should throw error when trying to decrypt with invalid wallet passphrase in body', async () => {
const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
const req = {
bitgo,
body: {
walletId,
payload,
walletPassphrase: 'invalidPassphrase',
},
config: {
signerFileSystemPath: 'signerFileSystemPath',
},
} as unknown as Request;
await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith(
"Error when trying to decrypt private key: CORRUPT: password error - ccm: tag doesn't match"
);
readFileStub.restore();
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!