Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: bigchaindb/js-crypto-conditions
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: dyne/js-crypto-conditions
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 5 commits
  • 11 files changed
  • 3 contributors

Commits on Jun 22, 2022

  1. Copy the full SHA
    f1dea55 View commit details
  2. Copy the full SHA
    3c1e90e View commit details

Commits on Jun 23, 2022

  1. async 😣

    albertolerda committed Jun 23, 2022
    Copy the full SHA
    ab92440 View commit details

Commits on Jan 27, 2023

  1. Copy the full SHA
    87782c6 View commit details

Commits on Sep 18, 2024

  1. Merge pull request #1 from dyne/zenroom-dep

    Update zenroom version dependency
    puria authored Sep 18, 2024
    Copy the full SHA
    e8df32a View commit details
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -15,7 +15,9 @@
],
"dependencies": {
"asn1.js": "5.4.1",
"tweetnacl": "^1.0.3"
"json-stable-stringify": "^1.0.1",
"tweetnacl": "^1.0.3",
"zenroom": "^2.16.3"
},
"optionalDependencies": {
"ed25519": "0.0.5"
@@ -28,6 +30,7 @@
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"@babel/runtime-corejs3": "^7.17.2",
"@types/json-stable-stringify": "^1.0.34",
"babel-loader": "^8.2.2",
"buffer": "^6.0.3",
"chai": "^4.3.3",
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import PrefixSha256 from './types/prefix-sha256'
import ThresholdSha256 from './types/threshold-sha256'
import RsaSha256 from './types/rsa-sha256'
import Ed25519Sha256 from './types/ed25519-sha256'
import ZenroomSha256 from './types/zenroom-sha256'
import base64url from './util/base64url'

const EMPTY_BUFFER = Buffer.alloc(0)
@@ -15,6 +16,7 @@ TypeRegistry.registerType(PrefixSha256)
TypeRegistry.registerType(ThresholdSha256)
TypeRegistry.registerType(RsaSha256)
TypeRegistry.registerType(Ed25519Sha256)
TypeRegistry.registerType(ZenroomSha256)

export const validateCondition = (serializedCondition) => {
// Parse condition, throw on error
@@ -75,6 +77,7 @@ export {
PreimageSha256,
PrefixSha256,
ThresholdSha256,
ZenroomSha256,
RsaSha256,
base64url
}
6 changes: 6 additions & 0 deletions src/schemas/fingerprint.js
Original file line number Diff line number Diff line change
@@ -28,3 +28,9 @@ export const Ed25519FingerprintContents = asn1.define('Ed25519FingerprintContent
this.key('publicKey').implicit(0).octstr()
)
})

export const ZenroomFingerprintContents = asn1.define('ZenroomFingerprintContents', function () {
this.seq().obj(
this.key('script').implicit(0).octstr()
)
})
11 changes: 10 additions & 1 deletion src/schemas/fulfillment.js
Original file line number Diff line number Diff line change
@@ -37,12 +37,21 @@ export const Ed25519Sha256Fulfillment = asn.define('Ed25519Sha256Fulfillment', f
)
})

export const ZenroomSha256Fulfillment = asn.define('ZenroomSha256Fulfillment', function () {
this.seq().obj(
this.key('script').implicit(0).octstr(),
this.key('data').implicit(1).octstr(),
this.key('keys').implicit(2).octstr()
)
})

export const Fulfillment = asn.define('Fulfillment', function () {
this.choice({
preimageSha256Fulfillment: this.implicit(0).use(PreimageFulfillment),
prefixSha256Fulfillment: this.implicit(1).use(PrefixFulfillment),
thresholdSha256Fulfillment: this.implicit(2).use(ThresholdFulfillment),
rsaSha256Fulfillment: this.implicit(3).use(RsaSha256Fulfillment),
ed25519Sha256Fulfillment: this.implicit(4).use(Ed25519Sha256Fulfillment)
ed25519Sha256Fulfillment: this.implicit(4).use(Ed25519Sha256Fulfillment),
zenroomSha256Fulfillment: this.implicit(5).use(ZenroomSha256Fulfillment)
})
})
2 changes: 1 addition & 1 deletion src/types/base-sha256.js
Original file line number Diff line number Diff line change
@@ -20,4 +20,4 @@ class BaseSha256 extends Fulfillment {
}
}

