Mise à jour de GitLab prévue ce samedi 8 mai 2021 à partir de 9h00 CET | GitLab upgrade planned this Saturday May 4th of 2021 from 9:00 AM CET

Commit 3302197e authored by Cédric Moreau's avatar Cédric Moreau

TDD: Block:Global: certifications must be verified (signature)

parent 60141655
......@@ -15,8 +15,16 @@ var TEST_PARAMS = {
var enc = nacl.util.encodeBase64,
dec = nacl.util.decodeBase64;
var that = module.exports;
module.exports = {
/*****************************
*
* GENERAL CRYPTO
*
*****************************/
sign: function (msg, sec, done) {
var m = nacl.util.decodeUTF8(msg);
var signedMsg = naclBinding.sign(m, sec);
......@@ -81,6 +89,18 @@ module.exports = {
getScryptKey(key, salt, function(keyBytes) {
done(null, nacl.sign.keyPair.fromSeed(keyBytes));
});
},
/*****************************
*
* FUNCTIONAL CRYPTO
*
*****************************/
isValidCertification: function (selfCert, selfSig, otherPubkey, otherSig, otherTime, done) {
var raw = selfCert + selfSig + '\n' + 'META:TS:' + otherTime + '\n';
var verified = this.verify(raw, otherSig, otherPubkey);
done(verified ? null : 'Wrong signature for certification');
}
};
......
var async = require('async');
var crypto = require('./crypto');
var common = require('./common');
var mongoose = require('mongoose');
var Identity = mongoose.model('Identity', require('../models/identity'));
var Membership = mongoose.model('Membership', require('../models/membership'));
var Certification = mongoose.model('Certification', require('../models/certification'));
module.exports = function (dao) {
return new GlobalValidator(dao);
};
function GlobalValidator (dao) {
this.checkSignatures = function (block, done) {
async.series([
async.apply(checkCertificationsAreValid, block)
], done);
};
this.validate = function (block, done) {
async.series([
async.apply(checkIdentityUnicity, block),
async.apply(checkPubkeyUnicity, block),
async.apply(checkLeaversAreMembers, block),
async.apply(checkExcludedAreMembers, block),
async.apply(checkCertificationsDelayIsRespected, block),
async.apply(checkNewcomersHaveEnoughCertifications, block),
async.apply(checkNewcomersAreNotOudistanced, block)
], done);
};
function checkCertificationsAreValid (block, done) {
async.forEach(block.certifications, function(inlineCert, callback){
var cert = Certification.fromInline(inlineCert);
async.waterfall([
function (next){
dao.getIdentityByPubkey(cert.to, next);
},
function (idty, next){
var selfCert = idty.selfCert();
crypto.isValidCertification(selfCert, idty.sig, cert.from, cert.sig, cert.when.timestamp(), next);
},
], callback);
}, done);
}
function checkIdentityUnicity (block, done) {
done();
}
function checkPubkeyUnicity (block, done) {
done();
}
function checkLeaversAreMembers (block, done) {
done();
}
function checkExcludedAreMembers (block, done) {
done();
}
function checkCertificationsDelayIsRespected (block, done) {
done();
}
function checkNewcomersHaveEnoughCertifications (block, done) {
done();
}
function checkNewcomersAreNotOudistanced (block, done) {
done();
}
}
\ No newline at end of file
......@@ -28,6 +28,10 @@ CertificationSchema.virtual('from').get(function () {
return this.pubkey;
});
CertificationSchema.virtual('when').get(function () {
return this.time;
});
CertificationSchema.methods = {
exists: function (done) {
......
......@@ -2,6 +2,7 @@ var async = require('async');
var _ = require('underscore');
var merkle = require('merkle');
var sha1 = require('sha1');
var crypto = require('../lib/crypto');
var base64 = require('../lib/base64');
var dos2unix = require('../lib/dos2unix');
var parsers = require('../lib/streams/parsers/doc');
......@@ -1148,7 +1149,7 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) {
function (idty, next){
logger.info('Signature for '+ certified);
var selfCert = idty.selfCert();
IdentityService.isValidCertification(selfCert, idty.sig, certifier, sig, when, next);
crypto.isValidCertification(selfCert, idty.sig, certifier, sig, when, next);
},
], done);
}
......
......@@ -27,12 +27,6 @@ function IdentityService (conn, conf) {
], done);
};
this.isValidCertification = function (selfCert, selfSig, otherPubkey, otherSig, otherTime, done) {
var raw = selfCert + selfSig + '\n' + 'META:TS:' + otherTime + '\n';
var verified = crypto.verify(raw, otherSig, otherPubkey);
done(verified ? null : 'Wrong signature for certification from \'' + otherPubkey + '\'');
}
/**
* Tries to persist a public key given in ASCII-armored format.
* Returns the database stored public key.
......@@ -52,7 +46,7 @@ function IdentityService (conn, conf) {
if (cert.from == idty.pubkey)
cb('Rejected certification: certifying its own self-certification has no meaning');
else
that.isValidCertification(selfCert, idty.sig, cert.from, cert.sig, cert.time.timestamp(), cb);
crypto.isValidCertification(selfCert, idty.sig, cert.from, cert.sig, cert.time.timestamp(), cb);
}, next);
},
function (next){
......
......@@ -478,4 +478,33 @@ module.exports = {
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:1411844660:tY5J+g3sM421sx0WNUuESUL8Zz2BU0UbtXT+nRsTlYThaDubMg/GmhsxWa0ccRJcZvftEwpENtVjyd6hyPSQCw==\n" +
"Transactions:\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
WRONGLY_SIGNED_CERTIFICATION:
"Version: 1\n" +
"Type: Block\n" +
"Currency: beta_brousouf\n" +
"Nonce: 11\n" +
"Number: 0\n" +
"Date: 1411776000\n" +
"ConfirmedDate: 1411776000\n" +
"Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" +
"MembersCount: 3\n" +
"Identities:\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:Die9lYNW1u/w50AfuaXwb4MJc3aKA3WfJwiy+31TqHIGC+VNnRKjMmrwMptN+a+dL6INjLrhMrPqoK60IkTlDQ==:1411837451:CAT\n" +
"G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:NJE8nYU4Im+KQDRdoAn5gcfic+Gjjzp0Pp0iji/Fzh9JIThoQeUDDew4Q5vJBEg/Aw7gPnIg+11TbLkIGa/ODQ==:1411837452:TAC\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:1V/QnQcnJtQSSvhOFBhl7kGXBea8gKEQ6iqPNCVb41yI9gN79XGtUeHhjlumhQkPeizlzpkcNBkL8bhokiNcBQ==:1411837457:SNOW\n" +
"Joiners:\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:iSQvl1VVc6+b1AUaBJ/VTTurGGHgaIcjASBhIlzI7M/7KVQV2Wi3oGUZUzLWqCAtGUsPcsj1HCV2/sRyxHmqAw==:1411837455:1411837451:CAT\n" +
"G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:25xK7+ph7IYeN9Hu8PvuIBjYdVURYtvKayPHZg7zrrYTs6ii2fMtk5J65a3bT/NKr2Qsd7I5TCL29QyiAXa7BA==:1411837456:1411837452:TAC\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:1411837462:1411837457:SNOW\n" +
"Leavers:\n" +
"Excluded:\n" +
"Certifications:\n" +
"G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:1411844654:vTvFYvjTYUT30t/9h7uNE/2LFJiYuA4YleIetFkb62XxDoxGizKC9VvVs7WRNArcfHvJ+RLyOoawQzpmw2DyCw==\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:1411844658:2KmmmIL8eK/TACjOqTqO5ZG/tgMYWWV8zRICWFQJuqWyYVg/y5wzXyHrgfpdMYhwYMRBhwbMk1sPNLo/kzp0AA==\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:1411844653:DU4JlHxJtIb2Z7Ag4Jy+z0qjNNo5jzN5EvTUWOTRRzeb6LbOClw2X+pmb0mV/wpVKd/lJrUHAWeKMDHG4MukCA==\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:1411844660:tY5J+g3sM421sx0WNUuESUL8Zz2BU0UbtXT+nRsTlYThaDubMg/GmhsxWa0ccRJcZvftEwpENtVjyd6hyPSQCw==\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:1411844659:kr2JA6wCGfbNKGpyM86BscsFk22aA9oiAon8mWRPl4G8UpJKZs3tjuPRAw5+04KLCRWl/TT1TumDCkeEjev7DA==\n" +
"Transactions:\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
};
var async = require('async');
var should = require('should');
var assert = require('assert');
var mongoose = require('mongoose');
var parsers = require('../../../app/lib/streams/parsers/doc');
var blocks = require('../../data/blocks');
var validator = require('../../../app/lib/globalValidator');
var parser = parsers.parseBlock();
var Block = mongoose.model('Block', require('../../../app/models/block'));
var Identity = mongoose.model('Identity', require('../../../app/models/identity'));
describe("Block local coherence", function(){
it('a valid block should not have certification error', validate(blocks.VALID_ROOT, function (err, done) {
should.not.exist(err);
done();
}));
it('a block with certification of unknown pubkey should fail', validate(blocks.WRONGLY_SIGNED_CERTIFICATION, function (err, done) {
should.exist(err);
err.should.equal('Wrong signature for certification');
done();
}));
});
function validate (raw, callback) {
var block;
return function (done) {
async.waterfall([
function (next){
parser.asyncWrite(raw, next);
},
function (obj, next){
block = new Block(obj);
validator(new BlockCheckerDao(block)).validate(block, next);
},
function (obj, next){
validator(new BlockCheckerDao(block)).checkSignatures(block, next);
},
], function (err) {
callback(err, done);
});
};
}
/**
* Mock dao for testing
*/
function BlockCheckerDao (block) {
this.getIdentityByPubkey = function (pubkey, done) {
var i = 0;
var found = false;
while (!found && i < block.identities.length) {
if (block.identities[i].match(new RegExp('^' + pubkey)))
found = Identity.fromInline(block.identities[i]);
i++;
}
done(null, found);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment