diff --git a/app/lib/keyhelper.js b/app/lib/keyhelper.js index 45c7d832b071ae279fcc05aad89040736cb6c30b..cac6051341edd7ccdb26d3694409411cdc76fa4d 100644 --- a/app/lib/keyhelper.js +++ b/app/lib/keyhelper.js @@ -4,10 +4,24 @@ var PacketList = openpgp.packet.List; module.exports = { + fromKey: function (key){ + return new KeyHelper(key.toPacketlist()); + }, + fromPackets: function (packetList){ return new KeyHelper(packetList); }, + fromEncodedPackets: function (encodedPackets){ + return this.fromDecodedPackets(base64.decode(encodedPackets)); + }, + + fromDecodedPackets: function (decodedPackets){ + var list = new openpgp.packet.List(); + list.read(decodedPackets); + return new KeyHelper(list); + }, + fromArmored: function (armored){ var readKeys = openpgp.key.readArmored(armored).keys; var packets = new PacketList(); @@ -26,6 +40,10 @@ function KeyHelper (packetList) { var that = this; var key = new openpgp.key.Key(packetList); + this.getFingerprint = function (){ + return key && key.primaryKey && key.primaryKey.getFingerprint().toUpperCase(); + }; + this.getUserID = function (param, next){ var primaryUser = key.getPrimaryUser(); return primaryUser && primaryUser.user && primaryUser.user.userId && primaryUser.user.userId.userid; diff --git a/app/models/key.js b/app/models/key.js index 24a42e23eacb3b9e79b7a8d8ab6a86565cf4a151..d8cb81004f0c9c65950582cb3ea902f8cde1b7ff 100644 --- a/app/models/key.js +++ b/app/models/key.js @@ -124,7 +124,7 @@ KeySchema.statics.setKicked = function(fingerprint, done){ }); }; -KeySchema.statics.removeKicked = function(fingerprint, done){ +KeySchema.statics.unsetKicked = function(fingerprint, done){ var Key = this.model('Key'); Key.update({ fingerprint: fingerprint }, { kick: false }, function (err) { done(err); diff --git a/app/models/keyblock.js b/app/models/keyblock.js index ce98f427841bf7807f5fb4549e60f1074667255f..60468f382b959d80141967a67afedcdb3501d7a4 100644 --- a/app/models/keyblock.js +++ b/app/models/keyblock.js @@ -70,6 +70,16 @@ KeyBlockSchema.methods = { return json; }, + getNewPubkeys: function() { + var pubkeys = []; + this.keysChanges.forEach(function(kc){ + if (kc.type == 'F' || kc.type == 'N') { + pubkeys.push(kc.keypackets); + } + }); + return pubkeys; + }, + getPublicKeysPackets: function() { var pubkeys = []; this.publicKeys.forEach(function(obj){ @@ -197,8 +207,15 @@ KeyBlockSchema.methods = { getMemberships: function() { var notFoundMembership = 0; var mss = {}; - this.memberships.forEach(function(shortMS){ + this.keysChanges.forEach(function(kc){ + var shortSIG = kc.membership.signature; + var shortMS = kc.membership.membership; + // Membership content var sp = shortMS.split(':'); + // Signature + var signature = '-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1\n\n'; + signature += shortSIG; + signature += '-----END PGP SIGNATURE-----\n'; var ms = { version: sp[0], keyID: sp[1].substring(24), @@ -206,20 +223,10 @@ KeyBlockSchema.methods = { membership: sp[2], date: new Date(parseInt(sp[3])*1000), userid: sp[4], + signature: signature }; mss[ms.keyID] = ms; }); - this.membershipsSigs.forEach(function(msSig){ - var keyID = msSig.fingerprint.substring(24); - if (mss[keyID]) { - var signature = '-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1\n\n'; - signature += msSig.packets; - signature += '-----END PGP SIGNATURE-----\n'; - mss[keyID].signature = signature; - mss[keyID].issuer = msSig.fingerprint; - } - else notFoundMembership++; - }); return { 'notFoundMembership': notFoundMembership, 'mss': mss diff --git a/app/models/trustedkey.js b/app/models/trustedkey.js new file mode 100644 index 0000000000000000000000000000000000000000..0771b03d3b0cb06dfd27311b6b37c1a69debf679 --- /dev/null +++ b/app/models/trustedkey.js @@ -0,0 +1,29 @@ +var mongoose = require('mongoose'); +var Schema = mongoose.Schema; + +var TrustedKeySchema = new Schema({ + keyID: { type: String, unique: true }, + fingerprint: String, + uid: String, + packets: String, + created: { type: Date, default: Date.now }, + updated: { type: Date, default: Date.now } +}); + +TrustedKeySchema.pre('save', function (next) { + this.updated = Date.now(); + next(); +}); + +TrustedKeySchema.statics.getTheOne = function (keyID, done) { + this.find({ keyID: keyID }, function (err, keys) { + if(keys.length < 1){ + done('Trusted Key 0x' + keyID + ' not found.'); + return; + } + var pubkey = keys[0]; + done(null, pubkey); + }); +}; + +module.exports = TrustedKeySchema; diff --git a/app/service/KeychainService.js b/app/service/KeychainService.js index a9830f12f30c0007da28d0fb1e7e4e7eab751668..9a6a6bcea6c659117e6380c98618ea0e1e613145 100644 --- a/app/service/KeychainService.js +++ b/app/service/KeychainService.js @@ -22,6 +22,7 @@ function KeyService (conn, conf, PublicKeyService) { var Membership = conn.model('Membership'); var KeyBlock = conn.model('KeyBlock'); var PublicKey = conn.model('PublicKey'); + var TrustedKey = conn.model('TrustedKey'); var Link = conn.model('Link'); var Key = conn.model('Key'); @@ -136,13 +137,12 @@ function KeyService (conn, conf, PublicKeyService) { }, function (next) { // Check document's coherence - // checkCoherence(currentBlock, block, next); - // }, - // function (next) { + checkCoherence(currentBlock, block, next); + }, + function (next) { // Save block data + compute links obsolescence - console.log('OK'); - next(null, block); - // saveBlockData(block, next); + // next(null, block); + saveBlockData(block, next); } ], done); }; @@ -154,12 +154,8 @@ function KeyService (conn, conf, PublicKeyService) { checkKicked(block, next); }, function (next){ - // Check memberships - checkMemberships(current, block, next); - }, - function (next){ - // Check certifications updates - checkCertificationsUpdates(block, next); + // Check key changes + checkKeychanges(current, block, next); }, function (next){ // Check members' changes (+ and -), root & count @@ -170,6 +166,20 @@ function KeyService (conn, conf, PublicKeyService) { }); } + function checkKeychanges (current, block, done) { + if (current) { + done('Post-root blocks are not managed yet'); + } else { + checkRootBlockKeychanges(block, done); + } + } + + function checkRootBlockKeychanges(block, done) { + async.forEach(block.keysChanges, function(kc, callback){ + callback(kc.type != 'F' ? 'Root block must contain only FOUNDER keychanges' : null); + }, done); + } + function checkMemberships (current, block, done) { // Test membership var basicPubkeys = block.getBasicPublicKeys(); @@ -432,15 +442,15 @@ function KeyService (conn, conf, PublicKeyService) { } function updateMembers (block, done) { - var mss = block.getMemberships().mss; - async.forEach(_(mss).values(), function(ms, callback){ - var doMember = ms.membership == 'IN' ? Key.addMember : Key.removeMember; + async.forEach(block.membersChanges, function(mc, callback){ + var isPlus = mc[0] == '+'; + var fpr = mc.substring(1); async.waterfall([ function (next){ - doMember.call(Key, ms.fingerprint, next); + (isPlus ? Key.addMember : Key.removeMember).call(Key, fpr, next); }, function (next) { - Key.removeKicked(ms.fingerprint, next); + Key.unsetKicked(fpr, next); } ], callback); }, done); @@ -460,21 +470,19 @@ function KeyService (conn, conf, PublicKeyService) { }, function (next){ // Save new pubkeys - var pubkeys = block.getBasicPublicKeys(); - async.forEach(pubkeys, function(key, callback){ - var armored = unix2dos(key.armor()); - var parser = parsers.parsePubkey(next); - async.waterfall([ - function (next){ - parser.asyncWrite(armored, next); - }, - function (json, next) { - json.keychain = base64.encode(key.toPacketlist().write()); - PublicKeyService.submitPubkey(json, function (err) { - next(err); - }); - }, - ], callback); + var pubkeys = block.getNewPubkeys(); + async.forEach(pubkeys, function(encodedPackets, callback){ + var key = keyhelper.fromEncodedPackets(encodedPackets); + var fpr = key.getFingerprint(); + var kid = fpr.substring(24); + var trusted = new TrustedKey({ + fingerprint: fpr, + keyID: kid, + packets: encodedPackets + }); + trusted.save(function (err){ + callback(err); + }); }, next); }, function (next){ @@ -483,24 +491,25 @@ function KeyService (conn, conf, PublicKeyService) { }, function (next){ // Save links - var certifs = block.getTierCertificationPackets(); - async.forEach(certifs, function(certif, callback){ - async.waterfall([ - function (next){ - PublicKey.getTheOne(certif.issuerKeyId.toHex().toUpperCase(), next); - }, - function (pubk, next){ - var link = new Link({ - source: pubk.fingerprint, - target: certif.target, - timestamp: certif.created.timestamp() - }); - link.save(function (err) { - next(err); - }); - }, - ], callback); - }, next); + next(); + // var certifs = block.getTierCertificationPackets(); + // async.forEach(certifs, function(certif, callback){ + // async.waterfall([ + // function (next){ + // PublicKey.getTheOne(certif.issuerKeyId.toHex().toUpperCase(), next); + // }, + // function (pubk, next){ + // var link = new Link({ + // source: pubk.fingerprint, + // target: certif.target, + // timestamp: certif.created.timestamp() + // }); + // link.save(function (err) { + // next(err); + // }); + // }, + // ], callback); + // }, next); }, function (next){ // Save memberships @@ -511,7 +520,8 @@ function KeyService (conn, conf, PublicKeyService) { }, function (next){ // Compute obsolete links - computeObsoleteLinks(block, next); + next(); + // computeObsoleteLinks(block, next); }, ], function (err) { done(err, block); diff --git a/server.js b/server.js index 58c0edb1aa8ffd86456a735fad556a0dd54eb183..69b030dbfd1a158a9c0966996982947335ac335c 100644 --- a/server.js +++ b/server.js @@ -10,7 +10,7 @@ var http = require('http'); var log4js = require('log4js'); var connectPgp = require('connect-pgp'); -var models = ['Amendment', 'Coin', 'Configuration', 'Forward', 'Key', 'Link', 'CKey', 'Merkle', 'Peer', 'PublicKey', 'Wallet', 'Transaction', 'TxMemory', 'Membership', 'KeyBlock']; +var models = ['Amendment', 'Coin', 'Configuration', 'Forward', 'Key', 'Link', 'TrustedKey', 'Merkle', 'Peer', 'PublicKey', 'Wallet', 'Transaction', 'TxMemory', 'Membership', 'KeyBlock']; var INNER_WRITE = true; function Server (dbConf, overrideConf, interceptors, onInit) { @@ -175,6 +175,7 @@ function Server (dbConf, overrideConf, interceptors, onInit) { 'wallets', 'transactions', 'txmemories', + 'trustedkeys', 'memberships']; async.forEachSeries(deletableCollections, function(collection, next){ if (that.conn.collections[collection]) { diff --git a/wotserver.js b/wotserver.js index f22380d8c93982a8debacc88d6a8dc118135b290..a7df37c8bf76e21a269b07508f92735c77138d0a 100644 --- a/wotserver.js +++ b/wotserver.js @@ -35,7 +35,7 @@ function WOTServer (dbConf, overrideConf, interceptors, onInit) { server.KeychainService.submitKeyBlock(obj, next); }, function (tx, next){ - server.emit('transaction', tx); + server.emit('keyblock', tx); next(null, tx); }, ], next);