mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
added secret store connection
This commit is contained in:
parent
d777bd9030
commit
2662a7795b
61
package-lock.json
generated
61
package-lock.json
generated
@ -382,6 +382,15 @@
|
||||
"long": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"JSONStream": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
|
||||
"integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
|
||||
"requires": {
|
||||
"jsonparse": "^1.2.0",
|
||||
"through": ">=2.2.7 <3"
|
||||
}
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
||||
@ -1782,6 +1791,21 @@
|
||||
"resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM="
|
||||
},
|
||||
"es6-promisify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
|
||||
"requires": {
|
||||
"es6-promise": "^4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promise": {
|
||||
"version": "4.2.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
|
||||
"integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@ -2240,6 +2264,11 @@
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"eyes": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
|
||||
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
@ -3587,6 +3616,33 @@
|
||||
"is-object": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"jayson": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-2.1.0.tgz",
|
||||
"integrity": "sha512-WQhCph4BgSDbRUPdZYqGMojKMxjzPqCCKmWYMsRWX/Bvh1oP+Irs2upeEJy8flU3ZAZzm68TjuL1X8u9Rt4wWQ==",
|
||||
"requires": {
|
||||
"@types/node": "^10.3.5",
|
||||
"JSONStream": "^1.3.1",
|
||||
"commander": "^2.12.2",
|
||||
"es6-promisify": "^5.0.0",
|
||||
"eyes": "^0.1.8",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"lodash": "^4.17.10",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
|
||||
"integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
|
||||
@ -3653,6 +3709,11 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"jsonparse": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
|
||||
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
|
||||
},
|
||||
"jsonwebtoken": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
|
||||
|
@ -54,6 +54,7 @@
|
||||
"eth-crypto": "^1.2.4",
|
||||
"eth-ecies": "^1.0.3",
|
||||
"ethereumjs-util": "^6.0.0",
|
||||
"jayson": "^2.1.0",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"node-fetch": "^2.2.0",
|
||||
"web3": "1.0.0-beta.36",
|
||||
|
75
src/secretstore/ParityClient.ts
Normal file
75
src/secretstore/ParityClient.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import * as jayson from "jayson"
|
||||
import {Client} from "jayson"
|
||||
import {URL} from "url"
|
||||
import Logger from "../utils/Logger"
|
||||
|
||||
function add0xPrefix(key) {
|
||||
return key.startsWith("0x") ? key : "0x" + key
|
||||
}
|
||||
|
||||
export default class ParityClient {
|
||||
|
||||
private rpcClient: Client
|
||||
|
||||
constructor(private url: string, private address: string, private password: string) {
|
||||
this.rpcClient = jayson.Client.http(new URL(this.url))
|
||||
}
|
||||
|
||||
public async signKeyId(keyId): Promise<string> {
|
||||
return this.sendJsonRpcRequest(this.rpcClient,
|
||||
"secretstore_signRawHash",
|
||||
[this.address, this.password, add0xPrefix(keyId)])
|
||||
.then((result: string) => {
|
||||
Logger.log("fu", result)
|
||||
return result
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public generateDocumentKeyFromKey(serverKey) {
|
||||
return this.sendJsonRpcRequest(this.rpcClient,
|
||||
"secretstore_generateDocumentKey",
|
||||
[this.address, this.password, serverKey])
|
||||
.then((result: string) => {
|
||||
return result
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public encryptDocument(encryptedKey, document: string) {
|
||||
// `document` must be encoded in hex when sent to encryption
|
||||
return this.sendJsonRpcRequest(this.rpcClient, "secretstore_encrypt",
|
||||
[this.address, this.password, encryptedKey,
|
||||
add0xPrefix(new Buffer(document).toString("hex"))])
|
||||
.then((result: string) => {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public decryptDocument(decryptedSecret, commonPoint, decryptShadows, encryptedDocument) {
|
||||
return this.sendJsonRpcRequest(this.rpcClient,
|
||||
"secretstore_shadowDecrypt",
|
||||
[this.address, this.password, decryptedSecret,
|
||||
commonPoint, decryptShadows, encryptedDocument])
|
||||
.then((result: string) => {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
private sendJsonRpcRequest(rpcClient: Client, methodName: string, paramsList: any[]) {
|
||||
return new Promise((resolve, reject) => {
|
||||
rpcClient.request(
|
||||
methodName,
|
||||
paramsList,
|
||||
(err, response) => {
|
||||
const error = response.error || err
|
||||
if (error) {
|
||||
Logger.error("JSON RPC call failed:", error)
|
||||
Logger.error(`Method ${methodName}`)
|
||||
return reject(error)
|
||||
}
|
||||
return resolve(response.result.toString())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
@ -1,8 +1,59 @@
|
||||
import SecretStoreDocumentHandler from "@oceanprotocol/secret-store-client"
|
||||
import Logger from "../utils/Logger"
|
||||
import ParityClient from "./ParityClient"
|
||||
import SecretStoreClient from "./SecretStoreClient"
|
||||
|
||||
export default class SecretStore {
|
||||
|
||||
public test() {
|
||||
return new SecretStoreDocumentHandler()
|
||||
private partiyClient: ParityClient
|
||||
private secretStoreClient: SecretStoreClient
|
||||
|
||||
constructor(config: { secretStoreUrl: string, parityUrl: string, address: string, password: string }) {
|
||||
|
||||
this.partiyClient = new ParityClient(config.parityUrl, config.address, config.password)
|
||||
this.secretStoreClient = new SecretStoreClient(config.secretStoreUrl)
|
||||
}
|
||||
|
||||
public async generateServerKey(serverKeyId: string): Promise<string> {
|
||||
|
||||
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
|
||||
|
||||
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
|
||||
|
||||
const key = await this.secretStoreClient.generateServerKey(serverKeyId, serverKeyIdSig)
|
||||
|
||||
Logger.log("key:", key)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
public async storeDocumentKey(serverKeyId: string, documentKeyId): Promise<string> {
|
||||
|
||||
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
|
||||
const documentKeyIdSig = await this.partiyClient.signKeyId(documentKeyId)
|
||||
|
||||
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
|
||||
|
||||
const key = await this.secretStoreClient.storeDocumentKey(
|
||||
serverKeyId, serverKeyIdSig,
|
||||
documentKeyId, documentKeyIdSig,
|
||||
)
|
||||
|
||||
Logger.log("key:", key)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
public async retrieveDocumentKey(serverKeyId: string): Promise<string> {
|
||||
|
||||
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
|
||||
|
||||
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
|
||||
|
||||
const key = await this.secretStoreClient.retrieveDocumentKey(serverKeyId, serverKeyIdSig)
|
||||
|
||||
Logger.log("key:", key)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
}
|
||||
|
108
src/secretstore/SecretStoreClient.ts
Normal file
108
src/secretstore/SecretStoreClient.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import fetch from "node-fetch"
|
||||
import Logger from "../utils/Logger"
|
||||
|
||||
function removeLeading0xPrefix(key) {
|
||||
return key.startsWith("0x") ? key.replace("0x", "") : key
|
||||
}
|
||||
|
||||
export default class SecretStoreClient {
|
||||
|
||||
constructor(private url: string, private threshold?: number) {
|
||||
this.url = url
|
||||
this.threshold = threshold || 1
|
||||
}
|
||||
|
||||
public async generateServerKey(serverKeyId: string, serverKeyIdSig: string): Promise<string> {
|
||||
|
||||
const url = [
|
||||
this.url, "shadow", serverKeyId,
|
||||
removeLeading0xPrefix(serverKeyIdSig),
|
||||
this.threshold,
|
||||
].join("/")
|
||||
|
||||
const result = await fetch(url, {
|
||||
method: "POST",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
throw Error(`Unable to generate Server Key ${response.statusText}`)
|
||||
})
|
||||
.catch((error) => {
|
||||
throw Error(`Unable to generate Server Key: ${error.message}`)
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
throw Error(`Unable to generate Server Key`)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/*
|
||||
curl -X POST http://localhost:8082/shadow/
|
||||
0000000000000000000000000000000000000000000000000000000000000000/
|
||||
de12681e0b8f7a428f12a6694a5f7e1324deef3d627744d95d51b862afc13799251831b3611ae436c452b54cdf5c4e78b361a396ae183e8b4c34519e895e623c00/
|
||||
368244efaf441c2dabf7a723355a97b3b86f27bdb2827ae6f34ddece5132efd37af4ba808957b7113b4296bc4ae9ec7be38f9de6bae00504e775883a50d4658a/
|
||||
b7ad0603946987f1a154ae7f074e45da224eaa83704aac16a2d43a675d219654cf087b5d7aacce0790a65abbc1a495b26e71a5c6e9a4a71b543bf0048935bc13
|
||||
*/
|
||||
|
||||
public async storeDocumentKey(serverKeyId: string, serverKeyIdSig: string,
|
||||
commonPoint: string, encryptedPoint: string) {
|
||||
const url = [this.url, "shadow", serverKeyId, removeLeading0xPrefix(serverKeyIdSig),
|
||||
removeLeading0xPrefix(commonPoint), removeLeading0xPrefix(encryptedPoint)]
|
||||
.join("/")
|
||||
|
||||
Logger.log("url", url)
|
||||
const result = await fetch(url, {
|
||||
method: "POST",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response
|
||||
}
|
||||
throw Error(`Unable to store document Keys ${response.statusText}`)
|
||||
})
|
||||
.catch((error) => {
|
||||
throw Error(`Unable to store document keys: ${error.message}`)
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
throw Error(`Unable to store document Keys`)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public async retrieveDocumentKey(documentKeyId, documentKeyIdSig) {
|
||||
|
||||
const url = [
|
||||
this.url, documentKeyId,
|
||||
removeLeading0xPrefix(documentKeyIdSig),
|
||||
].join("/")
|
||||
|
||||
Logger.log(url)
|
||||
|
||||
const result = await fetch(url, {
|
||||
method: "GET",
|
||||
})
|
||||
.then((response) => {
|
||||
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
throw Error(`Unable to retrieve decryption Keys ${response.statusText}`)
|
||||
})
|
||||
.catch((e) => {
|
||||
throw Error(`Unable to retrieve decryption keys: ${e.message}`)
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
throw Error(`Unable to retrieve decryption Keys`)
|
||||
}
|
||||
|
||||
// results should have (decrypted_secret, common_point, decrypt_shadows)
|
||||
return JSON.parse(result)
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import {assert} from "chai"
|
||||
import SecretStore from "../../src/secretstore/SecretStore"
|
||||
|
||||
describe("SecretStore", () => {
|
||||
|
||||
describe("#test()", () => {
|
||||
it("should return instance", () => {
|
||||
|
||||
const fu = new SecretStore().test()
|
||||
assert(fu)
|
||||
})
|
||||
})
|
||||
})
|
52
test/secretstore/SecretStore.test_.ts
Normal file
52
test/secretstore/SecretStore.test_.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import BigNumber from "bignumber.js"
|
||||
import {assert} from "chai"
|
||||
import ConfigProvider from "../../src/ConfigProvider"
|
||||
import Config from "../../src/models/Config"
|
||||
import SecretStore from "../../src/secretstore/SecretStore"
|
||||
|
||||
const parityUrl = "http://localhost:8545"
|
||||
const ssUrl = "https://secret-store.dev-ocean.com"
|
||||
|
||||
ConfigProvider.configure({
|
||||
nodeUri: ssUrl,
|
||||
} as Config)
|
||||
|
||||
const address = "0xa50f397644973dba99624404b2894825840aa03b"
|
||||
const password = "unittest"
|
||||
|
||||
const secretStore: SecretStore = new SecretStore({
|
||||
secretStoreUrl: ssUrl, parityUrl,
|
||||
address,
|
||||
password,
|
||||
})
|
||||
|
||||
function generateRandomId(): string {
|
||||
const id: string = BigNumber.random(64).toString().replace("0.", "")
|
||||
|
||||
// sometimes it only generates 63 digits
|
||||
return id.length === 63 ? id + "0" : id
|
||||
}
|
||||
|
||||
describe("SecretStore", () => {
|
||||
|
||||
describe("#generateServerKey()", () => {
|
||||
it("should generate Server key", async () => {
|
||||
|
||||
const serverKeyId = generateRandomId()
|
||||
const serverKey = await secretStore.generateServerKey(serverKeyId)
|
||||
|
||||
assert(serverKey)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#storeDocumentKey()", () => {
|
||||
it("should store Document key", async () => {
|
||||
|
||||
const serverKeyId = generateRandomId()
|
||||
const documentKeyId = generateRandomId()
|
||||
const documentKey = await secretStore.storeDocumentKey(serverKeyId, documentKeyId)
|
||||
|
||||
assert(documentKey)
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user