1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

added encrypt and decrypt document

This commit is contained in:
Sebastian Gerske 2018-10-22 12:46:27 +02:00
parent da5386f490
commit b172a245b1
14 changed files with 177 additions and 99 deletions

View File

@ -1,5 +0,0 @@
export default class DocumentKeys {
commonPoint: string
encryptedKey: string
encryptedPoint: string
}

View File

@ -0,0 +1,10 @@
export default class HexHelpler {
public static removeLeading0xPrefix(key) {
return key.startsWith("0x") ? key.replace("0x", "") : key
}
public static add0xPrefix(key) {
return key.startsWith("0x") ? key : "0x" + key
}
}

View File

@ -2,11 +2,8 @@ import * as jayson from "jayson"
import {Client} from "jayson"
import {URL} from "url"
import Logger from "../utils/Logger"
import DocumentKeys from "./DocumentKeys"
function add0xPrefix(key) {
return key.startsWith("0x") ? key : "0x" + key
}
import HexHelpler from "./HexHelpler"
import GeneratedKey from "./keys/GeneratedKey"
export default class ParityClient {
@ -23,7 +20,7 @@ export default class ParityClient {
public async signKeyId(keyId): Promise<string> {
return this.sendJsonRpcRequest(this.rpcClient,
"secretstore_signRawHash",
[this.address, this.password, add0xPrefix(keyId)])
[this.address, this.password, HexHelpler.add0xPrefix(keyId)])
.then((result: string) => {
return result
})
@ -34,32 +31,36 @@ export default class ParityClient {
"secretstore_generateDocumentKey",
[this.address, this.password, serverKey])
.then((result: any) => {
return {
const generatedKey = {
commonPoint: result.common_point,
encryptedKey: result.encrypted_key,
encryptedPoint: result.encrypted_point,
} as DocumentKeys
} as GeneratedKey
return generatedKey
})
}
public encryptDocument(encryptedKey, document: any): Promise<string> {
public encryptDocument(encryptedKey: string, document: any): Promise<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(JSON.stringify(document)).toString("hex"))])
const documentString = JSON.stringify(document)
const documentHexed = HexHelpler.add0xPrefix(new Buffer(documentString).toString("hex"))
return this.sendJsonRpcRequest(this.rpcClient,
"secretstore_encrypt",
[this.address, this.password, encryptedKey, documentHexed])
.then((result: string) => {
return result
})
}
public decryptDocument(decryptedSecret: string, commonPoint: string,
decryptShadows: string, encryptedDocument: string): Promise<any> {
decryptShadows: string[], encryptedDocument: string): Promise<any> {
return this.sendJsonRpcRequest(this.rpcClient,
"secretstore_shadowDecrypt",
[this.address, this.password, decryptedSecret,
commonPoint, decryptShadows, encryptedDocument])
.then((result: string) => {
return result
const documentString = new Buffer(HexHelpler.removeLeading0xPrefix(result), "hex").toString("utf8")
return JSON.parse(documentString)
})
}
@ -77,4 +78,4 @@ export default class ParityClient {
})
})
}
}
}

View File