export default BaseSha256;
export default BaseSha256;
165 changes: 165 additions & 0 deletions src/types/zenroom-sha256.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/**
* @module types
*/

import { sign } from 'tweetnacl'
import BaseSha256 from './base-sha256'
import MissingDataError from '../errors/missing-data-error'
import ValidationError from '../errors/validation-error'
import bufferToUint8Array from '../util/buffer-to-uint-array'
import { ZenroomFingerprintContents as Asn1ZenroomFingerprintContents } from '../schemas/fingerprint'
import { zencode_exec } from 'zenroom'
import {default as stringify} from 'json-stable-stringify';

/**
* Zenroom: Zenroom condition.
*
* This condition implements execution of arbitrary zencode scripts
*
* (For zenroom?)
* ED25519 is assigned the type ID 4. It relies only on the ED25519 feature
* suite which corresponds to a bitmask of 0x20.
*/
class ZenroomSha256 extends BaseSha256 {
constructor () {
super()
this.script = null
this.data = null
this.keys = null
}

setScript (script) {
if (typeof script != "string") {
throw new Error('The script must be a string')
}

this.script = script
}

setData (data) {

this.data = data
}

setKeys (keys) {
this.keys = keys
}

getScript () {
return this.script
}

getData () {
return this.data
}

getKeys () {
return this.keys
}

parseJson (json) {
this.setScript(json.script.toString('utf-8'))
this.setData(JSON.parse(json.data.toString('utf-8')))
this.setKeys(JSON.parse(json.keys.toString('utf-8')))
}

/**
* Produce the contents of the condition hash.
*
* This function is called internally by the `getCondition` method.
*
* @return {Buffer} Encoded contents of fingerprint hash.
*
* @private
*/
getFingerprintContents () {
if (!this.script) {
throw new MissingDataError('Requires a zencode script')
}

return Asn1ZenroomFingerprintContents.encode({
script: this.script
})
}

getAsn1JsonPayload () {
return {
script: this.script,
data: JSON.stringify(this.data),
keys: JSON.stringify(this.keys)
}
}

/**
* Calculate the cost of fulfilling this condition.
*
* The cost of the Ed25519 condition is 2^17 = 131072.
*
* @return {Number} Expected maximum cost to fulfill this condition
* @private
*/
calculateCost () {
return ZenroomSha256.CONSTANT_COST
}

/**
* Verify the signature of this Ed25519 fulfillment.
*
* The signature of this Ed25519 fulfillment is verified against the provided
* message and public key.
*
* @param {Buffer} message Message to validate against.
* @return {Boolean} Whether this fulfillment is valid.
*/
validate (message) {
throw new Error('Not implemented yet')
}


async sign(messageStr, condition_script, keyring) {
let message = JSON.parse(messageStr.toString('utf-8'))
const data = this.data || {}
try {
data.asset = message.asset.data
} catch(e) {}
const result = await zencode_exec(condition_script,
{ keys: JSON.stringify({keyring}),
data: JSON.stringify(data) })

message['metadata'] = message['metadata'] || {}

Object.assign(message['metadata'], {data: JSON.parse(result.result),
logs: result.logs})
return Buffer.from(JSON.stringify(message))

}

async validate(messageStr) {
const message = JSON.parse(messageStr.toString('utf-8'))
let data = this.data || {}
try {
data.asset = message.asset.data
} catch(e) {}
try {
data.result = message.metadata.data
} catch(e) {}

const zen = await zencode_exec(this.script,
{keys: JSON.stringify(this.keys),
data: JSON.stringify(data)})

const result = JSON.parse(zen.result)
return message.metadata.result &&
stringify(message.metadata.result) == stringify(result)
}
}

