Skip to content

Commit

Permalink
SGX computation support (#34)
Browse files Browse the repository at this point in the history
Co-authored-by: filipgolem <[email protected]>
  • Loading branch information
mfranciszkiewicz and filipgolem authored Nov 13, 2020
1 parent f91fa33 commit 1e02cb1
Show file tree
Hide file tree
Showing 13 changed files with 692 additions and 150 deletions.
4 changes: 2 additions & 2 deletions examples/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yajsapi_examples",
"version": "0.1.0",
"version": "0.1.1",
"description": "NodeJS API Examples for Next Golem",
"repository": "https://github.com/golemfactory/yajsapi",
"scripts": {
Expand All @@ -15,7 +15,7 @@
"bluebird": "^3.5.0",
"dayjs": "^1.8.31",
"ts-node": "^9.0.0",
"yajsapi": "0.1.0-alpha.3"
"yajsapi": "file:../"
},
"devDependencies": {
"tsconfig-paths": "^3.9.0",
Expand Down
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yajsapi",
"version": "0.1.0-alpha.3",
"version": "0.1.1-alpha.3",
"description": "NodeJS API for Next Golem",
"repository": "https://github.com/golemfactory/yajsapi",
"main": "dist/index.js",
Expand All @@ -18,16 +18,23 @@
"axios": "^0.19.2",
"bluebird": "^3.5.0",
"commander": "^6.2.0",
"dayjs": "^1.9.6",
"dayjs": "~1.9.1",
"js-csp": "^1.0.1",
"eccrypto": "^1.1.5",
"minimist": "^1.2.5",
"rewire": "^3.0.2",
"secp256k1": "^4.0.2",
"sgx-ias-js": "~0.1.1",
"tmp": "^0.2.1",
"utf8": "~3.0.0",
"uuid": "^8.3.1",
"winston": "^3.3.3",
"ya-ts-client": "^0.2.0"
},
"devDependencies": {
"@types/eccrypto": "^1.1.2",
"@types/node": "14.6.2",
"@types/utf8": "^2.1.6",
"ts-node": "^9.0.0",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.9.7"
Expand Down
123 changes: 123 additions & 0 deletions yajsapi/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import * as crypto from "crypto";
import * as eccrypto from "eccrypto";
import * as secp256k1 from "secp256k1";

export function rand_hex(length: number): string {
let byte_sz = Math.floor(length / 2);
return crypto.randomBytes(byte_sz).toString("hex");
}

export class PrivateKey {
inner!: Buffer;

constructor() {
this.inner = eccrypto.generatePrivate();
}

static from(buffer: Buffer): PrivateKey {
let key = Object.create(this.prototype);
key.inner = buffer;
return key;
}

static fromHex(hex: string): PublicKey {
let inner = Buffer.from(hex, "hex");
return PublicKey.from(inner);
}

publicKey(compressed: boolean = true): PublicKey {
let buffer = compressed
? eccrypto.getPublicCompressed(this.inner)
: eccrypto.getPublic(this.inner);
return PublicKey.from(buffer);
}

async derive(publicKey: PublicKey): Promise<Buffer> {
return await eccrypto.derive(this.inner, publicKey.inner);
}

async sign(msg: Buffer) {
return await eccrypto.sign(this.inner, msg);
}

toString(): string {
return this.inner.toString("hex");
}
}

export class PublicKey {
inner!: Buffer;

private constructor() {}

static from(buffer: Buffer): PublicKey {
let key = Object.create(this.prototype);
key.inner = buffer;
return key;
}

static fromHex(hex: string): PublicKey {
let inner = Buffer.from(hex, "hex");
return PublicKey.from(inner);
}

toString(): string {
return this.inner.toString("hex");
}
}

export class CryptoCtx {
priv_key!: PrivateKey;
ephem_key!: Buffer;

static async from(pub_key: PublicKey, priv_key?: PrivateKey): Promise<CryptoCtx> {
priv_key = priv_key ? priv_key : new PrivateKey();
let ephem_key = Buffer.from(secp256k1.ecdh(pub_key.inner, priv_key.inner));
return new CryptoCtx(priv_key, ephem_key);
}

private constructor(priv_key: PrivateKey, ephem_key: Buffer) {
this.priv_key = priv_key;
this.ephem_key = ephem_key;
}

encrypt(data: Buffer): Buffer {
let iv = crypto.randomBytes(12);
let cipher = crypto.createCipheriv("aes-256-gcm", this.ephem_key, iv);

let chunk_1 = cipher.update(data);
let chunk_2 = cipher.final();
let tag = cipher.getAuthTag();

let buffer = Buffer.alloc(1 + iv.length + 1 + tag.length, 0, 'binary');
let off = 0;

buffer.writeUInt8(iv.length, off);
off += 1;
iv.copy(buffer, off);
off += iv.length;
buffer.writeUInt8(tag.length, off);
off += 1;
tag.copy(buffer, off);

return Buffer.concat([buffer, chunk_1, chunk_2]);
}

decrypt(data: Buffer): Buffer {
let off = 0;
let iv_length = data.readUInt8(off);
off += 1;
let iv = data.slice(off, off + iv_length);
off += iv_length;
let tag_length = data.readUInt8(off);
off += 1;
let tag = data.slice(off, off + tag_length);
off += tag_length;
let enc = data.slice(off);

var cipher = crypto.createDecipheriv("aes-256-gcm", this.ephem_key, iv);
cipher.setAuthTag(tag);

return Buffer.concat([cipher.update(enc), cipher.final()]);
}
}
4 changes: 2 additions & 2 deletions yajsapi/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import events from "events";
import { Engine, Task, vm } from "./runner";
import { Engine, Task, sgx, vm } from "./runner";
import { WorkContext } from "./runner/ctx";
import * as props from "./props";
import * as rest from "./rest";
import * as storage from "./storage";
import * as utils from "./utils";

export { Engine, Task, vm, WorkContext, props, rest, storage, utils };
export { Engine, Task, sgx, vm, WorkContext, props, rest, storage, utils };
50 changes: 13 additions & 37 deletions yajsapi/props/inf.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,34 @@
import { Field, Model } from "./base";

const INF_MEM: string = "golem.inf.mem.gib";
const INF_STORAGE: string = "golem.inf.storage.gib";
const INF_CORES: string = "golem.inf.cpu.cores";
const INF_RUNTIME: string = "golem.runtime.name";
const TRANSFER_CAPS: string = "golem.activity.caps.transfer.protocol";
export const INF_MEM: string = "golem.inf.mem.gib";
export const INF_STORAGE: string = "golem.inf.storage.gib";
export const INF_CORES: string = "golem.inf.cpu.cores";
export const INF_RUNTIME: string = "golem.runtime.name";
export const TRANSFER_CAPS: string = "golem.activity.caps.transfer.protocol";

export enum RuntimeType {
UNKNOWN = "",
WASMTIME = "wasmtime",
EMSCRIPTEN = "emscripten",
VM = "vm",
}

enum WasmInterface {
WASI_0 = "0",
WASI_0preview1 = "0preview1",
SGX_WASI = "sgx",
SGX_JS_SP = "sgx-js-sp",
}

export class InfBase {
cores: Field = new Field({ metadata: { key: INF_CORES } });
mem: Field = new Field({ metadata: { key: INF_MEM } });
runtime: Field = new Field({ metadata: { key: INF_RUNTIME } });

storage?: Field = new Field({ metadata: { key: INF_STORAGE } });
transfers: Field = new Field({ metadata: { key: TRANSFER_CAPS } });
}

export class InfVm extends InfBase {
runtime = new Field({
value: RuntimeType.VM,
metadata: { key: INF_RUNTIME },
});
cores: Field = new Field({ value: 1, metadata: { key: INF_CORES } });
static fields(inf: InfBase, keys: string[]) {
return getFields(inf, keys);
}
}

export const InfVmKeys = getFields(new InfVm(), ["mem", "storage", "runtime"]);

function getFields(obj, keys) {
function getFields(obj: object, keys: string[]) {
let fields = {};
keys.forEach((key) => {
fields[key] = obj[key].metadata.key;
Expand All @@ -49,24 +41,8 @@ export class ExeUnitRequest extends Model {
package_url: Field = new Field({
metadata: { key: "golem.srv.comp.task_package" },
});
constructor(package_url) {
constructor(package_url: any) {
super();
this.package_url.value = package_url;
}
}

export enum VmPackageFormat {
UNKNOWN = "",
GVMKIT_SQUASH = "gvmkit-squash",
}

export class VmRequest extends ExeUnitRequest {
package_format: Field = new Field({
metadata: { key: "golem.srv.comp.vm.package_format" },
});

constructor(package_url, package_format) {
super(package_url);
this.package_format.value = package_format;
}
}
Loading

0 comments on commit 1e02cb1

Please sign in to comment.