From 9bab1450dd988ecf11b2128a22f18b13b733f9bb Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Sat, 23 May 2020 07:56:56 -0700 Subject: [PATCH] fix(encryption): Added encryption library --- src/bch-js.js | 3 ++ src/crypto.js | 4 ++ src/encryption.js | 44 +++++++++++++++++ test/integration/encryption.js | 31 ++++++++++++ test/unit/encryption.js | 71 +++++++++++++++++++++++++++ test/unit/fixtures/encryption-mock.js | 19 +++++++ 6 files changed, 172 insertions(+) create mode 100644 src/encryption.js create mode 100644 test/integration/encryption.js create mode 100644 test/unit/encryption.js create mode 100644 test/unit/fixtures/encryption-mock.js diff --git a/src/bch-js.js b/src/bch-js.js index 4f4ad4c..43b6532 100644 --- a/src/bch-js.js +++ b/src/bch-js.js @@ -31,7 +31,9 @@ const Wallet = require("./wallet") const Schnorr = require("./schnorr") const SLP = require("./slp/slp") const IPFS = require("./ipfs") +const Encryption = require("./encryption") +// Indexers const Blockbook = require("./blockbook") const OpenBazaar = require("./openbazaar") const Ninsight = require("./ninsight") @@ -84,6 +86,7 @@ class BCHJS { this.Crypto = Crypto this.ECPair = ECPair this.ECPair.setAddress(this.Address) + this.encryption = new Encryption(libConfig) this.Generating = new Generating(libConfig) this.HDNode = new HDNode(this.Address) this.Mnemonic = new Mnemonic(this.Address) diff --git a/src/crypto.js b/src/crypto.js index 86dfe66..02edebf 100644 --- a/src/crypto.js +++ b/src/crypto.js @@ -29,6 +29,7 @@ class Crypto { static sha256(buffer) { return Bitcoin.crypto.sha256(buffer) } + /** * @api Crypto.ripemd160() ripemd160()-Utility for creating ripemd160 hash. * @apiName ripemd160 @@ -54,6 +55,7 @@ class Crypto { static ripemd160(buffer) { return Bitcoin.crypto.ripemd160(buffer) } + /** * @api Crypto.hash256() hash256() - Utility for creating double sha256 hash. * @apiName hash256 @@ -79,6 +81,7 @@ class Crypto { static hash256(buffer) { return Bitcoin.crypto.hash256(buffer) } + /** * @api Crypto.hash160() hash160() - Utility for creating ripemd160(sha256()) hash. * @apiName hash160 @@ -104,6 +107,7 @@ class Crypto { static hash160(buffer) { return Bitcoin.crypto.hash160(buffer) } + /** * @api Crypto.randomBytes() randomBytes() - Generates cryptographically strong pseudo-random data. * @apiName randomBytes diff --git a/src/encryption.js b/src/encryption.js new file mode 100644 index 0000000..4749bef --- /dev/null +++ b/src/encryption.js @@ -0,0 +1,44 @@ +/* + This library contains useful functions that deal with encryption. +*/ + +const axios = require("axios") + +let _this + +class Encryption { + constructor(config) { + this.restURL = config.restURL + this.apiToken = config.apiToken + this.axios = axios + // console.log(`Blockbook apiToken: ${this.apiToken}`) + + // Add JWT token to the authorization header. + this.axiosOptions = { + headers: { + authorization: `Token ${this.apiToken}` + } + } + + _this = this + } + + // Search the blockchain for a public key associated with a BCH address. + async getPubKey(addr) { + try { + if (!addr || typeof addr !== "string") + throw new Error(`Input must be a valid Bitcoin Cash address.`) + + const response = await _this.axios.get( + `${this.restURL}encryption/publickey/${addr}`, + _this.axiosOptions + ) + return response.data + } catch (error) { + if (error.response && error.response.data) throw error.response.data + else throw error + } + } +} + +module.exports = Encryption diff --git a/test/integration/encryption.js b/test/integration/encryption.js new file mode 100644 index 0000000..61dba3f --- /dev/null +++ b/test/integration/encryption.js @@ -0,0 +1,31 @@ +const assert = require("chai").assert + +const BCHJS = require("../../src/bch-js") +const bchjs = new BCHJS() + +describe("#Encryption", () => { + describe("#getPubKey", () => { + it("should get a public key", async () => { + const addr = "bitcoincash:qpf8jv9hmqcda0502gjp7nm3g24y5h5s4unutghsxq" + + const result = await bchjs.encryption.getPubKey(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "success") + assert.equal(result.success, true) + assert.property(result, "publicKey") + }) + + it("should report when public key can not be found", async () => { + const addr = "bitcoincash:qpxqr2pmcverj4vukgjqssvk2zju8tp9xsgz2nqagx" + + const result = await bchjs.encryption.getPubKey(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "success") + assert.equal(result.success, false) + assert.property(result, "publicKey") + assert.equal(result.publicKey, "not found") + }) + }) +}) diff --git a/test/unit/encryption.js b/test/unit/encryption.js new file mode 100644 index 0000000..80dc5b4 --- /dev/null +++ b/test/unit/encryption.js @@ -0,0 +1,71 @@ +const assert = require("chai").assert +const sinon = require("sinon") + +const BCHJS = require("../../src/bch-js") +// const bchjs = new BCHJS() +let bchjs + +const mockData = require("./fixtures/encryption-mock") + +describe("#Encryption", () => { + let sandbox + + beforeEach(() => { + bchjs = new BCHJS() + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe("#getPubKey", () => { + // Failure address: + // bitcoincash:qpxqr2pmcverj4vukgjqssvk2zju8tp9xsgz2nqagx + + it("should throw error if BCH address is not provided.", async () => { + try { + await bchjs.encryption.getPubKey() + + assert.equal(true, false, "Unexpected result!") + } catch (err) { + // console.log(`err: `, err) + assert.include( + err.message, + "Input must be a valid Bitcoin Cash address" + ) + } + }) + + it("should report when public key can not be found", async () => { + // Stub the network call. + sandbox + .stub(bchjs.encryption.axios, "get") + .resolves({ data: mockData.failureMock }) + + const addr = "bitcoincash:qpxqr2pmcverj4vukgjqssvk2zju8tp9xsgz2nqagx" + + const result = await bchjs.encryption.getPubKey(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "success") + assert.equal(result.success, false) + assert.property(result, "publicKey") + assert.equal(result.publicKey, "not found") + }) + + it("should get a public key", async () => { + // Stub the network call. + sandbox + .stub(bchjs.encryption.axios, "get") + .resolves({ data: mockData.successMock }) + + const addr = "bitcoincash:qpf8jv9hmqcda0502gjp7nm3g24y5h5s4unutghsxq" + + const result = await bchjs.encryption.getPubKey(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "success") + assert.equal(result.success, true) + assert.property(result, "publicKey") + }) + }) +}) diff --git a/test/unit/fixtures/encryption-mock.js b/test/unit/fixtures/encryption-mock.js new file mode 100644 index 0000000..d4d19da --- /dev/null +++ b/test/unit/fixtures/encryption-mock.js @@ -0,0 +1,19 @@ +/* + Mock data used for unit tests against the Encryption library. +*/ + +const successMock = { + success: true, + publicKey: + "03fcc37586d93af1e146238217989924e0ab1f011c34e1a23aec529354d5b28eb4" +} + +const failureMock = { + success: false, + publicKey: "not found" +} + +module.exports = { + successMock, + failureMock +}