@ -1,4 +1,5 @@
import Logger from "../utils/Logger"
import GeneratedKey from "./keys/GeneratedKey"
import RetrievedKey from "./keys/RetrievedKey"
import ParityClient from "./ParityClient"
import SecretStoreClient from "./SecretStoreClient"
@ -13,53 +14,77 @@ export default class SecretStore {
url: config.parityUrl, address: config.address,
password: config.password,
})
this.secretStoreClient = new SecretStoreClient(config.secretStoreUrl)
this.secretStoreClient = new SecretStoreClient({url: config.secretStoreUrl})
}
public async generateServerKey(serverKeyId: string): Promise<string> {
public async encryptDocument(serverKeyId: string, document: any): Promise<string> {
const serverKey = await this.generateServerKey(serverKeyId)
// generate document key
const documentKey: GeneratedKey = await this.generateDocumentKey(serverKey)
// store the document key in secret store
await this.storeDocumentKey(serverKeyId, documentKey)
// encrypt document
const encryptedDocument =
await this.partiyClient.encryptDocument(documentKey.encryptedKey, document)
return encryptedDocument
}
public async decryptDocument(serverkeyId: string, encryptedDocument: string): Promise<any> {
// get document key from secret store
const documentKey: RetrievedKey = await this.retrieveDocumentKey(serverkeyId)
const decryptDocument: any = await this.partiyClient.decryptDocument(
documentKey.decryptedSecret, documentKey.commonPoint,
documentKey.decryptShadows, encryptedDocument)
return decryptDocument
}
private async generateServerKey(serverKeyId: string): Promise<string> {
// sign server key id
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
// Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
const key = await this.secretStoreClient.generateServerKey(serverKeyId, serverKeyIdSig)
// generate server key
const serverKey = await this.secretStoreClient.generateServerKey(serverKeyId, serverKeyIdSig)
Logger.log("key:", key)
return key
return serverKey
}
public async storeDocumentKey(serverKeyId: string, documentKeyId): Promise<string> {
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
const serverKey = await this.secretStoreClient.generateServerKey(
serverKeyId, serverKeyIdSig)
Logger.log("key:", serverKey)
const documentKey = this.partiyClient.generateDocumentKeyFromKey(serverKey)
return documentKey
private async generateDocumentKey(serverKey: string): Promise<GeneratedKey> {
// generate document key from server key
const documentKeys: GeneratedKey = await this.partiyClient.generateDocumentKeyFromKey(serverKey)
return documentKeys
}
public async retrieveDocumentKey(serverKeyId: string): Promise<string> {
private async storeDocumentKey(serverKeyId: string, documentKeys: GeneratedKey): Promise<boolean> {
// sign server key id
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
// store document key in secret store
await this.secretStoreClient.storeDocumentKey(serverKeyId, serverKeyIdSig,
documentKeys.commonPoint, documentKeys.encryptedPoint)
const key = await this.secretStoreClient.retrieveDocumentKey(serverKeyId, serverKeyIdSig)
Logger.log("key:", key)
return key
return true
}
public encryptDocument(document: string) {
}
private async retrieveDocumentKey(serverKeyId: string): Promise<RetrievedKey> {
public decryptDocument(encryptedDocument: string) {
// sign server key id
const serverKeyIdSig = await this.partiyClient.signKeyId(serverKeyId)
// Logger.log("serverKeyId:", serverKeyId, "serverKeyIdSig:", serverKeyIdSig)
// retrieve document key from secret store
const documentKeys: RetrievedKey = await this.secretStoreClient.retrieveDocumentKey(serverKeyId, serverKeyIdSig)
return documentKeys
}
}

View File

@ -1,25 +1,27 @@
import fetch from "node-fetch"
import Logger from "../utils/Logger"
function removeLeading0xPrefix(key) {
return key.startsWith("0x") ? key.replace("0x", "") : key
}
import HexHelpler from "./HexHelpler"
import RetrievedKey from "./keys/RetrievedKey"
export default class SecretStoreClient {
constructor(private url: string, private threshold?: number) {
this.url = url
this.threshold = threshold || 1
private threshold: number
private url: string
constructor(config: { url: string, threshold?: number }) {
this.url = config.url
this.threshold = config.threshold || 1
}
public async generateServerKey(serverKeyId: string, serverKeyIdSig: string): Promise<string> {
const url = [
this.url, "shadow", serverKeyId,
removeLeading0xPrefix(serverKeyIdSig),
HexHelpler.removeLeading0xPrefix(serverKeyIdSig),
this.threshold,
].join("/")
// Logger.log("url", url)
const result = await fetch(url, {
method: "POST",
})
@ -40,27 +42,20 @@ export default class SecretStoreClient {
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)]
commonPoint: string, encryptedPoint: string): Promise<boolean> {
const url = [this.url, "shadow", serverKeyId, HexHelpler.removeLeading0xPrefix(serverKeyIdSig),
HexHelpler.removeLeading0xPrefix(commonPoint), HexHelpler.removeLeading0xPrefix(encryptedPoint)]
.join("/")
Logger.log("url", url)
// Logger.log("url", url)
const result = await fetch(url, {
method: "POST",
})
.then((response) => {
if (response.ok) {
return response
if (response.ok && response.status === 200) {
return true
}
throw Error(`Unable to store document Keys ${response.statusText}`)
})
@ -75,25 +70,29 @@ export default class SecretStoreClient {
return result
}
public async retrieveDocumentKey(documentKeyId, documentKeyIdSig) {
public async retrieveDocumentKey(serverKeyId, serverKeyIdSig): Promise<RetrievedKey> {
const url = [
this.url, documentKeyId,
removeLeading0xPrefix(documentKeyIdSig),
].join("/")
const url = [this.url, "shadow", serverKeyId, HexHelpler.removeLeading0xPrefix(serverKeyIdSig)]
.join("/")
Logger.log(url)
// Logger.log("url", url)
const result = await fetch(url, {
const result: RetrievedKey = await fetch(url, {
method: "GET",
})
.then((response) => {
if (response.ok) {
return response.json()
}
throw Error(`Unable to retrieve decryption Keys ${response.statusText}`)
})
.then((data) => {
return {
commonPoint: data.common_point,
decryptedSecret: data.decrypted_secret,
decryptShadows: data.decrypt_shadows,
} as RetrievedKey
})
.catch((e) => {
throw Error(`Unable to retrieve decryption keys: ${e.message}`)
})
@ -102,7 +101,6 @@ export default class SecretStoreClient {
throw Error(`Unable to retrieve decryption Keys`)
}
// results should have (decrypted_secret, common_point, decrypt_shadows)
return JSON.parse(result)
return result
}
}

View File

@ -0,0 +1,6 @@
import KeyBase from "./KeyBase"
export default class GeneratedKey extends KeyBase {
public encryptedKey: string
public encryptedPoint: string
}

View File

@ -0,0 +1,3 @@
export default class KeyBase {
public commonPoint: string
}

View File

@ -0,0 +1,6 @@
import KeyBase from "./KeyBase"
export default class RetrievedKey extends KeyBase {
public decryptedSecret: string
public decryptShadows: string[]
}

View File

@ -2,8 +2,11 @@ import BigNumber from "bignumber.js"
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import Config from "../../src/models/Config"
import DocumentKeys from "../../src/secretstore/DocumentKeys"
import GeneratedKey from "../../src/secretstore/keys/GeneratedKey"
import ParityClient from "../../src/secretstore/ParityClient"
import * as GeneratedKeyMaterial from "./keys/GeneratedKey.json"
import * as RetrievedKeyMaterial from "./keys/RetrievedKey.json"
import * as ServerKey from "./keys/ServerKey.json"
const parityUrl = "http://localhost:8545"
@ -13,13 +16,11 @@ ConfigProvider.configure({
const address = "0xa50f397644973dba99624404b2894825840aa03b"
const password = "unittest"
const serverKey =
"0x36131d552e561d8231cd91c8020d869e14c11b16e79fb80ecf8302ea0a0539c969dbc0b547398daf293c259431d7c483ee5974b0ef179297edbe6d39af4374d5"
const testDocument = {
so: "secure",
soWow: true,
}
const parityClient: ParityClient = new ParityClient({
url: parityUrl,
address, password,
@ -47,7 +48,7 @@ describe("ParityClient", () => {
describe("#generateDocumentKeyFromKey()", () => {
it("should generate a document key from a server key", async () => {
const documentKey = await parityClient.generateDocumentKeyFromKey(serverKey)
const documentKey = await parityClient.generateDocumentKeyFromKey(ServerKey)
assert(documentKey)
})
})
@ -55,7 +56,7 @@ describe("ParityClient", () => {
describe("#encryptDocument()", () => {
it("should encrypt an document", async () => {
const documentKey: DocumentKeys = await parityClient.generateDocumentKeyFromKey(serverKey)
const documentKey: GeneratedKey = await parityClient.generateDocumentKeyFromKey(ServerKey)
const encryptedDocument = await parityClient.encryptDocument(documentKey.encryptedKey, testDocument)
assert(encryptedDocument)
})
@ -64,9 +65,16 @@ describe("ParityClient", () => {
describe("#decryptDocument()", () => {
it("should decrypt an document", async () => {
const documentKey: DocumentKeys = await parityClient.generateDocumentKeyFromKey(serverKey)
const encryptedDocument = await parityClient.encryptDocument(documentKey.encryptedKey, testDocument)
const encryptedDocument: string =
await parityClient.encryptDocument(GeneratedKeyMaterial.encryptedKey, testDocument)
assert(encryptedDocument)
const decryptedDocument: any = await parityClient.decryptDocument(
RetrievedKeyMaterial.decryptedSecret, RetrievedKeyMaterial.commonPoint,
RetrievedKeyMaterial.decryptShadows, encryptedDocument)
assert(decryptedDocument)
assert(testDocument.soWow === decryptedDocument.soWow)
})
})
})

View File

@ -11,6 +11,13 @@ ConfigProvider.configure({
nodeUri: parityUrl,
} as Config)
const testDocument = {
so: "ocean",
soWow: true,
many: "text is nice to have",
i: "blow up this document with blind text",
}
const address = "0xa50f397644973dba99624404b2894825840aa03b"
const password = "unittest"
@ -29,24 +36,28 @@ function generateRandomId(): string {
describe("SecretStore", () => {
describe("#generateServerKey()", () => {
it("should generate Server key", async () => {
describe("#encryptDocument()", () => {
it("should encrypt an document", async () => {
const serverKeyId = generateRandomId()
const serverKey = await secretStore.generateServerKey(serverKeyId)
assert(serverKey)
const encryptedDocument = await secretStore.encryptDocument(serverKeyId, testDocument)
assert(encryptedDocument)
})
})
describe("#storeDocumentKey()", () => {
it("should store Document key", async () => {
describe("#decryptDocument()", () => {
it("should decrypt an document", async () => {
const serverKeyId = generateRandomId()
const documentKeyId = generateRandomId()
const documentKey = await secretStore.storeDocumentKey(serverKeyId, documentKeyId)
assert(documentKey)
const encryptedDocument: string = await secretStore.encryptDocument(serverKeyId, testDocument)
assert(encryptedDocument)
const decryptedDocument: any = await secretStore.decryptDocument(serverKeyId, encryptedDocument)
assert(decryptedDocument)
assert(testDocument.soWow === decryptedDocument.soWow)
})
})
})

View File

@ -0,0 +1,5 @@
{
"commonPoint": "0xba52313ef585265b52434b1c45a7aa19cf59e371b8d4f5d5f3ef45863e51341b9648dc83ce11b7158347b2cfb2613f92689d6d3704e84dee4eafd38abd0c7ca6",
"encryptedKey": "0x04e77b1d4b3919354550900d871c8ee698ca592e45ee715dad607c408fc18982bae479b3c752dec27eebbe00b102b512e6454e747138f4d882a2fa3dbe84bb3851518766c01e216fc5b01f7a4eb2e18ea2f159063801b0e43f5f632089a80ab982520707ee9e3f4980931a8814e44febdd960b366336ee35b26bfe523950d28bb6bdc0a65240c43b999cae3cd8258a06cb8dd52b2a2516bf15ad4d00d8c50f4e5f8bc48cf7173db5cce77a182093404402",
"encryptedPoint": "0x1697d31ba17eb819177004618f2a5e00fceb355b12ceb4a476ade59adfc9f6579f9b951ef0695eb852f1ff1deff1f12205760b8d1c5a46ba44cce7d54571200a"
}

View File

@ -0,0 +1,8 @@
{
"commonPoint": "0xba52313ef585265b52434b1c45a7aa19cf59e371b8d4f5d5f3ef45863e51341b69b7237c31ee48ea7cb84d304d9ec06d976292c8fb17b211b1502c7442f37f89",
"decryptedSecret": "0x7b6bee06bd00dc825d2c99f324b47e4aee9219d5453076a735cfc3d55c730df285c6e0117ceb90805aee7cfb86e0574d04c17aa09cdff9957b4a91a2af79a3d3",
"decryptShadows": [
"0x0429f62a48a25306bb64d8a5b74b0d6ee01f062fe1f7238f6b5078e3e7726751b46dd8834c5346bca3d6059ddc923747ecfea545579210db09f8a6708ab05f452ace3956408afddcb3b8796637198109fa046af23c6bcd6da5424cf8d7165d805c6265ea4e358731e4a71d32760d0423d12cf117d9b401bd2d7c321a4b9d47a79d383adce06c45352e23f2bec3262d637b",
"0x045fdbbb9782c046f3023e1d699ee9ae80413e44162ecf4f5ac6ace369f7e0604035abb3b7aed9d087293561ef75eb9296a6582cbefb1af7f449a97bcb5282f9b6cbb1059d595b2e2ec6cef40fceacf228462bebe985b8738e22c6ec196b25e408b7cbb608a74a167a2b5d4e12182e2942ded30d18a6b99b243395d4a4cabe25168560946ce3dd5d77b48b5148c78491e1"
]
}

View File

@ -0,0 +1 @@
"0x92c18be2b3f6aea31fc1e58f833936f16f635c0657bf03c3b05a0e3f5809ffec64736f0774b9be536e65a125b05fd21c0ae32a03c1338dcbe6ddb1ce2cd5b95a"

View File

@ -1,5 +1,6 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"lib": [
"es6",
"es7"