ZenroomSha256.TYPE_ID = 5
ZenroomSha256.TYPE_NAME = 'zenroom-sha-256'
ZenroomSha256.TYPE_ASN1_CONDITION = 'zenroomSha256Condition'
ZenroomSha256.TYPE_ASN1_FULFILLMENT = 'zenroomSha256Fulfillment'
ZenroomSha256.TYPE_CATEGORY = 'simple'

ZenroomSha256.CONSTANT_COST = 131072

export default ZenroomSha256;
4 changes: 4 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import Fulfillment from './lib/fulfillment';
import TypeRegistry from './lib/type-registry';
import {
Ed25519Sha256Json,
ZenroomSha256Json,
PrefixSha256Json,
PreimageSha256Json,
RsaSha256Json,
@@ -19,6 +20,7 @@ import PrefixSha256 from './types/prefix-sha256';
import ThresholdSha256 from './types/threshold-sha256';
import RsaSha256 from './types/rsa-sha256';
import Ed25519Sha256 from './types/ed25519-sha256';
import ZenroomSha256 from './types/zenroom-sha256';
import base64url from './util/base64url';

export { base64url, Condition, Fulfillment, TypeRegistry };
@@ -28,6 +30,7 @@ export {
PrefixSha256,
ThresholdSha256,
Ed25519Sha256,
ZenroomSha256,
};

// Extras
@@ -65,4 +68,5 @@ export function fromJson(
| ThresholdSha256Json
| RsaSha256Json
| Ed25519Sha256Json
| ZenroomSha256Json
): Fulfillment;
3 changes: 3 additions & 0 deletions types/lib/fulfillment.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Ed25519Sha256Json,
ZenroomSha256Json,
PreimageSha256Json,
PrefixSha256Json,
RsaSha256Json,
@@ -16,6 +17,7 @@ interface FulfillmentAsn1JsonValueMap {
[TypeAsn1Fulfillment.ThresholdSha256]: ThresholdSha256Json;
[TypeAsn1Fulfillment.RsaSha256]: RsaSha256Json;
[TypeAsn1Fulfillment.Ed25519Sha256]: Ed25519Sha256Json;
[TypeAsn1Fulfillment.ZenroomSha256]: ZenroomSha256Json;
}

export interface FulfillmentAsn1Json<
@@ -45,6 +47,7 @@ export default class Fulfillment {
| ThresholdSha256Json
| RsaSha256Json
| Ed25519Sha256Json
| ZenroomSha256Json
): Fulfillment;

getTypeId(): TypeId;
4 changes: 3 additions & 1 deletion types/lib/type-registry.d.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import type PrefixSha256 from '../types/prefix-sha256';
import type ThresholdSha256 from '../types/threshold-sha256';
import type RsaSha256 from '../types/rsa-sha256';
import type Ed25519Sha256 from '../types/ed25519-sha256';
import type ZenroomSha256 from '../types/zenroom-sha256';

export interface RegisteredType {
typeId: TypeId;
@@ -20,7 +21,8 @@ export interface RegisteredType {
| PrefixSha256
| ThresholdSha256
| RsaSha256
| Ed25519Sha256;
| Ed25519Sha256
| ZenroomSha256;
}

export default class TypeRegistry {
19 changes: 19 additions & 0 deletions types/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ export enum Types {
ThresholdSha256 = 'ThresholdSha256',
RsaSha256 = 'RsaSha256',
Ed25519Sha256 = 'Ed25519Sha256',
ZenroomSha256 = 'ZenroomSha256',
}

export enum TypeId {
@@ -15,6 +16,7 @@ export enum TypeId {
ThresholdSha256 = 2,
RsaSha256 = 3,
Ed25519Sha256 = 4,
ZenroomSha256 = 5,
}

export enum TypeName {
@@ -23,6 +25,7 @@ export enum TypeName {
ThresholdSha256 = 'threshold-sha-256',
RsaSha256 = 'rsa-sha-256',
Ed25519Sha256 = 'ed25519-sha-256',
ZenroomSha256 = 'zenroom-sha-256',
}

export enum TypeAsn1Condition {
@@ -31,6 +34,7 @@ export enum TypeAsn1Condition {
ThresholdSha256 = 'thresholdSha256Condition',
RsaSha256 = 'rsaSha256Condition',
Ed25519Sha256 = 'ed25519Sha256Condition',
ZenroomSha256 = 'zenroomSha256Condition',
}

export enum TypeAsn1Fulfillment {
@@ -39,6 +43,7 @@ export enum TypeAsn1Fulfillment {
ThresholdSha256 = 'thresholdSha256Fulfillment',
RsaSha256 = 'rsaSha256Fulfillment',
Ed25519Sha256 = 'ed25519Sha256Fulfillment',
ZenroomSha256 = 'zenroomSha256Fulfillment',
}

export enum TypeCategory {
@@ -47,6 +52,7 @@ export enum TypeCategory {
ThresholdSha256 = 'compound',
RsaSha256 = 'simple',
Ed25519Sha256 = 'simple',
ZenroomSha256 = 'simple',
}

export interface PreimageSha256Json {
@@ -92,6 +98,18 @@ export interface Ed25519Sha256Asn1Json {
signature: Buffer;
}

export interface ZenroomSha256Json {
type: Types.ZenroomSha256;
script: string;
data: string;
keys: string;
}

export interface ZenroomSha256Asn1Json {
script: Buffer;
data: Buffer;
keys: Buffer;
}
export interface ThresholdSha256Json {
type: Types.ThresholdSha256;
threshold: number;
@@ -101,6 +119,7 @@ export interface ThresholdSha256Json {
| ThresholdSha256Json
| RsaSha256Json
| Ed25519Sha256Json
| ZenroomSha256Json
)[];
subconditions?: ConditionAsn1Json[];
}
50 changes: 50 additions & 0 deletions types/types/zenroom-sha256.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type {
ZenroomSha256Asn1Json,
ZenroomSha256Json,
TypeAsn1Condition,
TypeAsn1Fulfillment,
TypeCategory,
TypeId,
TypeName,
} from '.';
import type BaseSha256 from './base-sha256';

export const TYPE_ID: TypeId.ZenroomSha256;
export const TYPE_NAME: TypeName.ZenroomSha256;
export const TYPE_ASN1_CONDITION: TypeAsn1Condition.ZenroomSha256;
export const TYPE_ASN1_FULFILLMENT: TypeAsn1Fulfillment.ZenroomSha256;
export const TYPE_CATEGORY: TypeCategory.ZenroomSha256;

export const CONSTANT_COST = 131072;
export default class ZenroomSha256 extends BaseSha256 {
private publicKey: Record<string, any>;
private signature: Record<string, any>;

static TYPE_ID: TypeId.ZenroomSha256;
static TYPE_NAME: TypeName.ZenroomSha256;
static TYPE_ASN1_CONDITION: TypeAsn1Condition.ZenroomSha256;
static TYPE_ASN1_FULFILLMENT: TypeAsn1Fulfillment.ZenroomSha256;
static TYPE_CATEGORY: TypeCategory.ZenroomSha256;

static CONSTANT_COST: number;

constructor();

setScript(script: string): void;
setData(data: Record<string, any>): void;
setKeys(keys: Record<string, any>): void;

getScript(): string;
getData(): Record<string, any>;
getKeys(): Record<string, any>;

parseJson(json: ZenroomSha256Json): void;

private getFingerprintContents(): Buffer;

getAsn1JsonPayload(): ZenroomSha256Asn1Json;

async sign(message: Buffer, condition_script: string, private_keys: Record<string, any>): Buffer;
async validate(message: Buffer): boolean;
}