From d365650a7a2c612d74c12b3204c4217477c6aff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Guti=C3=A9rrez?= Date: Mon, 4 Feb 2019 16:26:56 +0100 Subject: [PATCH] implemented proof generator on DDO --- package-lock.json | 301 +++++++++++++++++++++------- package.json | 2 + src/ddo/DDO.ts | 59 +++++- src/ddo/MetaData.ts | 28 ++- test/ddo/DDO.test.ts | 142 ++++++++++--- test/testdata/MetaData.ts | 3 +- test/utils/SignatureHelpers.test.ts | 8 +- 7 files changed, 420 insertions(+), 123 deletions(-) diff --git a/package-lock.json b/package-lock.json index df39855..ecbe1ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "integrity": "sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ==", "dev": true, "requires": { - "@babel/types": "^7.1.3", + "@babel/types": "^7.1.6", "jsesc": "^2.5.1", "lodash": "^4.17.10", "source-map": "^0.5.0", @@ -64,14 +64,6 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } } }, "@babel/parser": { @@ -98,14 +90,31 @@ "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.3", + "@babel/generator": "^7.1.6", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.3", - "@babel/types": "^7.1.3", - "debug": "^3.1.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.10" + }, + "dependencies": { + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, "@babel/types": { @@ -144,6 +153,15 @@ "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", "dev": true }, + "@types/chai-spies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.0.tgz", + "integrity": "sha512-Bj/froHomMnlAPEYEeqhmSuNSjTWW/VuSvCVdhLdcb67+dy4ffjTR6fC0YYw9tHP6KR3U8fkF1mgzmzlChHc5Q==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -1101,6 +1119,43 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } } } }, @@ -1146,6 +1201,12 @@ "type-detect": "^4.0.5" } }, + "chai-spies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.0.0.tgz", + "integrity": "sha512-elF2ZUczBsFoP07qCfMO/zeggs8pqCf3fZGyK5+2X4AndS8jycZYID91ztD9oQ7d/0tnS963dPkd0frQEThDsg==", + "dev": true + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1487,15 +1548,6 @@ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1965,6 +2017,16 @@ "requires": { "pump": "^3.0.0" } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } } } }, @@ -2201,8 +2263,7 @@ "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" }, "file-type": { "version": "5.2.0", @@ -2266,17 +2327,6 @@ } } }, - "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -3331,6 +3381,60 @@ "requires": { "pkg-dir": "^3.0.0", "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } } }, "imurmurhash": { @@ -3983,24 +4087,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -4127,12 +4213,6 @@ "run-queue": "^1.0.3" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -5949,16 +6029,6 @@ "safe-buffer": "^5.1.2" } }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", @@ -6714,15 +6784,6 @@ "tweetnacl": "~0.14.0" } }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -7001,11 +7062,30 @@ "worker-farm": "^1.5.2" }, "dependencies": { + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } } } }, @@ -7381,6 +7461,17 @@ "worker-farm": "^1.5.2" }, "dependencies": { + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7585,6 +7676,15 @@ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, + "ursa-optional": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/ursa-optional/-/ursa-optional-0.9.10.tgz", + "integrity": "sha512-RvEbhnxlggX4MXon7KQulTFiJQtLJZpSb9ZSa7ZTkOW0AzqiVTaLjI4vxaSzJBDH9dwZ3ltZadFiBaZslp6haA==", + "requires": { + "bindings": "^1.3.0", + "nan": "^2.11.1" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -8350,6 +8450,51 @@ "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", "yargs-parser": "^11.1.1" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + } } }, "yargs-parser": { diff --git a/package.json b/package.json index 4b3ee79..5085d17 100644 --- a/package.json +++ b/package.json @@ -69,9 +69,11 @@ }, "devDependencies": { "@types/chai": "^4.1.7", + "@types/chai-spies": "^1.0.0", "@types/mocha": "^5.2.5", "@types/node": "^10.12.17", "chai": "^4.2.0", + "chai-spies": "^1.0.0", "cross-env": "^5.2.0", "mocha": "^5.2.0", "nyc": "^13.1.0", diff --git a/src/ddo/DDO.ts b/src/ddo/DDO.ts index ee5c471..04f0265 100644 --- a/src/ddo/DDO.ts +++ b/src/ddo/DDO.ts @@ -2,6 +2,8 @@ import { Authentication } from "./Authentication" import { PublicKey } from "./PublicKey" import { Service } from "./Service" import { Proof } from "./Proof" +import Web3Provider from '../keeper/Web3Provider' +import * as signatureHelpers from "../utils/SignatureHelpers" /** * DID Descriptor Object. @@ -26,7 +28,7 @@ export class DDO { public static deserialize(ddoString: string): DDO { const ddo = JSON.parse(ddoString) - return ddo as DDO + return new DDO(ddo) } public "@context": string = "https://w3id.org/future-method/v1" @@ -77,4 +79,59 @@ export class DDO { return service } + + /** + * Generate the checksum using the current content. + * @return {string[]} DDO checksum. + */ + public getChecksum(): string { + const web3 = Web3Provider.getWeb3() + const {metadata} = this.findServiceByType('Metadata') + const {files, name, author, license} = metadata.base + + const values = [ + ...files + .map(({checksum}) => checksum) + .filter(_ => !!_), + name, + author, + license, + this.id, + ] + + return web3.utils.sha3(values.join('')) + } + + /** + * Generates proof using personal sing. + * @param {string} publicKey Public key to be used on personal sign. + * @param {string} password Password if it's requirted. + * @return {Promise} Proof object. + */ + public async generateProof(publicKey: string, password?: string): Promise { + + const checksum = this.getChecksum(); + + const signature = await signatureHelpers.signText(checksum, publicKey, password) + + return { + created: (new Date()).toISOString(), + creator: publicKey, + type: "DDOIntegritySignature", + signatureValue: signature, + } + } + + /** + * Generates and adds a proof using personal sing on the DDO. + * @param {string} publicKey Public key to be used on personal sign. + * @param {string} password Password if it's requirted. + * @return {Promise} Proof object. + */ + public async addProof(publicKey: string, password?: string): Promise { + if (this.proof) { + throw new Error('Proof already exists') + } + this.proof = await this.generateProof(publicKey, password) + } } diff --git a/src/ddo/MetaData.ts b/src/ddo/MetaData.ts index 6cfbee1..f361524 100644 --- a/src/ddo/MetaData.ts +++ b/src/ddo/MetaData.ts @@ -1,3 +1,11 @@ +export interface File { + url: string + checksum?: string + checksumType?: string + contentLength?: string + resourceId?: string +} + /** * Base attributes of Assets Metadata. * @see https://github.com/oceanprotocol/OEPs/tree/master/8#base-attributes @@ -140,6 +148,18 @@ export class MetaDataBase { * @example 10 */ price: number + + /** + * Array of File objects including the encrypted file urls and some additional information. + * @type {File[]} + */ + files: File[] + + /** + * SHA3 hash of concatenated values: [list of all file checksums] + name + author + license + did + * @type {string} + */ + checksum: string } /** @@ -192,14 +212,6 @@ export interface AdditionalInformation { uri: string mediaType: string }[] - - - /** - * Checksum of attributes to be able to compare if there are changes in - * the asset that you are purchasing. - * @type {string} - */ - checksum: string } export interface MetaData { diff --git a/test/ddo/DDO.test.ts b/test/ddo/DDO.test.ts index c47826f..b3f294b 100644 --- a/test/ddo/DDO.test.ts +++ b/test/ddo/DDO.test.ts @@ -1,60 +1,66 @@ -import {assert} from "chai" -import { Authentication} from "../../src/ddo/Authentication" +import { assert, expect, use, spy } from "chai" +import * as spies from "chai-spies" + import { DDO } from "../../src/ddo/DDO" -import { MetaData, MetaDataBase, Curation, AdditionalInformation } from "../../src/ddo/MetaData" -import { PublicKey } from "../../src/ddo/PublicKey" import { Service } from "../../src/ddo/Service" +import ConfigProvider from "../../src/ConfigProvider" +import config from "../config" +import * as signatureHelpers from "../../src/utils/SignatureHelpers" + import * as jsonDDO from "../testdata/ddo.json" +use(spies); + describe("DDO", () => { const testDDO: DDO = new DDO({ + id: `did:op:${"a".repeat(64)}`, publicKey: [ { id: "did:op:123456789abcdefghi#keys-1", type: "RsaVerificationKey2018", owner: "did:op:123456789abcdefghi", publicKeyPem: "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n", - } as PublicKey, + }, { id: "did:op:123456789abcdefghi#keys-2", type: "Ed25519VerificationKey2018", owner: "did:op:123456789abcdefghi", publicKeyBase58: "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV", - } as PublicKey, + }, ], authentication: [ { type: "RsaSignatureAuthentication2018", publicKey: "did:op:123456789abcdefghi#keys-1", - } as Authentication, + }, { type: "ieee2410Authentication2018", publicKey: "did:op:123456789abcdefghi#keys-2", - } as Authentication, + }, ], service: [ { type: "OpenIdConnectVersion1.0Service", serviceEndpoint: "https://openid.example.com/", - } as Service, + }, { type: "CredentialRepositoryService", serviceEndpoint: "https://repository.example.com/service/8377464", - } as Service, + }, { type: "XdiService", serviceEndpoint: "https://xdi.example.com/8377464", - } as Service, + }, { type: "HubService", serviceEndpoint: "https://hub.example.com/.identity/did:op:0123456789abcdef/", - } as Service, + }, { type: "MessagingService", serviceEndpoint: "https://example.com/messages/8377464", - } as Service, - { + }, + { type: "SocialWebInboxService", serviceEndpoint: "https://social.example.com/83hfh37dj", description: "My public social inbox", @@ -62,22 +68,22 @@ describe("DDO", () => { amount: "0.50", currency: "USD", }, - } as Service, + }, { id: "did:op:123456789abcdefghi;bops", type: "BopsService", serviceEndpoint: "https://bops.example.com/enterprise/", - } as Service, + }, { type: "Consume", // tslint:disable-next-line serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}", - } as Service, + }, { type: "Compute", // tslint:disable-next-line serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}", - } as Service, + }, { type: "Metadata", serviceEndpoint: "http://myaquarius.org/api/v1/provider/assets/metadata/{did}", @@ -115,12 +121,29 @@ describe("DDO", () => { inLanguage: "en", tags: "weather, uk, 2011, temperature, humidity", price: 10, - } as MetaDataBase, + files: [ + { + url: "234ab87234acbd09543085340abffh21983ddhiiee982143827423421", + checksum: "efb2c764274b745f5fc37f97c6b0e761", + contentLength: "4535431", + resourceId: "access-log2018-02-13-15-17-29-18386C502CAEA932" + }, + { + url: "234ab87234acbd6894237582309543085340abffh21983ddhiiee982143827423421", + checksum: "085340abffh21495345af97c6b0e761", + contentLength: "12324" + }, + { + url: "80684089027358963495379879a543085340abffh21983ddhiiee982143827abcc2" + } + ], + checksum: "" + }, curation: { rating: 0.93, numVotes: 123, schema: "Binary Votting", - } as Curation, + }, additionalInformation: { updateFrecuency: "yearly", structuredMarkup: [ @@ -133,12 +156,20 @@ describe("DDO", () => { mediaType: "text/turtle", }, ], - } as AdditionalInformation, - } as MetaData, + }, + }, }, ], }) + before(async () => { + ConfigProvider.setConfig(config) + }) + + afterEach(() => { + spy.restore() + }) + describe("#serialize()", () => { it("should properly serialize", async () => { @@ -163,13 +194,13 @@ describe("DDO", () => { it("should create an predefined ddo", async () => { - const service: Service = { + const service: Partial = { serviceEndpoint: "http://", description: "nice service", - } as Service + } const ddo = new DDO({ - service: [service], + service: [service], }) assert(ddo) @@ -186,13 +217,13 @@ describe("DDO", () => { it("should properly deserialize from serialized object", async () => { const ddoString = DDO.serialize(testDDO) - assert(ddoString) + assert.typeOf(ddoString, 'string') const ddo: DDO = DDO.deserialize(ddoString) - assert(ddo) + assert.instanceOf(ddo, DDO) - assert(ddo.id === testDDO.id) - assert(ddo.publicKey[0].publicKeyPem === testDDO.publicKey[0].publicKeyPem) + assert.equal(ddo.id, testDDO.id) + assert.equal(ddo.publicKey[0].publicKeyPem, testDDO.publicKey[0].publicKeyPem) }) it("should properly deserialize from json file", async () => { @@ -200,8 +231,57 @@ describe("DDO", () => { const ddo: DDO = DDO.deserialize(JSON.stringify(jsonDDO)) assert(ddo) - assert(ddo.id === jsonDDO.id) - assert(ddo.publicKey[0].publicKeyPem === jsonDDO.publicKey[0].publicKeyPem) + assert.equal(ddo.id, jsonDDO.id) + assert.equal(ddo.publicKey[0].publicKeyPem, jsonDDO.publicKey[0].publicKeyPem) + }) + }) + + describe("#getChecksum()", () => { + it("should properly generate a the checksum DDO", async () => { + const ddo = new DDO(testDDO) + const checksum = ddo.getChecksum() + + assert.equal(checksum, "0x15f27a7a3c7b15d2b06dec7347c6b8da168adddd7df51a8ebbbe87b59b80049b") + }) + }) + + describe("#generateProof()", () => { + + const publicKey = `0x${'a'.repeat(40)}` + const signature = `0x${'a'.repeat(130)}` + + it("should properly generate the proof", async () => { + const signTextSpy = spy.on(signatureHelpers, 'signText', () => signature) + const ddo = new DDO(testDDO) + const checksum = ddo.getChecksum() + const proof = await ddo.generateProof(publicKey) + + assert.include(proof, { + creator: publicKey, + type: 'DDOIntegritySignature', + signatureValue: signature, + }) + expect(signTextSpy).to.have.been.called.with(checksum, publicKey) + }) + }) + + describe("#addProof()", () => { + + const publicKey = `0x${'a'.repeat(40)}` + + it("should properly add the proof on the DDO", async () => { + const fakeProof = { + creation: Date.now(), + creator: 'test', + type: 'test', + signaturValue: 'test' + } + const ddo = new DDO(testDDO) + const generateProofSpy = spy.on(ddo, 'generateProof', () => fakeProof) + await ddo.addProof(publicKey) + + assert.equal(ddo.proof, fakeProof) + expect(generateProofSpy).to.have.been.called.with(publicKey) }) }) }) diff --git a/test/testdata/MetaData.ts b/test/testdata/MetaData.ts index 610889d..f153257 100644 --- a/test/testdata/MetaData.ts +++ b/test/testdata/MetaData.ts @@ -34,6 +34,8 @@ export const metadataMock: MetaData = { inLanguage: "en", tags: "weather, uk, 2011, temperature, humidity", price: 10, + files: [], + checksum: "" }, curation: { rating: 0.93, @@ -42,7 +44,6 @@ export const metadataMock: MetaData = { }, additionalInformation: { updateFrecuency: "yearly", - checksum: "", structuredMarkup: [ { uri: "http://skos.um.es/unescothes/C01194/jsonld", diff --git a/test/utils/SignatureHelpers.test.ts b/test/utils/SignatureHelpers.test.ts index a9b7e9e..2b4dcd9 100644 --- a/test/utils/SignatureHelpers.test.ts +++ b/test/utils/SignatureHelpers.test.ts @@ -10,13 +10,16 @@ use(spies); describe("SignatureHelpers", () => { - const publicKey = "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e" + const publicKey = `0x${'a'.repeat(40)}` const text = "0123456789abcde" const signature = `0x${'a'.repeat(130)}` before(async () => { ConfigProvider.setConfig(config) }) + afterEach(() => { + spy.restore() + }) describe("#signText", () => { let personalSignSpy @@ -25,9 +28,6 @@ describe("SignatureHelpers", () => { const web3 = Web3Provider.getWeb3() personalSignSpy = spy.on(web3.eth.personal, 'sign', () => signature) }) - afterEach(() => { - spy.restore() - }) it("should sign a text as expected", async () => { const signed = await signText(text, publicKey)