From 3eae5fd62c9cbfccda6fb0f58908a840a27c7cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zochniak?= Date: Thu, 16 Jan 2020 23:18:58 +0100 Subject: [PATCH] Add `debug_localize` to schema3 It's used to convert packed sig3 links to user-readable JSON objects. --- CHANGELOG.md | 5 +++++ lib/schema3.js | 39 ++++++++++++++++++++++++++++++++++++- lib/sig3.js | 28 +++++++++++++++----------- lib/team_hidden.js | 2 +- package-lock.json | 2 +- package.json | 2 +- src/schema3.iced | 19 ++++++++++++++++++ src/sig3.iced | 8 ++++++-- src/team_hidden.iced | 4 ++-- test/files/team_hidden.iced | 29 +++++++++++++++++++++++++++ 10 files changed, 119 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfcee02..cb3a6bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.3.16 (2020-01-22) + +- Add sig3/Base::get_schema() and schema3/Node::debug_localize for transforming + message-packed sig3 signatures to user-readable JSON objects. + ## 2.3.15 (2020-01-16) - Support `assert_pgp_hash` optional argument, passed to KBPGP. diff --git a/lib/schema3.js b/lib/schema3.js index bb02955..ad343a1 100644 --- a/lib/schema3.js +++ b/lib/schema3.js @@ -1,4 +1,4 @@ -// Generated by IcedCoffeeScript 108.0.12 +// Generated by IcedCoffeeScript 108.0.11 (function() { var Array, Binary, Bool, ChainType, Dict, Int, KID, LinkType, Node, Object, Or, Path, PtkType, Seqno, String, StringEnum, Struct, Time, Value, mkerr, parse, __hasProp = {}.hasOwnProperty, @@ -72,6 +72,10 @@ }); }; + Node.prototype.debug_localize = function(obj) { + return obj; + }; + Node.prototype._check_value = function(_arg) { var checker, obj, path; checker = _arg.checker, path = _arg.path, obj = _arg.obj; @@ -132,6 +136,19 @@ return null; }; + Dict.prototype.debug_localize = function(obj) { + var k, ret, v, _ref; + ret = {}; + _ref = this._keys; + for (k in _ref) { + v = _ref[k]; + if (obj[k] != null) { + ret[v._name || k] = v.debug_localize(obj[k]); + } + } + return ret; + }; + Dict.prototype.set_key = function(k, v) { return this._keys[k] = v; }; @@ -155,6 +172,16 @@ return this; }; + Array.prototype.debug_localize = function(obj) { + var i, ret, v, _i, _len; + ret = []; + for (i = _i = 0, _len = obj.length; _i < _len; i = ++_i) { + v = obj[i]; + ret[i] = this._elem.debug_localize(obj[i]); + } + return ret; + }; + Array.prototype._check = function(_arg) { var err, i, new_path, o, obj, path, _i, _len; path = _arg.path, obj = _arg.obj; @@ -191,6 +218,16 @@ this._slots = slots; } + Struct.prototype.debug_localize = function(obj) { + var i, ret, v, _i, _len; + ret = []; + for (i = _i = 0, _len = obj.length; _i < _len; i = ++_i) { + v = obj[i]; + ret[i] = this._slots[i].debug_localize(obj[i]); + } + return ret; + }; + Struct.prototype._check = function(_arg) { var err, i, new_path, o, obj, path, _i, _len; path = _arg.path, obj = _arg.obj; diff --git a/lib/sig3.js b/lib/sig3.js index 888489e..5c5ea6b 100644 --- a/lib/sig3.js +++ b/lib/sig3.js @@ -158,9 +158,8 @@ return this.ignore_if_unsupported = outer_obj.ignore_if_unsupported; }; - Base.prototype._enforce_schema = function(_arg, cb) { - var json, schm; - json = _arg.json; + Base.prototype.get_schema = function() { + var schm; schm = schema.dict({ c: schema.time().name("ctime"), e: schema.binary(16).name("entropy"), @@ -185,6 +184,13 @@ }).optional().name("client_info") }).name("inner"); this._v_extend_schema(schm); + return schm; + }; + + Base.prototype._enforce_schema = function(_arg, cb) { + var json, schm; + json = _arg.json; + schm = this.get_schema(); return cb(schm.check(json)); }; @@ -204,7 +210,7 @@ _this._enforce_schema({ json: json }, esc(__iced_deferrals.defer({ - lineno: 134 + lineno: 138 }))); __iced_deferrals._fulfill(); }); @@ -240,7 +246,7 @@ return km = arguments[0]; }; })(), - lineno: 146 + lineno: 150 }))); __iced_deferrals._fulfill(); })(function() { @@ -267,7 +273,7 @@ _this._v_decode_inner({ json: json }, esc(__iced_deferrals.defer({ - lineno: 159 + lineno: 163 }))); __iced_deferrals._fulfill(); })(function() { @@ -335,7 +341,7 @@ return res = arguments[0]; }; })(), - lineno: 191 + lineno: 195 })), { prefix: _this._prefix() }); @@ -368,7 +374,7 @@ _this._check_clock_skew({ now: now }, esc(__iced_deferrals.defer({ - lineno: 198 + lineno: 202 }))); __iced_deferrals._fulfill(); }); @@ -440,7 +446,7 @@ return inner = arguments[0]; }; })(), - lineno: 234 + lineno: 238 }))); __iced_deferrals._fulfill(); }); @@ -465,7 +471,7 @@ return outer = arguments[0].outer; }; })(), - lineno: 236 + lineno: 240 }))); __iced_deferrals._fulfill(); })(function() { @@ -484,7 +490,7 @@ return sig = arguments[0]; }; })(), - lineno: 237 + lineno: 241 }))); __iced_deferrals._fulfill(); })(function() { diff --git a/lib/team_hidden.js b/lib/team_hidden.js index af464d1..d334e07 100644 --- a/lib/team_hidden.js +++ b/lib/team_hidden.js @@ -57,7 +57,7 @@ i: schema.binary(16).name("team_id"), m: schema.bool().optional().name("is_implicit"), p: schema.bool().optional().name("is_public") - })); + }).name('team')); }; TeamBase.prototype._v_decode_inner = function(_arg, cb) { diff --git a/package-lock.json b/package-lock.json index 3b109c4..f9b054b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "keybase-proofs", - "version": "2.3.15", + "version": "2.3.16", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9a00658..26cf926 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keybase-proofs", - "version": "2.3.15", + "version": "2.3.16", "description": "Publicly-verifiable proofs of identity", "main": "lib/main.js", "scripts": { diff --git a/src/schema3.iced b/src/schema3.iced index da8ba36..3548780 100644 --- a/src/schema3.iced +++ b/src/schema3.iced @@ -29,6 +29,7 @@ class Node _check : ({path, obj}) -> mkerr path, "internal error, no checker found" check : (obj) -> @_check { path : Path.top(@_name), obj } + debug_localize : (obj) -> obj _check_value : ({checker, path, obj}) -> if not obj? and checker.is_optional() then return null @@ -52,6 +53,12 @@ class Dict extends Node if not obj[k]? and not v.is_optional() then return mkerr new_path, "key is missing but is mandatory" return null + debug_localize : (obj) -> + ret = {} + for k,v of @_keys when obj[k]? + ret[v._name or k] = v.debug_localize obj[k] + ret + set_key : (k,v) -> @_keys[k] = v @@ -65,6 +72,12 @@ class Array extends Node @_empty_is_ok = true @ + debug_localize : (obj) -> + ret = [] + for v,i in obj + ret[i] = @_elem.debug_localize obj[i] + ret + _check : ({path, obj}) -> unless parse.is_array(obj) return mkerr path, "need an array" @@ -80,6 +93,12 @@ class Struct extends Node constructor : ({slots}) -> @_slots = slots + debug_localize : (obj) -> + ret = [] + for v,i in obj + ret[i] = @_slots[i].debug_localize obj[i] + ret + _check : ({path, obj}) -> unless parse.is_array(obj) return mkerr path, "need an array" diff --git a/src/sig3.iced b/src/sig3.iced index 95eb46e..f739a2b 100644 --- a/src/sig3.iced +++ b/src/sig3.iced @@ -105,7 +105,7 @@ exports.Base = class Base @prev = outer_obj.prev @ignore_if_unsupported = outer_obj.ignore_if_unsupported - _enforce_schema : ({json}, cb) -> + get_schema : () -> schm = schema.dict({ c : schema.time().name("ctime") e : schema.binary(16).name("entropy") @@ -127,6 +127,10 @@ exports.Base = class Base }).optional().name("client_info") }).name("inner") @_v_extend_schema schm + return schm + + _enforce_schema : ({json}, cb) -> + schm = @get_schema() cb schm.check json decode_inner : ({json, outer_obj}, cb) -> @@ -240,4 +244,4 @@ exports.Base = class Base {json, armored} = _encode_dict raw cb null, { raw, armored, json } -#------------------------- \ No newline at end of file +#------------------------- diff --git a/src/team_hidden.iced b/src/team_hidden.iced index ab9a81b..617d3da 100644 --- a/src/team_hidden.iced +++ b/src/team_hidden.iced @@ -34,7 +34,7 @@ exports.TeamBase = class TeamBase extends Base t : schema.chain_type().name("chain_type") }).optional().name("implicit_admin") i : schema.binary(16).name("team_id") m : schema.bool().optional().name("is_implicit") - p : schema.bool().optional().name("is_public") }) + p : schema.bool().optional().name("is_public") }).name('team') _v_decode_inner : ({json}, cb) -> @team = { @@ -174,4 +174,4 @@ exports.RotateKey = class RotateKey extends TeamBase reverse_sig : k.reverse_sig.toString('base64') return ret -#------------------ \ No newline at end of file +#------------------ diff --git a/test/files/team_hidden.iced b/test/files/team_hidden.iced index 33ea683..ed2960d 100644 --- a/test/files/team_hidden.iced +++ b/test/files/team_hidden.iced @@ -290,3 +290,32 @@ exports.test_bad_reverse_sig = (T,cb) -> T.equal err.message, "Signature failed to verify", "right error" T.assert (err.stack.indexOf("_v_verify_reverse_sig") > 0), "we find a reverse sig in the stack" cb null + +exports.test_schema_localize = (T, cb) -> + esc = make_esc cb + await gen { T }, esc defer { km, ret, arg } + [err, outer_obj] = sig3.OuterLink.decode ret.raw.outer + T.no_error err + + obj = new team_hidden.RotateKey {} + await obj.decode_inner { json: ret.raw.inner, outer_obj }, esc defer() + localized = obj.get_schema().debug_localize(ret.raw.inner) + + for f in ['ctime', 'entropy', 'merkle_root', 'signer', 'parent_chain_tail', 'client_info', 'team', 'body'] + T.assert localized[f]?, "looking for field #{f}" + for f in ['ctime', 'hash_meta', 'seqno'] + T.assert localized.merkle_root?[f]?, "looking for field merkle_root.#{f}" + for f in ['eldest_seqno', 'kid', 'uid'] + T.assert localized.signer?[f]?, "looking for field signer.#{f}" + for f in ['tail', 'seqno', 'chain_type'] + T.assert localized.parent_chain_tail?[f]?, "looking for field parent_chain_tail.#{f}" + for f in ['description', 'version'] + T.assert localized.client_info?[f]?, "looking for field client_info.#{f}" + for f in ['team_id', 'is_implicit', 'is_public'] + T.assert localized.team?[f]?, "looking for field team.#{f}" + T.assert localized.body?.keys?, "looking for localized.body.keys" + for k in localized.body?.keys ? [] + for f in ['appkey_derivation_version', 'seed_check', 'encryption_kid', 'generation', 'reverse_sig', 'signing_kid', 'ptk_type'] + T.assert k[f]?, "looking for field body.keys.#{f}" + + cb null