Skip to content

Commit

Permalink
initial version for cryptoconditions in JS
Browse files Browse the repository at this point in the history
  • Loading branch information
albertolerda committed Jun 22, 2022
1 parent 3a180e0 commit f1dea55
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 2 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
],
"dependencies": {
"asn1.js": "5.4.1",
"tweetnacl": "^1.0.3"
"tweetnacl": "^1.0.3",
"zenroom": "^2.2.3-bc442c74"
},
"optionalDependencies": {
"ed25519": "0.0.5"
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Up @@ -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()
)
})
8 changes: 8 additions & 0 deletions src/schemas/fulfillment.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ export const Ed25519Sha256Fulfillment = asn.define('Ed25519Sha256Fulfillment', f
)
})

export const ZenroomSha256Fulfillment = asn.define('Ed25519Sha256Fulfillment', 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),
Expand Down
129 changes: 129 additions & 0 deletions src/types/zenroom-sha256.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/**
* @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'

/**
* 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
}

parseJson (json) {
console.log(json)
this.setData(json.data)
}

/**
* 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: this.data,
keys: 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) {
if (!Buffer.isBuffer(message)) {
throw new TypeError('Message must be a Buffer')
}

// Use native library if available (~60x faster)
let result
if (ed25519) {
result = ed25519.Verify(message, this.signature, this.publicKey)
} else {
result = sign.detached.verify(bufferToUint8Array(message), bufferToUint8Array(this.signature), bufferToUint8Array(this.publicKey))
}

if (result !== true) {
throw new ValidationError('Invalid ed25519 signature')
}

return true
}
}

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
Expand Up @@ -3,6 +3,7 @@ import Fulfillment from './lib/fulfillment';
import TypeRegistry from './lib/type-registry';
import {
Ed25519Sha256Json,
ZenroomSha256Json,
PrefixSha256Json,
PreimageSha256Json,
RsaSha256Json,
Expand All @@ -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/ed25519-sha256';
import base64url from './util/base64url';

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

// Extras
Expand Down Expand Up @@ -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,
Expand All @@ -16,6 +17,7 @@ interface FulfillmentAsn1JsonValueMap {
[TypeAsn1Fulfillment.ThresholdSha256]: ThresholdSha256Json;
[TypeAsn1Fulfillment.RsaSha256]: RsaSha256Json;
[TypeAsn1Fulfillment.Ed25519Sha256]: Ed25519Sha256Json;
[TypeAsn1Fulfillment.ZenroomSha256]: ZenroomSha256Json;
}

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

getTypeId(): TypeId;
Expand Down
4 changes: 3 additions & 1 deletion types/lib/type-registry.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +21,8 @@ export interface RegisteredType {
| PrefixSha256
| ThresholdSha256
| RsaSha256
| Ed25519Sha256;
| Ed25519Sha256
| ZenroomSha256;
}

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

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

export enum TypeName {
Expand All @@ -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 {
Expand All @@ -31,6 +34,7 @@ export enum TypeAsn1Condition {
ThresholdSha256 = 'thresholdSha256Condition',
RsaSha256 = 'rsaSha256Condition',
Ed25519Sha256 = 'ed25519Sha256Condition',
ZenroomSha256 = 'zenroomSha256Condition',
}

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

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

export interface PreimageSha256Json {
Expand Down Expand Up @@ -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;
Expand All @@ -101,6 +119,7 @@ export interface ThresholdSha256Json {
| ThresholdSha256Json
| RsaSha256Json
| Ed25519Sha256Json
| ZenroomSha256Json
)[];
subconditions?: ConditionAsn1Json[];
}
Expand Down
41 changes: 41 additions & 0 deletions types/types/zenroom-sha256.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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();

parseJson(json: ZenroomSha256Json): void;

private getFingerprintContents(): Buffer;

getAsn1JsonPayload(): ZenroomSha256Asn1Json;

validate(message: Buffer): boolean;
}

0 comments on commit f1dea55

Please sign in to comment.