Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added key trust model

  • Loading branch information...
commit abb640dd7134cb347df0123c4254e06e70fcf73d 1 parent be452b4
@cdauth authored
View
54 keyring/file.js
@@ -290,6 +290,60 @@ utils.extend(_KeyringStream.prototype, {
this._subkeySignatures = { };
this._identitySignatures = { };
this._attributeSignatures = { };
+ this._ownerTrust = { };
+ },
+
+ _getOwnerTrustInfo : function(keyId, filter, fields) {
+ return Keyring._filter(new Fifo.fromArraySingle(this._ownerTrust[keyId] || [ ]), filter).map(function(it, next) {
+ next(null, Keyring._strip(it, fields));
+ });
+ },
+
+ _addOwnerTrustInfo : function(keyId, trustInfo, callback) {
+ if(!this._ownerTrust[keyId])
+ this._ownerTrust[keyId] = [ ];
+ this._ownerTrust[keyId].push(trustInfo);
+ callback(null);
+ },
+
+ _removeOwnerTrustBySignature : function(signatureId) {
+ var ret = [ ];
+ for(var i in this._ownerTrust) {
+ for(var j=0; j<this._ownerTrust[i].length; j++) {
+ if(this._ownerTrust[i][j].signaturePath.indexOf(signatureId) != -1) {
+ ret.push(utils.extend({ key: i }, this._ownerTrust[i][j]));
+ this._ownerTrust[i] = this._ownerTrust[i].slice(0, j).concat(this._ownerTrust[i].slice(j+1));
+ j--;
+ }
+ }
+ }
+ return Fifo.fromArraySingle(ret);
+ },
+
+ _removeKeyTrust : function(keyId) {
+ if(!this._ownerTrust[keyId])
+ return Fifo.fromArraySingle([ ]);
+
+ for(var i=0; i<this._ownerTrust[keyId].length; i++) {
+ if(this._ownerTrust[keyId][i].signaturePath.length == 0) {
+ this._ownerTrust[keyId] = this._ownerTrust[keyId].slice(0, i).concat(this._ownerTrust[keyId].slice(i+1));
+ i--;
+ }
+ }
+
+ var ret = [ ];
+
+ for(var i in this._ownerTrust) {
+ for(var j=0; j<this._ownerTrust[i].length; j++) {
+ if(this._ownerTrust[i][j].keyPath[0] == keyId) {
+ ret.push(utils.extend({ key: i }, this._ownerTrust[i][j]));
+ this._ownerTrust[i] = this._ownerTrust[i].slice(0, j).concat(this._ownerTrust[i].slice(j+1));
+ j--;
+ }
+ }
+ }
+
+ return Fifo.fromArraySingle(ret);
}
});
View
4 keyring/filters.js
@@ -120,6 +120,10 @@ Filter.KeyFlag = _valueFilter(function(subPackets, flag) {
return false;
});
+Filter.ArrayContains = _valueFilter(function(array, contains) {
+ return array.indexOf(contains) != -1;
+});
+
function _normaliseFilterValue(value) {
if(value instanceof Date)
View
47 keyring/index.js
@@ -396,6 +396,14 @@ Keyring.prototype = {
callback(new Error("Not implemented."));
},
+ getAllSignatures : function(keyId, filter, fields) {
+ return Fifo.fromArraySingle([
+ this.getKeySignatures(keyId, filter, fields),
+ this.getIdentityList(keyId).map(function(identityId, next) { next(null, this.getIdentitySignatures(keyId, identityId, filter, fields));}.bind(this)),
+ this.getAttributeList(keyId).map(function(attributeId, next) { next(null, this.getAttributeSignatures(keyId, attributeId, filter, fields));}.bind(this))
+ ]).recursive();
+ },
+
saveChanges : function(callback) {
callback(new Error("Not implemented."));
},
@@ -458,6 +466,42 @@ Keyring.prototype = {
searchByFingerprint : function(keyId) {
throw new Error("Implemented in keyring/combine.js");
+ },
+
+ /**
+ * Trust all signatures and trust signatures issued by the given key.
+ */
+ trustKey : function(keyId, callback) {
+ throw new Error("Implemented in keyring/trust.js");
+ },
+
+ untrustKey : function(keyId, callback) {
+ throw new Error("Implemented in keyring/trust.js");
+ },
+
+ _getOwnerTrustInfo : function(keyId, filter, fields) {
+ return __getNotImplementedFifo();
+ },
+
+ _addOwnerTrustInfo : function(keyId, trustInfo, callback) {
+ callback(new Error("Not implemented."));
+ },
+
+ /**
+ * Removes all owner trust records that contain the given signature in their signature chain.
+ * Returns those records.
+ */
+ _removeOwnerTrustBySignature : function(signatureId) {
+ return __getNotImplementedFifo();
+ },
+
+ /**
+ * Removes the initial key trust records for that key (that is, a trust record with an empty signature
+ * path). Also removes all trust records that have that key at the start of their key path and returns
+ * them.
+ */
+ _removeKeyTrust : function(keyId) {
+ return __getNotImplementedFifo();
}
};
@@ -523,4 +567,5 @@ require("./addRemove");
require("./search");
require("./importExport");
require("./combine");
-require("./signatureRelations");
+require("./signatureRelations");
+require("./trust");
View
20 keyring/signatureRelations.js
@@ -59,6 +59,13 @@ var async = require("async");
* mark it as non-sensitive.
* 8. Make sure that the security level of a key is inherited to the signatures it makes.
* a) A signature is verified. Set its security level to the lowest among its own and that of the key.
+ * 9. Calculate the trust of keys, identities and attributes. TODO: Handle signature expiration and revocation
+ * a) A certification signature is verified, revoked or removed. Recalculate the trust of the signed
+ * identity or attribute.
+ * b) A key or certification signature is verified, revoked or removed that contains a trust amount.
+ * Recalculate the owner trust of the signed key.
+ * c) The owner trust of a key changes. Apply the effects of this on all the keys, identities and
+ * attributes that have been signed by the key.
*/
utils.extend(Keyring.prototype, {
@@ -98,6 +105,10 @@ utils.extend(Keyring.prototype, {
checks.push(this.__checkSelfSignatures.bind(this, keyId));
}
+ // Check 9b
+ if([ consts.SIG.KEY, consts.SIG.CERT_0, consts.SIG.CERT_1, consts.SIG.CERT_2, consts.SIG.CERT_3 ].indexOf(signatureInfo.sigtype) != -1 && signatureInfo.trustSignature)
+ checks.push(remove ? this.__removeOwnerTrustSignature.bind(this, signatureInfo.id) : this.__addOwnerTrustSignature.bind(this, keyId, signatureInfo));
+
async.series(checks, callback);
},
@@ -125,6 +136,10 @@ utils.extend(Keyring.prototype, {
__identitySignatureVerified : function(keyId, identityId, signatureInfo, callback) {
var checks = [ this.__keySignatureVerified.bind(this, keyId, signatureInfo) ];
+ // Check 9a
+ if([ consts.SIG.CERT_0, consts.SIG.CERT_1, consts.SIG.CERT_2, consts.SIG.CERT_3 ].indexOf(signatureInfo.sigtype) != -1)
+ checks.push(this.__updateIdentityTrust.bind(this, keyId, identityId));
+
async.series(checks, callback);
},
@@ -135,6 +150,10 @@ utils.extend(Keyring.prototype, {
__attributeSignatureVerified : function(keyId, attributeId, signatureInfo, callback) {
var checks = [ this.__keySignatureVerified.bind(this, keyId, signatureInfo) ];
+ // Check 9a
+ if([ consts.SIG.CERT_0, consts.SIG.CERT_2, consts.SIG.CERT_3 ].indexOf(signatureInfo.sigtype) != -1)
+ checks.push(this.__updateAttributeTrust.bind(this, keyId, attributeId));
+
async.series(checks, callback);
},
@@ -541,5 +560,4 @@ utils.extend(Keyring.prototype, {
}.bind(this));
}.bind(this), [ "date" ]);
}
-
});
View
256 keyring/trust.js
@@ -0,0 +1,256 @@
+var Keyring = require("./index");
+var utils = require("../utils");
+var async = require("async");
+var consts = require("../consts");
+
+/*
+ * This is complicated. For each key, there may be several owner trust entries, representing a trust signature
+ * chain, with the following fields:
+ * - keyPath: The issuers of the signatures in signaturePath
+ * - signaturePath: The trust signature chain
+ * - regexp: An array of regexps that have been defined in the trust signature chain
+ * - amount: A float between 0 and 1, 1 for full trust (120), 0.5 for partial trust (60)
+ * - level: An integer, defining the remaining maximum size for the chain of trust
+ * Somewhere, there an initial trust that is set by the user.
+ * - Let’s say the user has given initial trust to a key "gnewpg". keyPath, signaturePath and regexp are
+ * empty arrays, amount is 1, level is 255 (max).
+ * - "gnewpg" tsigns "gswot" with amount=60, level=2, no regexp. This adds an owner trust entry to the "gswot"
+ * key, with the following values: {keyPath: [ "gnewpg" ], signaturePath: [ "sig1" ], regexp: [ ], amount: 0.5, level: 1}
+ * - "gnewpg" tsigns "gswot" another time, this time with amount=60, level=2, regexp=abc. This adds another
+ * owner trust entry to the "gswot" key, with the following values: {keyPath: [ "gnewpg" ], signaturePath: [ "sig2" ], regexp: [ "abc" ], amount: 0.5, level: 1}
+ * - "gswot" tsigns "cdauth" with amount=120, level=1, regexp=def. This adds two owner trust entries to the
+ * "cdauth" key, as there are two trust chains from "gnewpg" to "cdauth". The values are:
+ * {keyPath: [ "gnewpg", "gswot" ], signaturePath: [ "sig1", "sig3" ], regexp: [ "def" ], amount: 0.5, level: 0}
+ * {keyPath: [ "gnewpg", "gswot" ], signaturePath: [ "sig2", "sig3" ], regexp: [ "abc", "def" ], amount: 0.5, level: 0}
+ * Note that as the second entry has conflicting regexps, it does not actually set any trust. Also note
+ * how the trust amounts have been multiplied by each other (0.5 * 1). Also note that level is 0 because
+ * the previous entries of the signature chains both had level=1 and it is decreased by 1 in each step.
+ * - "cdauth" tsigns "tdauth" with amount=90, level=1, no regexp. This does not add any owner trust records,
+ * as "cdauth" is only owner-trusted with level-0 signature chains.
+ * - "gswot" tsigns "gnewpg" with amount=90, level=1, no regexp. This does not add any owner trust records,
+ * as "gnewpg" is already in the trust chain of all owner trust records of "gswot"
+ *
+ * Now there is the identity trust. When a key with an owner-trust record signs an identity or attribute,
+ * this is what happens:
+ * - Only owner-trust records are considered where all regexps match the signed identity (or, in case of
+ * an attribute, where there are no regexps)
+ * - For each signature issuer, the owner-trust record with the highest trust amount counts
+ * - The trust on the name of an identity and on an attribute will be the sum of the owner trust amounts of
+ * all the keys that have signed it with CERT_0, CERT_2 or CERT_3, only counting one signature for each issuer
+ * - The trust on the e-mail adrress of an identity will be the sum of the owner trust amounts of all the keys
+ * that have signed it with CERT_0, CERT_1, CERT_2 or CERT_3, only counting one signature for each issuer
+ */
+
+utils.extend(Keyring.prototype, {
+ trustKey : function(keyId, callback) {
+ this.__addOwnerTrustInfo(keyId, { keyPath: [ ], signaturePath: [ ], regexp: [ ], amount: 1, level: 255 }, callback);
+ },
+
+ untrustKey : function(keyId, callback) {
+ this._removeKeyTrust(keyId).forEachSeries(function(trustInfo, next) {
+ this.__ownerTrustChanged(trustInfo.key, next);
+ }.bind(this), callback);
+ },
+
+ /**
+ * Called when a trust signature is verified. Extends all the trust chains that exist for the key
+ * with the new signature.
+ */
+ __addOwnerTrustSignature : function(onKeyId, signatureInfo, callback) {
+ this._getOwnerTrustInfo(signatureInfo.issuer, { level: new Keyring.Filter.GreaterThan(0) }, [ "keyPath", "signaturePath", "regexp", "amount", "level" ]).forEachSeries(function(trustInfo, next) {
+ this.__addSignatureToTrustPath(onKeyId, trustInfo, signatureInfo, next);
+ }.bind(this), callback);
+ },
+
+ /**
+ * Creates trust chains for a signature. Recursively re-invokes itself for trust signatures that
+ * the signed key has issued, avoiding recursive loops and stopping when the trust level is 0.
+ */
+ __addSignatureToTrustPath : function(onKeyId, trustInfo, signatureInfo, callback) {
+ var level = signatureInfo.hashedSubPackets[consts.SIGSUBPKT.TRUST][0].value.level;
+ var regexp = signatureInfo.hashedSubPackets[consts.SIGSUBPKT.REGEXP] ? signatureInfo.hashedSubPackets[consts.SIGSUBPKT.REGEXP][0].value : null;
+
+ // Trust amount 120 (full trust): factor 1, trust amount 60 (partial trust): factor 0.5
+ var factor = signatureInfo.hashedSubPackets[consts.SIGSUBPKT.TRUST][0].value.amount / 120;
+ if(factor > 1)
+ factor = 1;
+ if(factor == 0)
+ return callback(null);
+
+ var thisTrust = {
+ keyPath: trustInfo.keyPath.concat([ signatureInfo.issuer ]),
+ signaturePath: trustInfo.signaturePath.concat([ signatureInfo.id ]),
+ regexp: trustInfo.regexp.concat(regexp ? [ regexp ] : [ ]),
+ amount: trustInfo.amount*factor,
+ level: Math.min(trustInfo.level-1, level)
+ };
+
+ this.__addOwnerTrustInfo(onKeyId, thisTrust, callback);
+ },
+
+ /**
+ * Wrapper for _addOwnerTrustInfo() that updates the trust paths after adding.
+ */
+ __addOwnerTrustInfo : function(keyId, trustInfo, callback) {
+ this._addOwnerTrustInfo(keyId, trustInfo, function(err) {
+ if(err)
+ return callback(err);
+
+ this.__ownerTrustChanged(keyId, function(err) {
+ if(err || trustInfo.level == 0)
+ return callback(err);
+
+ if(trustInfo.level == 0)
+ return callback();
+
+ var trustSigFilter = { verified: true, revoked: null, expired: new Keyring.Filter.Not(new Keyring.Filter.LessThan(new Date())), sigtype: [ consts.SIG.KEY, consts.SIG.CERT_0, consts.SIG.CERT_1, consts.SIG.CERT_2, consts.SIG.CERT_3 ] };
+ this.getKeySignatureListByIssuer(keyId, trustSigFilter).concat(this.getIdentitySignatureListByIssuer(keyId, trustSigFilter), this.getAttributeSignatureListByIssuer(keyId, trustSigFilter)).forEachSeries(function(signatureRecord, next) {
+ // Avoid recursive trust chains
+ if(signatureRecord.keyId == keyId || trustInfo.keyPath.indexOf(signatureRecord.keyId) != -1)
+ return next();
+
+ this.getSignatureById(signatureRecord.signatureId, function(err, signatureInfo) {
+ if(err)
+ return next(err);
+
+ this.__addSignatureToTrustPath(signatureRecord.keyId, trustInfo, signatureInfo, next);
+ }.bind(this), [ "hashedSubPackets" ]);
+ }.bind(this), callback);
+ }.bind(this));
+ }.bind(this));
+ },
+
+ /**
+ * Called when a trust signature is removed/revoked/expires. Removes all trust chains that involve
+ * this signature.
+ */
+ __removeOwnerTrustSignature : function(signatureId, callback) {
+ var keysChecked = { };
+ this._removeOwnerTrustBySignature(signatureId, callback).forEachSeries(function(trustInfo, next) {
+ if(keysChecked[trustInfo.key])
+ return next();
+
+ keysChecked[trustInfo.key] = true;
+ this.__ownerTrustChanged(trustInfo.key, next);
+ }.bind(this), callback);
+ },
+
+ /**
+ * Called when the owner trust of a key has changed. Recalculates the trust in all identities and
+ * attributes that this key has signed.
+ */
+ __ownerTrustChanged : function(keyId, callback) {
+ async.series([
+ function(next) {
+ var identitiesChecked = { };
+ this.getIdentitySignatureListByIssuer(keyId, { verified: true, sigtype: [ consts.SIG.CERT_0, consts.SIG.CERT_1, consts.SIG.CERT_2, consts.SIG.CERT_3 ]}).forEachSeries(function(signatureRecord, next) {
+ if(identitiesChecked[signatureRecord.identityId])
+ return next();
+
+ identitiesChecked[signatureRecord.identityId] = true;
+ this.__updateIdentityTrust(signatureRecord.keyId, signatureRecord.identityId, next);
+ }.bind(this), next);
+ }.bind(this),
+ function(next) {
+ var attributesChecked = { };
+ this.getAttributeSignatureListByIssuer(keyId, { verified: true, sigtype: [ consts.SIG.CERT_0, consts.SIG.CERT_2, consts.SIG.CERT_3 ]}).forEachSeries(function(signatureRecord, next) {
+ if(attributesChecked[signatureRecord.attributeId])
+ return next();
+
+ attributesChecked[signatureRecord.attributeId] = true;
+ this.__updateAttributeTrust(signatureRecord.keyId, signatureRecord.attributeId, next);
+ }.bind(this), next);
+ }.bind(this)
+ ], callback);
+ },
+
+ /**
+ * Calculates the owner trust of a given key. If onId is given, regexp trusts are also considered if
+ * they match the expression.
+ */
+ __getOwnerTrust : function(keyId, onId, callback) {
+ this._getOwnerTrustInfo(keyId, null, [ "keyPath", "regexp", "amount" ]).toArraySingle(function(err, trustRecords) {
+ if(err)
+ return callback(err);
+
+ var ret = 0;
+
+ outer: for(var i=0; i<trustRecords.length; i++) {
+ // Filter by regexp
+ for(var j=0; j<trustRecords[i].regexp.length; j++) {
+ if(onId == null || !onId.match(new RegExp("^"+trustRecords[i].regexp[j]+"$"))) {
+ continue outer;
+ }
+ }
+
+ if(trustRecords[i].amount > ret)
+ ret = trustRecords[i].amount;
+
+ if(ret == 1)
+ break;
+ }
+
+ callback(null, ret);
+ });
+ },
+
+ __updateIdentityTrust : function(keyId, identityId, callback) {
+ var trustName = { };
+ var trustEmail = { };
+ this.getIdentitySignatures(keyId, identityId, { verified: true, revoked: null, expired: new Keyring.Filter.Not(new Keyring.Filter.LessThan(new Date())), sigtype: [ consts.SIG.CERT_0, consts.SIG.CERT_1, consts.SIG.CERT_2, consts.SIG.CERT_3 ] }, [ "issuer", "sigtype" ]).forEachSeries(function(signatureInfo, next) {
+ this.__getOwnerTrust(signatureInfo.issuer, identityId, function(err, ownerTrust) {
+ if(err)
+ return next(err);
+
+ if(signatureInfo.sigtype != consts.SIG.CERT_1 && (!trustName[signatureInfo.issuer] || trustName[signatureInfo.issuer] < ownerTrust))
+ trustName[signatureInfo.issuer] = ownerTrust;
+
+ if(!trustEmail[signatureInfo.issuer] || trustEmail[signatureInfo.issuer] < ownerTrust)
+ trustEmail[signatureInfo.issuer] = ownerTrust;
+
+ next();
+ });
+ }.bind(this), function(err) {
+ if(err)
+ return callback(err);
+
+ var update = { nameTrust : 0, emailTrust : 0 };
+ for(var i in trustName)
+ update.nameTrust += trustName[i];
+ for(var i in trustEmail)
+ update.emailTrust += trustEmail[i];
+
+ this._updateIdentity(keyId, identityId, update, callback);
+ }.bind(this));
+ },
+
+ __updateAttributeTrust : function(keyId, attributeId, callback) {
+ var trust = { };
+ this.getAttributeSignatures(keyId, attributeId, { verified: true, revoked: null, expired: new Keyring.Filter.Not(new Keyring.Filter.LessThan(new Date())), sigtype: [ consts.SIG.CERT_0, consts.SIG.CERT_2, consts.SIG.CERT_3 ] }, [ "issuer", "sigtype" ]).forEachSeries(function(signatureInfo, next) {
+ this.__getOwnerTrust(signatureInfo.issuer, null, function(err, ownerTrust) {
+ if(err)
+ return next(err);
+
+ if(!trust[signatureInfo.issuer] || trust[signatureInfo.issuer] < ownerTrust)
+ trust[signatureInfo.issuer] = ownerTrust;
+
+ next();
+ });
+ }.bind(this), function(err) {
+ if(err)
+ return callback(err);
+
+ var update = { trust : 0 };
+ for(var i in trust)
+ update.trust += trust[i];
+
+ this._updateAttribute(keyId, attributeId, update, callback);
+ }.bind(this));
+ }
+});
+
+function __getNotImplementedFifo() {
+ var ret = new Fifo();
+ ret._end(new Error("Not implemented."));
+ return ret;
+}
View
12 packetContent.js
@@ -155,7 +155,9 @@ function getIdentityPacketInfo(body, callback)
email : email,
comment : comment,
binary : body,
- id : content
+ id : content,
+ nameTrust : 0,
+ emailTrust : 0
});
}
@@ -165,7 +167,8 @@ function getAttributePacketInfo(body, callback)
pkt : consts.PKT.ATTRIBUTE,
id : utils.hash(body, "sha1", "base64").substring(0, 27),
subPackets : [ ],
- binary : body
+ binary : body,
+ trust : 0
};
var stream = new BufferedStream(body);
@@ -228,7 +231,8 @@ function getSignaturePacketInfo(body, callback)
signature : null, // The signature as buffer object
hashalgoSecurity : null,
security : null,
- verified : false
+ verified : false,
+ trustSignature : false
};
var byte1 = body.readUInt8(0);
@@ -288,6 +292,8 @@ function getSignaturePacketInfo(body, callback)
ret.exportable = false;
if(ret.hashedSubPackets[consts.SIGSUBPKT.SIG_EXPIRE] && ret.date)
ret.expires = new Date(ret.date.getTime() + (ret.hashedSubPackets[consts.SIGSUBPKT.SIG_EXPIRE][0].value*1000));
+ if(ret.hashedSubPackets[consts.SIGSUBPKT.TRUST] && ret.hashedSubPackets[consts.SIGSUBPKT.TRUST][0].value.level > 0 && ret.hashedSubPackets[consts.SIGSUBPKT.TRUST][0].value.amount > 0)
+ ret.trustSignature = true;
callback(null, ret);
});
View
BIN  tests/gswot.pgp
Binary file not shown
View
77 tests/keyring.js
@@ -6,6 +6,8 @@ var ID_CDAUTH = "299C33F4F76ADFE9";
var ID_CDAUTH_NEW = "9C22F455A0CD27E9";
var ID_TDAUTH = "B183D07CBD57A7B3";
var ID_V3 = "FFD1B4AC7C19FD19";
+var ID_GSWOT = "6BCB9B4B8875FB7F";
+var ID_STEPHEN = "D11C2911CE519CDE";
exports.nonexistantKeyring = function(test) {
test.expect(2);
@@ -310,8 +312,81 @@ exports.cdauth.testKeyring = function(test, keyring, callback) {
test.equals(keyInfo.id, "19A29C7A53A0B130");
next();
}, [ "id" ]);
+ },
+
+ ///////////
+ // TRUST //
+ ///////////
+
+ function(next) { // Trust cdauth key
+ keyring.trustKey(ID_CDAUTH_NEW, function(err) {
+ test.ifError(err);
+ next();
+ });
+ },
+ function(next) { // Test that cdauth’s identities are trusted
+ keyring.getIdentityList(ID_CDAUTH_NEW, { nameTrust: 1, emailTrust: 1 }).toArraySingle(function(err, identities) {
+ test.ifError(err);
+ test.equals(identities.length, 4);
+ next();
+ });
+ },
+ function(next) { // Test that tdauth’s identities are not trusted
+ keyring.getIdentityList(ID_TDAUTH, { nameTrust: 0, emailTrust: 0 }).toArraySingle(function(err, identities) {
+ test.ifError(err);
+ test.equals(identities.length, 3);
+ next();
+ });
+ },
+ function(next) { // Import GSWOT key, which is tsigned by CDAUTH_NEW
+ keyring.importKeys(fs.createReadStream(__dirname+"/gswot.pgp"), function(err, imported) {
+ test.ifError(err);
+ test.equals(imported.keys.length, 3);
+ next();
+ });
+ },
+ function(next) { // Check that Stephens identities are trusted (because they are signed by GSWOT and Kenneth
+ keyring.getIdentityList(ID_STEPHEN, { nameTrust: new pgp.Keyring.Filter.GreaterThanOrEqual(1), emailTrust: new pgp.Keyring.Filter.GreaterThanOrEqual(1) }).toArraySingle(function(err, identities) {
+ test.ifError(err);
+ test.equals(identities.length, 5);
+ next();
+ });
+ },
+ function(next) { // Check that Stephens attribute is trusted (because it is signed by Kenneth, who is trusted by GSWOT
+ keyring.getAttributeList(ID_STEPHEN, { trust: new pgp.Keyring.Filter.GreaterThanOrEqual(1) }).toArraySingle(function(err, attributes) {
+ test.ifError(err);
+ test.equals(attributes.length, 1);
+ next();
+ });
+ },
+ function(next) { // Untrust CDAUTH
+ keyring.untrustKey(ID_CDAUTH_NEW, function(err) {
+ test.ifError(err);
+ next();
+ });
+ },
+ function(next) { // Check that CDAUTH’s identities are not trusted anymore
+ keyring.getIdentityList(ID_CDAUTH_NEW, { nameTrust: 0, emailTrust: 0 }).toArraySingle(function(err, identities) {
+ test.ifError(err);
+ test.equals(identities.length, 4);
+ next();
+ });
+ },
+ function(next) { // Check that Stephens identities are not trusted anymore
+ keyring.getIdentityList(ID_STEPHEN, { nameTrust: 0, emailTrust: 0 }).toArraySingle(function(err, identities) {
+ test.ifError(err);
+ test.equals(identities.length, 5);
+ next();
+ });
+ },
+ function(next) { // Check that Stephens attribute is not trusted anymore
+ keyring.getAttributeList(ID_STEPHEN, { trust: 0 }).toArraySingle(function(err, attributes) {
+ test.ifError(err);
+ test.equals(attributes.length, 1);
+ next();
+ });
}
], callback);
- return 171;
+ return 189;
};
Please sign in to comment.
Something went wrong with that request. Please try again.