Skip to content
Snippets Groups Projects
Commit 5f8c0f1a authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #1037 Migrate back duniter-keypair

parent 2272b78d
No related branches found
No related tags found
No related merge requests found
Showing
with 501 additions and 29 deletions
...@@ -30,5 +30,7 @@ app/modules/check-config.js ...@@ -30,5 +30,7 @@ app/modules/check-config.js
app/modules/config.js app/modules/config.js
app/modules/prover/*.js app/modules/prover/*.js
app/modules/prover/lib/*.js app/modules/prover/lib/*.js
app/modules/keypair/*.js
app/modules/keypair/lib/*.js
test/*.js test/*.js
test/**/*.js test/**/*.js
\ No newline at end of file
const bs58 = require('bs58')
export const Base58encode = (bytes:any) => bs58.encode(bytes)
export const Base58decode = (data:any) => new Uint8Array(bs58.decode(data))
import {Base58decode, Base58encode} from "./base58"
import {decodeBase64, decodeUTF8, encodeBase64} from "./nacl-util"
const nacl = require('tweetnacl');
const seedrandom = require('seedrandom');
const naclBinding = require('naclb');
const crypto_sign_BYTES = 64;
class Key {
constructor(readonly pub:string, readonly sec:string) {
}
/*****************************
*
* GENERAL CRYPTO
*
*****************************/
get publicKey() {
return this.pub
}
get secretKey() {
return this.sec
}
private rawSec() {
return Base58decode(this.secretKey)
}
json() {
return {
pub: this.publicKey,
sec: this.secretKey
}
}
sign(msg:string) {
return Promise.resolve(this.signSync(msg))
}
signSync(msg:string) {
const m = decodeUTF8(msg);
const signedMsg = naclBinding.sign(m, this.rawSec());
const sig = new Uint8Array(crypto_sign_BYTES);
for (let i = 0; i < sig.length; i++) {
sig[i] = signedMsg[i];
}
return encodeBase64(sig)
};
}
export function randomKey() {
const byteseed = new Uint8Array(32)
for (let i = 0; i < 32; i++) {
byteseed[i] = Math.floor(seedrandom()() * 255) + 1
}
const keypair = nacl.sign.keyPair.fromSeed(byteseed)
return new Key(
Base58encode(keypair.publicKey),
Base58encode(keypair.secretKey)
)
}
export function KeyGen(pub:string, sec:string) {
return new Key(pub, sec)
}
/**
* Verify a signature against data & public key.
* Return true of false as callback argument.
*/
export function verify(rawMsg:string, rawSig:string, rawPub:string) {
const msg = decodeUTF8(rawMsg);
const sig = decodeBase64(rawSig);
const pub = Base58decode(rawPub);
const m = new Uint8Array(crypto_sign_BYTES + msg.length);
const sm = new Uint8Array(crypto_sign_BYTES + msg.length);
let i;
for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];
for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i];
// Call to verification lib...
return naclBinding.verify(m, sm, pub);
}
declare function escape(s:string): string;
declare function unescape(s:string): string;
export const decodeUTF8 = function(s:string) {
let i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
}
export const encodeUTF8 = function(arr:any[]) {
let i, s = [];
for (i = 0; i < arr.length; i++) s.push(String.fromCharCode(arr[i]));
return decodeURIComponent(escape(s.join('')))
}
export const encodeBase64 = function(arr:Uint8Array) {
if (typeof btoa === 'undefined' || !window) {
return (new Buffer(arr)).toString('base64');
} else {
let i, s = [], len = arr.length;
for (i = 0; i < len; i++) s.push(String.fromCharCode(arr[i]));
return btoa(s.join(''));
}
}
export const decodeBase64 = function(s:string) {
if (typeof atob === 'undefined' || !window) {
return new Uint8Array(Array.prototype.slice.call(new Buffer(s, 'base64'), 0));
} else {
let i, d = atob(s), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
}
}
\ No newline at end of file
...@@ -29,6 +29,14 @@ export interface CurrencyConfDTO { ...@@ -29,6 +29,14 @@ export interface CurrencyConfDTO {
udReevalTime0: number udReevalTime0: number
dtReeval: number dtReeval: number
} }
export interface KeypairConfDTO {
pair: Keypair
oldPair: Keypair
salt: string
passwd: string
}
export class ConfDTO implements CurrencyConfDTO { export class ConfDTO implements CurrencyConfDTO {
constructor( constructor(
......
...@@ -7,6 +7,7 @@ import {CertificationDTO} from "./dto/CertificationDTO" ...@@ -7,6 +7,7 @@ import {CertificationDTO} from "./dto/CertificationDTO"
import {TransactionDTO} from "./dto/TransactionDTO" import {TransactionDTO} from "./dto/TransactionDTO"
import {DBHead} from "./db/DBHead" import {DBHead} from "./db/DBHead"
import {LOCAL_RULES_HELPERS} from "./rules/local_rules" import {LOCAL_RULES_HELPERS} from "./rules/local_rules"
import {verify} from "./common/crypto/keyring"
const co = require('co'); const co = require('co');
const _ = require('underscore'); const _ = require('underscore');
...@@ -15,7 +16,6 @@ const common = require('duniter-common'); ...@@ -15,7 +16,6 @@ const common = require('duniter-common');
const constants = common.constants const constants = common.constants
const rawer = common.rawer const rawer = common.rawer
const unlock = common.txunlock const unlock = common.txunlock
const keyring = common.keyring
const Block = common.document.Block const Block = common.document.Block
const Membership = common.document.Membership const Membership = common.document.Membership
...@@ -1897,7 +1897,7 @@ async function getNodeIDfromPubkey(nodesCache: any, pubkey: string, dal: any) { ...@@ -1897,7 +1897,7 @@ async function getNodeIDfromPubkey(nodesCache: any, pubkey: string, dal: any) {
async function sigCheckRevoke(entry: MindexEntry, dal: any, currency: string) { async function sigCheckRevoke(entry: MindexEntry, dal: any, currency: string) {
try { try {
let pubkey = entry.pub, sig = entry.revocation; let pubkey = entry.pub, sig = entry.revocation || "";
let idty = await dal.getWrittenIdtyByPubkey(pubkey); let idty = await dal.getWrittenIdtyByPubkey(pubkey);
if (!idty) { if (!idty) {
throw Error("A pubkey who was never a member cannot be revoked"); throw Error("A pubkey who was never a member cannot be revoked");
...@@ -1913,7 +1913,7 @@ async function sigCheckRevoke(entry: MindexEntry, dal: any, currency: string) { ...@@ -1913,7 +1913,7 @@ async function sigCheckRevoke(entry: MindexEntry, dal: any, currency: string) {
sig: idty.sig, sig: idty.sig,
revocation: '' revocation: ''
}); });
let sigOK = keyring.verify(rawRevocation, sig, pubkey); let sigOK = verify(rawRevocation, sig, pubkey);
if (!sigOK) { if (!sigOK) {
throw Error("Revocation signature must match"); throw Error("Revocation signature must match");
} }
...@@ -1962,7 +1962,7 @@ async function checkCertificationIsValid (block: BlockDTO, cert: CindexEntry, fi ...@@ -1962,7 +1962,7 @@ async function checkCertificationIsValid (block: BlockDTO, cert: CindexEntry, fi
buid: buid, buid: buid,
sig: '' sig: ''
})); }));
const verified = keyring.verify(raw, cert.sig, cert.issuer); const verified = verify(raw, cert.sig, cert.issuer);
if (!verified) { if (!verified) {
throw constants.ERRORS.WRONG_SIGNATURE_FOR_CERT throw constants.ERRORS.WRONG_SIGNATURE_FOR_CERT
} }
......
...@@ -5,13 +5,13 @@ import {DBBlock} from "../db/DBBlock" ...@@ -5,13 +5,13 @@ import {DBBlock} from "../db/DBBlock"
import {TransactionDTO} from "../dto/TransactionDTO" import {TransactionDTO} from "../dto/TransactionDTO"
import * as local_rules from "./local_rules" import * as local_rules from "./local_rules"
import {BlockDTO} from "../dto/BlockDTO" import {BlockDTO} from "../dto/BlockDTO"
import {verify} from "../common/crypto/keyring"
const _ = require('underscore'); const _ = require('underscore');
const common = require('duniter-common'); const common = require('duniter-common');
const indexer = require('../indexer').Indexer const indexer = require('../indexer').Indexer
const constants = common.constants const constants = common.constants
const keyring = common.keyring
const rawer = common.rawer const rawer = common.rawer
const Identity = common.document.Identity const Identity = common.document.Identity
const Transaction = common.document.Transaction const Transaction = common.document.Transaction
...@@ -276,7 +276,7 @@ async function checkCertificationIsValid (block:{ number:number, currency:string ...@@ -276,7 +276,7 @@ async function checkCertificationIsValid (block:{ number:number, currency:string
buid: buid, buid: buid,
sig: '' sig: ''
})); }));
const verified = keyring.verify(raw, cert.sig, cert.from); const verified = verify(raw, cert.sig, cert.from);
if (!verified) { if (!verified) {
throw constants.ERRORS.WRONG_SIGNATURE_FOR_CERT throw constants.ERRORS.WRONG_SIGNATURE_FOR_CERT
} }
......
...@@ -4,13 +4,13 @@ import {ConfDTO} from "../dto/ConfDTO" ...@@ -4,13 +4,13 @@ import {ConfDTO} from "../dto/ConfDTO"
import {CindexEntry, IndexEntry, Indexer, MindexEntry, SindexEntry} from "../indexer" import {CindexEntry, IndexEntry, Indexer, MindexEntry, SindexEntry} from "../indexer"
import {BaseDTO, TransactionDTO} from "../dto/TransactionDTO" import {BaseDTO, TransactionDTO} from "../dto/TransactionDTO"
import {DBBlock} from "../db/DBBlock" import {DBBlock} from "../db/DBBlock"
import {verify} from "../common/crypto/keyring"
const _ = require('underscore'); const _ = require('underscore');
const common = require('duniter-common'); const common = require('duniter-common');
const constants = common.constants const constants = common.constants
const hashf = common.hashf const hashf = common.hashf
const keyring = common.keyring
const Block = common.document.Block const Block = common.document.Block
const Identity = common.document.Identity const Identity = common.document.Identity
const Membership = common.document.Membership const Membership = common.document.Membership
...@@ -73,7 +73,7 @@ export const LOCAL_RULES_FUNCTIONS = { ...@@ -73,7 +73,7 @@ export const LOCAL_RULES_FUNCTIONS = {
}, },
checkBlockSignature: async (block:BlockDTO) => { checkBlockSignature: async (block:BlockDTO) => {
if (!keyring.verify(block.getSignedPart(), block.signature, block.issuer)) if (!verify(block.getSignedPart(), block.signature, block.issuer))
throw Error('Block\'s signature must match'); throw Error('Block\'s signature must match');
return true; return true;
}, },
...@@ -94,7 +94,7 @@ export const LOCAL_RULES_FUNCTIONS = { ...@@ -94,7 +94,7 @@ export const LOCAL_RULES_FUNCTIONS = {
while (!wrongSig && i < block.identities.length) { while (!wrongSig && i < block.identities.length) {
const idty = Identity.fromInline(block.identities[i]); const idty = Identity.fromInline(block.identities[i]);
idty.currency = block.currency; idty.currency = block.currency;
wrongSig = !keyring.verify(idty.rawWithoutSig(), idty.sig, idty.pubkey); wrongSig = !verify(idty.rawWithoutSig(), idty.sig, idty.pubkey);
if (wrongSig) { if (wrongSig) {
throw Error('Identity\'s signature must match'); throw Error('Identity\'s signature must match');
} }
...@@ -382,7 +382,7 @@ export const LOCAL_RULES_FUNCTIONS = { ...@@ -382,7 +382,7 @@ export const LOCAL_RULES_FUNCTIONS = {
} }
function checkSingleMembershipSignature(ms:any) { function checkSingleMembershipSignature(ms:any) {
return keyring.verify(ms.getRaw(), ms.signature, ms.issuer); return verify(ms.getRaw(), ms.signature, ms.issuer);
} }
function getSigResult(tx:any) { function getSigResult(tx:any) {
...@@ -401,7 +401,7 @@ function getSigResult(tx:any) { ...@@ -401,7 +401,7 @@ function getSigResult(tx:any) {
while (signaturesMatching && i < tx.signatures.length) { while (signaturesMatching && i < tx.signatures.length) {
const sig = tx.signatures[i]; const sig = tx.signatures[i];
const pub = tx.issuers[i]; const pub = tx.issuers[i];
signaturesMatching = keyring.verify(raw, sig, pub); signaturesMatching = verify(raw, sig, pub);
sigResult.sigs[pub] = { sigResult.sigs[pub] = {
matching: signaturesMatching, matching: signaturesMatching,
index: i index: i
......
import {randomKey} from "../../lib/common/crypto/keyring"
import {ConfDTO, KeypairConfDTO} from "../../lib/dto/ConfDTO"
import {Scrypt} from "./lib/scrypt"
const inquirer = require('inquirer');
const fs = require('fs');
const yaml = require('js-yaml');
export const KeypairDependency = {
duniter: {
methods: {
scrypt: Scrypt
},
cliOptions: [
{ value: '--salt <salt>', desc: 'Salt to generate the keypair' },
{ value: '--passwd <password>', desc: 'Password to generate the keypair' },
{ value: '--keyN <N>', desc: 'Scrypt `N` parameter. Defaults to 4096.', parser: parseInt },
{ value: '--keyr <r>', desc: 'Scrypt `N` parameter. Defaults to 16.', parser: parseInt },
{ value: '--keyp <p>', desc: 'Scrypt `N` parameter. Defaults to 1.', parser: parseInt },
{ value: '--keyprompt', desc: 'Force to use the keypair given by user prompt.' },
{ value: '--keyfile <filepath>', desc: 'Force to use the keypair of the given YAML file. File must contain `pub:` and `sec:` fields.' }
],
wizard: {
'key': promptKey
},
onReset: {
config: (conf:ConfDTO, program:any, logger:any, confDAL:any) => confDAL.coreFS.remove('keyring.yml')
},
config: {
/*****
* Tries to load a specific parameter `conf.pair`
*/
onLoading: async (conf:KeypairConfDTO, program:any, logger:any, confDAL:any) => {
if ((program.keyN || program.keyr || program.keyp) && !(program.salt && program.passwd)) {
throw Error('Missing --salt and --passwd options along with --keyN|keyr|keyp option');
}
// If we have salt and password, convert it to keypair
if (program.salt || program.passwd) {
const salt = program.salt || '';
const key = program.passwd || '';
conf.pair = await Scrypt(salt, key);
}
// If no keypair has been loaded, try the default .yml file
if (!conf.pair || !conf.pair.pub || !conf.pair.sec) {
const ymlContent = await confDAL.coreFS.read('keyring.yml')
conf.pair = yaml.safeLoad(ymlContent);
}
// If no keypair has been loaded or derived from salt/key, generate a random one
if (!conf.pair || !conf.pair.pub || !conf.pair.sec) {
conf.pair = randomKey().json()
}
// With the --keyprompt option, temporarily use a keypair given from CLI prompt (it won't be stored)
if (program.keyprompt) {
// Backup of the current pair
conf.oldPair = {
pub: conf.pair.pub,
sec: conf.pair.sec
};
// Ask the for the session key
await promptKey(conf, program);
}
// With the --keyfile option, temporarily use a keypair given from file system (content won't be stored)
if (program.keyfile) {
// Backup of the current pair
conf.oldPair = {
pub: conf.pair.pub,
sec: conf.pair.sec
};
// Load file content
const doc = yaml.safeLoad(fs.readFileSync(program.keyfile, 'utf8'));
if (!doc || !doc.pub || !doc.sec) {
throw 'Could not load full keyring from file';
}
conf.pair = {
pub: doc.pub,
sec: doc.sec
}
}
},
beforeSave: async (conf:KeypairConfDTO, program:any, logger:any, confDAL:any) => {
if (program.keyprompt || program.keyfile) {
// Don't store the given key, but only the default/saved one
conf.pair = {
pub: conf.oldPair.pub,
sec: conf.oldPair.sec
};
}
delete conf.oldPair;
// We save the key in a separate file
const keyring = 'pub: "' + conf.pair.pub + '"\n' +
'sec: "' + conf.pair.sec + '"'
await confDAL.coreFS.write('keyring.yml', keyring)
// We never want to store salt, password or keypair in the conf.json file
delete conf.salt;
delete conf.passwd;
delete conf.pair;
}
}
}
};
async function promptKey (conf:KeypairConfDTO, program:any) {
const changeKeypair = !conf.pair || !conf.pair.pub || !conf.pair.sec;
const answersWantToChange = await inquirer.prompt([{
type: "confirm",
name: "change",
message: "Modify you keypair?",
default: changeKeypair
}]);
if (answersWantToChange.change) {
const obfuscatedSalt = (program.salt || "").replace(/./g, '*');
const answersSalt = await inquirer.prompt([{
type: "password",
name: "salt",
message: "Key's salt",
default: obfuscatedSalt || undefined
}]);
const obfuscatedPasswd = (program.passwd || "").replace(/./g, '*');
const answersPasswd = await inquirer.prompt([{
type: "password",
name: "passwd",
message: "Key\'s password",
default: obfuscatedPasswd || undefined
}]);
const keepOldSalt = obfuscatedSalt.length > 0 && obfuscatedSalt == answersSalt.salt;
const keepOldPasswd = obfuscatedPasswd.length > 0 && obfuscatedPasswd == answersPasswd.passwd;
const salt = keepOldSalt ? program.salt : answersSalt.salt;
const passwd = keepOldPasswd ? program.passwd : answersPasswd.passwd;
conf.pair = await Scrypt(salt, passwd)
}
}
"use strict";
import {Base58encode} from "../../../lib/common/crypto/base58"
import {decodeBase64} from "../../../lib/common/crypto/nacl-util"
const nacl = require('tweetnacl');
const scrypt = require('scryptb');
const SEED_LENGTH = 32; // Length of the key
/**
* Generates a new keypair object from salt + password strings.
* @param salt
* @param key
* @param N Scrypt parameter N. Defaults to 4096.
* @param r Scrypt parameter r. Defaults to 16.
* @param p Scrypt parameter p. Defaults to 1.
* @return keyPair An object containing the public and private keys, base58 encoded.
*/
export const Scrypt = async (salt:string, key:string, N = 4096, r = 16, p = 1) => {
const keyBytes = await getScryptKey(key, salt, N, r, p)
const pair = nacl.sign.keyPair.fromSeed(keyBytes);
return {
pub: Base58encode(new Buffer(pair.publicKey, 'hex')),
sec: Base58encode(new Buffer(pair.secretKey, 'hex'))
};
}
const getScryptKey = async (key:string, salt:string, N:number, r:number, p:number) => {
const res:any = await new Promise((resolve, reject) => {
scrypt.hash(key, { N, r, p }, SEED_LENGTH, salt, (err:any, res:Buffer) => {
if (err) return reject(err)
resolve(res)
})
})
return decodeBase64(res.toString("base64"))
}
...@@ -7,13 +7,13 @@ import {LOCAL_RULES_HELPERS} from "../../../lib/rules/local_rules" ...@@ -7,13 +7,13 @@ import {LOCAL_RULES_HELPERS} from "../../../lib/rules/local_rules"
import {Indexer} from "../../../lib/indexer" import {Indexer} from "../../../lib/indexer"
import {FileDAL} from "../../../lib/dal/fileDAL" import {FileDAL} from "../../../lib/dal/fileDAL"
import {DBBlock} from "../../../lib/db/DBBlock" import {DBBlock} from "../../../lib/db/DBBlock"
import {verify} from "../../../lib/common/crypto/keyring"
const _ = require('underscore'); const _ = require('underscore');
const moment = require('moment'); const moment = require('moment');
const inquirer = require('inquirer'); const inquirer = require('inquirer');
const common = require('duniter-common'); const common = require('duniter-common');
const keyring = common.keyring;
const hashf = common.hashf; const hashf = common.hashf;
const rawer = common.rawer; const rawer = common.rawer;
const Block = common.document.Block; const Block = common.document.Block;
...@@ -352,7 +352,7 @@ export class BlockGenerator { ...@@ -352,7 +352,7 @@ export class BlockGenerator {
const idty = Identity.fromJSON(identity); const idty = Identity.fromJSON(identity);
idty.currency = this.conf.currency; idty.currency = this.conf.currency;
const createIdentity = idty.rawWithoutSig(); const createIdentity = idty.rawWithoutSig();
const verified = keyring.verify(createIdentity, idty.sig, idty.pubkey); const verified = verify(createIdentity, idty.sig, idty.pubkey);
if (!verified) { if (!verified) {
throw constants.ERRORS.IDENTITY_WRONGLY_SIGNED; throw constants.ERRORS.IDENTITY_WRONGLY_SIGNED;
} }
...@@ -693,7 +693,7 @@ class NextBlockGenerator implements BlockGeneratorInterface { ...@@ -693,7 +693,7 @@ class NextBlockGenerator implements BlockGeneratorInterface {
cert.idty_sig = targetIdty.sig; cert.idty_sig = targetIdty.sig;
cert.buid = current ? [cert.block_number, targetBlock.hash].join('-') : common.constants.SPECIAL_BLOCK; cert.buid = current ? [cert.block_number, targetBlock.hash].join('-') : common.constants.SPECIAL_BLOCK;
const rawCert = Certification.fromJSON(cert).getRaw(); const rawCert = Certification.fromJSON(cert).getRaw();
if (keyring.verify(rawCert, certSig, cert.from)) { if (verify(rawCert, certSig, cert.from)) {
cert.sig = certSig; cert.sig = certSig;
let exists = false; let exists = false;
if (current) { if (current) {
......
...@@ -3,11 +3,11 @@ import {hashf} from "../../../lib/common" ...@@ -3,11 +3,11 @@ import {hashf} from "../../../lib/common"
import {DBBlock} from "../../../lib/db/DBBlock" import {DBBlock} from "../../../lib/db/DBBlock"
import {ConfDTO} from "../../../lib/dto/ConfDTO" import {ConfDTO} from "../../../lib/dto/ConfDTO"
import {Constants} from "./constants" import {Constants} from "./constants"
import {KeyGen} from "../../../lib/common/crypto/keyring"
const moment = require('moment'); const moment = require('moment');
const dos2unix = require('duniter-common').dos2unix; const dos2unix = require('duniter-common').dos2unix;
const querablep = require('querablep'); const querablep = require('querablep');
const keyring = require('duniter-common').keyring;
const rawer = require('duniter-common').rawer; const rawer = require('duniter-common').rawer;
const PAUSES_PER_TURN = 5; const PAUSES_PER_TURN = 5;
...@@ -94,7 +94,7 @@ function beginNewProofOfWork(stuff:any) { ...@@ -94,7 +94,7 @@ function beginNewProofOfWork(stuff:any) {
} }
else { else {
lastSecret = pair.sec; lastSecret = pair.sec;
sigFunc = keyring.Key(pair.pub, pair.sec).signSync; sigFunc = (msg:string) => KeyGen(pair.pub, pair.sec).signSync(msg)
} }
signatureFunc = sigFunc; signatureFunc = sigFunc;
let pow = "", sig = "", raw = ""; let pow = "", sig = "", raw = "";
......
...@@ -8,9 +8,9 @@ import {RevocationDTO} from "../lib/dto/RevocationDTO" ...@@ -8,9 +8,9 @@ import {RevocationDTO} from "../lib/dto/RevocationDTO"
import {BasicIdentity, IdentityDTO} from "../lib/dto/IdentityDTO" import {BasicIdentity, IdentityDTO} from "../lib/dto/IdentityDTO"
import {CertificationDTO} from "../lib/dto/CertificationDTO" import {CertificationDTO} from "../lib/dto/CertificationDTO"
import {DBCert} from "../lib/dal/sqliteDAL/CertDAL" import {DBCert} from "../lib/dal/sqliteDAL/CertDAL"
import {verify} from "../lib/common/crypto/keyring"
"use strict"; "use strict";
const keyring = require('duniter-common').keyring;
const constants = require('../lib/constants'); const constants = require('../lib/constants');
const BY_ABSORPTION = true; const BY_ABSORPTION = true;
...@@ -80,7 +80,7 @@ export class IdentityService { ...@@ -80,7 +80,7 @@ export class IdentityService {
return GlobalFifoPromise.pushFIFO(async () => { return GlobalFifoPromise.pushFIFO(async () => {
this.logger.info('⬇ IDTY %s %s', idty.pubkey, idty.uid); this.logger.info('⬇ IDTY %s %s', idty.pubkey, idty.uid);
// Check signature's validity // Check signature's validity
let verified = keyring.verify(createIdentity, idty.sig, idty.pubkey); let verified = verify(createIdentity, idty.sig, idty.pubkey);
if (!verified) { if (!verified) {
throw constants.ERRORS.SIGNATURE_DOES_NOT_MATCH; throw constants.ERRORS.SIGNATURE_DOES_NOT_MATCH;
} }
...@@ -210,7 +210,7 @@ export class IdentityService { ...@@ -210,7 +210,7 @@ export class IdentityService {
return GlobalFifoPromise.pushFIFO(async () => { return GlobalFifoPromise.pushFIFO(async () => {
try { try {
this.logger.info('⬇ REVOCATION %s %s', revoc.pubkey, revoc.idty_uid); this.logger.info('⬇ REVOCATION %s %s', revoc.pubkey, revoc.idty_uid);
let verified = keyring.verify(raw, revoc.revocation, revoc.pubkey); let verified = verify(raw, revoc.revocation, revoc.pubkey);
if (!verified) { if (!verified) {
throw 'Wrong signature for revocation'; throw 'Wrong signature for revocation';
} }
......
...@@ -5,12 +5,12 @@ import {DBPeer} from "../lib/dal/sqliteDAL/PeerDAL" ...@@ -5,12 +5,12 @@ import {DBPeer} from "../lib/dal/sqliteDAL/PeerDAL"
import {DBBlock} from "../lib/db/DBBlock" import {DBBlock} from "../lib/db/DBBlock"
import {Multicaster} from "../lib/streams/multicaster" import {Multicaster} from "../lib/streams/multicaster"
import {PeerDTO} from "../lib/dto/PeerDTO" import {PeerDTO} from "../lib/dto/PeerDTO"
import {verify} from "../lib/common/crypto/keyring"
const util = require('util'); const util = require('util');
const _ = require('underscore'); const _ = require('underscore');
const events = require('events'); const events = require('events');
const rp = require('request-promise'); const rp = require('request-promise');
const keyring = require('duniter-common').keyring;
const logger = require('../lib/logger').NewLogger('peering'); const logger = require('../lib/logger').NewLogger('peering');
const dos2unix = require('duniter-common').dos2unix; const dos2unix = require('duniter-common').dos2unix;
const hashf = require('duniter-common').hashf; const hashf = require('duniter-common').hashf;
...@@ -64,7 +64,7 @@ export class PeeringService { ...@@ -64,7 +64,7 @@ export class PeeringService {
const raw = rawer.getPeerWithoutSignature(p); const raw = rawer.getPeerWithoutSignature(p);
const sig = p.signature; const sig = p.signature;
const pub = p.pubkey; const pub = p.pubkey;
const signaturesMatching = keyring.verify(raw, sig, pub); const signaturesMatching = verify(raw, sig, pub);
return !!signaturesMatching; return !!signaturesMatching;
}; };
......
...@@ -2,6 +2,8 @@ import {ExecuteCommand} from "./app/cli" ...@@ -2,6 +2,8 @@ import {ExecuteCommand} from "./app/cli"
import * as stream from "stream" import * as stream from "stream"
import {Server} from "./server" import {Server} from "./server"
import {ConfDTO} from "./app/lib/dto/ConfDTO" import {ConfDTO} from "./app/lib/dto/ConfDTO"
import {ProverDependency} from "./app/modules/prover/index"
import {KeypairDependency} from "./app/modules/keypair/index"
const path = require('path'); const path = require('path');
const _ = require('underscore'); const _ = require('underscore');
...@@ -20,7 +22,6 @@ const daemonDependency = require('./app/modules/daemon'); ...@@ -20,7 +22,6 @@ const daemonDependency = require('./app/modules/daemon');
const pSignalDependency = require('./app/modules/peersignal'); const pSignalDependency = require('./app/modules/peersignal');
const routerDependency = require('./app/modules/router'); const routerDependency = require('./app/modules/router');
const pluginDependency = require('./app/modules/plugin'); const pluginDependency = require('./app/modules/plugin');
const proverDependency = require('./app/modules/prover').ProverDependency;
class Stacks { class Stacks {
...@@ -98,7 +99,8 @@ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([ ...@@ -98,7 +99,8 @@ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([
{ name: 'duniter-psignal', required: pSignalDependency }, { name: 'duniter-psignal', required: pSignalDependency },
{ name: 'duniter-router', required: routerDependency }, { name: 'duniter-router', required: routerDependency },
{ name: 'duniter-plugin', required: pluginDependency }, { name: 'duniter-plugin', required: pluginDependency },
{ name: 'duniter-prover', required: proverDependency } { name: 'duniter-prover', required: ProverDependency },
{ name: 'duniter-keypair', required: KeypairDependency }
]); ]);
const PRODUCTION_DEPENDENCIES = DEFAULT_DEPENDENCIES.concat([ const PRODUCTION_DEPENDENCIES = DEFAULT_DEPENDENCIES.concat([
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
"archiver": "1.3.0", "archiver": "1.3.0",
"async": "2.2.0", "async": "2.2.0",
"bindings": "1.2.1", "bindings": "1.2.1",
"bs58": "^4.0.1",
"co": "4.6.0", "co": "4.6.0",
"colors": "1.1.2", "colors": "1.1.2",
"commander": "2.9.0", "commander": "2.9.0",
...@@ -59,17 +60,20 @@ ...@@ -59,17 +60,20 @@
"inquirer": "3.0.6", "inquirer": "3.0.6",
"merkle": "0.5.1", "merkle": "0.5.1",
"moment": "2.18.1", "moment": "2.18.1",
"naclb": "1.3.9",
"node-pre-gyp": "0.6.34", "node-pre-gyp": "0.6.34",
"optimist": "0.6.1", "optimist": "0.6.1",
"q-io": "1.13.2", "q-io": "1.13.2",
"querablep": "^0.1.0", "querablep": "^0.1.0",
"request": "2.81.0", "request": "2.81.0",
"request-promise": "4.2.0", "request-promise": "4.2.0",
"seedrandom": "^2.4.3",
"sha1": "1.1.1", "sha1": "1.1.1",
"spawn-sync": "^1.0.15", "spawn-sync": "^1.0.15",
"sqlite3": "3.1.4", "sqlite3": "3.1.4",
"superagent": "3.5.2", "superagent": "3.5.2",
"tail": "^1.2.1", "tail": "^1.2.1",
"tweetnacl": "0.14.3",
"underscore": "1.8.3", "underscore": "1.8.3",
"unzip": "0.1.11", "unzip": "0.1.11",
"unzip2": "0.2.5", "unzip2": "0.2.5",
...@@ -83,7 +87,6 @@ ...@@ -83,7 +87,6 @@
"coveralls": "2.11.4", "coveralls": "2.11.4",
"duniter-bma": "1.3.x", "duniter-bma": "1.3.x",
"duniter-crawler": "1.3.x", "duniter-crawler": "1.3.x",
"duniter-keypair": "1.3.X",
"duniter-ui": "1.3.x", "duniter-ui": "1.3.x",
"eslint": "3.13.1", "eslint": "3.13.1",
"eslint-plugin-mocha": "4.8.0", "eslint-plugin-mocha": "4.8.0",
...@@ -100,7 +103,6 @@ ...@@ -100,7 +103,6 @@
"peerDependencies": { "peerDependencies": {
"duniter-bma": "1.3.x", "duniter-bma": "1.3.x",
"duniter-crawler": "1.3.x", "duniter-crawler": "1.3.x",
"duniter-keypair": "1.3.X",
"duniter-ui": "1.3.x" "duniter-ui": "1.3.x"
}, },
"bin": { "bin": {
......
...@@ -8,6 +8,7 @@ import {FileDAL} from "./app/lib/dal/fileDAL" ...@@ -8,6 +8,7 @@ import {FileDAL} from "./app/lib/dal/fileDAL"
import {DuniterBlockchain} from "./app/lib/blockchain/DuniterBlockchain" import {DuniterBlockchain} from "./app/lib/blockchain/DuniterBlockchain"
import {SQLBlockchain} from "./app/lib/blockchain/SqlBlockchain" import {SQLBlockchain} from "./app/lib/blockchain/SqlBlockchain"
import * as stream from "stream" import * as stream from "stream"
import {KeyGen, randomKey} from "./app/lib/common/crypto/keyring"
interface HookableServer { interface HookableServer {
getMainEndpoint: (...args:any[]) => Promise<any> getMainEndpoint: (...args:any[]) => Promise<any>
...@@ -28,7 +29,6 @@ const daemonize = require("daemonize2") ...@@ -28,7 +29,6 @@ const daemonize = require("daemonize2")
const parsers = require('duniter-common').parsers; const parsers = require('duniter-common').parsers;
const constants = require('./app/lib/constants'); const constants = require('./app/lib/constants');
const jsonpckg = require('./package.json'); const jsonpckg = require('./package.json');
const keyring = require('duniter-common').keyring;
const directory = require('./app/lib/system/directory'); const directory = require('./app/lib/system/directory');
const rawer = require('duniter-common').rawer; const rawer = require('duniter-common').rawer;
const logger = require('./app/lib/logger').NewLogger('server'); const logger = require('./app/lib/logger').NewLogger('server');
...@@ -150,11 +150,11 @@ export class Server extends stream.Duplex implements HookableServer { ...@@ -150,11 +150,11 @@ export class Server extends stream.Duplex implements HookableServer {
// Default keypair // Default keypair
if (!this.conf.pair || !this.conf.pair.pub || !this.conf.pair.sec) { if (!this.conf.pair || !this.conf.pair.pub || !this.conf.pair.sec) {
// Create a random key // Create a random key
this.conf.pair = keyring.randomKey().json() this.conf.pair = randomKey().json()
} }
// Extract key pair // Extract key pair
this.keyPair = keyring.Key(this.conf.pair.pub, this.conf.pair.sec); this.keyPair = KeyGen(this.conf.pair.pub, this.conf.pair.sec);
this.sign = this.keyPair.sign; this.sign = (msg:string) => this.keyPair.sign(msg)
// Blockchain object // Blockchain object
this.blockchain = new DuniterBlockchain(new SQLBlockchain(this.dal), this.dal); this.blockchain = new DuniterBlockchain(new SQLBlockchain(this.dal), this.dal);
// Update services // Update services
......
"use strict";
const should = require('should');
const co = require('co');
const nacl = require('tweetnacl');
const base58 = require('../../../app/lib/common/crypto/base58')
const naclUtil = require('../../../app/lib/common/crypto/nacl-util')
const keyring = require('../../../app/lib/common/crypto/keyring')
const Base58decode = base58.Base58decode
const Base58encode = base58.Base58encode
const enc = naclUtil.encodeBase64
const dec = naclUtil.decodeBase64
let pub, sec, rawPub, rawSec;
describe('ed25519 tests:', function(){
before(() => co(function*() {
// Generate the keypair
const keyPair = keyring.KeyGen('HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP');
pub = Base58decode(keyPair.publicKey);
sec = Base58decode(keyPair.secretKey);
rawPub = Base58encode(pub);
rawSec = Base58encode(sec);
}));
//it('good signature from existing secret key should be verified', function(done){
// const keys = nacl.sign.scryptKeyPair.fromSecretKey(dec("TM0Imyj/ltqdtsNG7BFOD1uKMZ81q6Yk2oz27U+4pvs9QBfD6EOJWpK3CqdNG368nJgszy7ElozAzVXxKvRmDA=="));
// const msg = "cg==";
// const goodSig = dec("52Hh9omo9rxklulAE7gvVeYvAq0GgXYoZE2NB/gzehpCYIT04bMcGIs5bhYLaH93oib34jsVMWs9Udadr1B+AQ==");
// const sig = crypto.signSync(msg, keys.secretKey);
// sig.should.equal(enc(goodSig));
// crypto.verify(msg, sig, enc(keys.publicKey)).should.be.true;
// done();
//});
it('good signature from generated key should be verified', function(done){
const msg = "Some message to be signed";
const sig = keyring.KeyGen(rawPub, rawSec).signSync(msg);
const verified = keyring.verify(msg, sig, rawPub);
verified.should.equal(true);
done();
});
it('wrong signature from generated key should NOT be verified', function(done){
const msg = "Some message to be signed";
const cor = dec(enc(msg) + 'delta');
const sig = keyring.KeyGen(rawPub, rawSec).signSync(msg);
const verified = keyring.verify(cor, sig, rawPub);
verified.should.equal(false);
done();
});
it('good signature on a Peer document with just BMA should be verified', function(done){
const msg = "Version: 10\n" +
"Type: Peer\n" +
"Currency: g1\n" +
"PublicKey: 3AF7bhGQRt6ymcBZgZTBMoDsEtSwruSarjNG8kDnaueX\n" +
"Block: 33291-0000088375C232A4DDAE171BB3D3C51347CB6DC8B7AA8BE4CD4DAEEADF26FEB8\n" +
"Endpoints:\n" +
"BASIC_MERKLED_API g1.duniter.org 10901\n"
const verified = keyring.verify(msg, "u8t1IoWrB/C7T+2rS0rKYJfjPG4FN/HkKGFiUO5tILIzjFDvxxQiVC+0o/Vaz805SMmqJvXqornI71U7//+wCg==", "3AF7bhGQRt6ymcBZgZTBMoDsEtSwruSarjNG8kDnaueX");
verified.should.equal(true);
done();
});
it('good signature on a Peer document with just BMA + BMAS should be verified', function(done){
const msg = "Version: 10\n" +
"Type: Peer\n" +
"Currency: g1\n" +
"PublicKey: Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm\n" +
"Block: 33291-0000088375C232A4DDAE171BB3D3C51347CB6DC8B7AA8BE4CD4DAEEADF26FEB8\n" +
"Endpoints:\n" +
"BASIC_MERKLED_API g1.duniter.tednet.fr 37.187.0.204 8999\n" +
"BMAS g1.duniter.tednet.fr 9000\n"
const verified = keyring.verify(msg, "ImvQDdpGv2M6CxSnBuseM/azJhBUGzWVgQhIvb5L2oGLm2GyLk/Sbi5wkb4IjbjbQfdRPdlcx5zxaHhvZCiWAA==", "Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm");
verified.should.equal(true);
done();
});
});
"use strict";
const co = require('co')
const should = require('should');
const keyring = require('../../../app/lib/common/crypto/keyring')
const naclUtil = require('../../../app/lib/common/crypto/nacl-util')
const enc = naclUtil.encodeBase64
const dec = naclUtil.decodeBase64
let key;
describe('Random keypair', function(){
before(() => co(function*() {
// Generate the keypair
key = keyring.randomKey()
}));
it('good signature from generated key should be verified', function(done){
const msg = "Some message to be signed";
const sig = keyring.KeyGen(key.publicKey, key.secretKey).signSync(msg);
const verified = keyring.verify(msg, sig, key.publicKey);
verified.should.equal(true);
done();
});
it('wrong signature from generated key should NOT be verified', function(done){
const msg = "Some message to be signed";
const cor = dec(enc(msg) + 'delta');
const sig = keyring.KeyGen(key.publicKey, key.secretKey).signSync(msg);
const verified = keyring.verify(cor, sig, key.publicKey);
verified.should.equal(false);
done();
});
});
"use strict";
const should = require('should');
const co = require('co');
const scrypt = require('../../../../app/modules/keypair/lib/scrypt').Scrypt
describe('Scrypt salt // key', () => {
it('abc // abc', () => co(function*() {
const pair = yield scrypt('abc', 'abc');
pair.should.have.property('pub').equal('HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd');
pair.should.have.property('sec').equal('51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP');
}));
it('abc // def', () => co(function*() {
const pair = yield scrypt('abc', 'def');
pair.should.have.property('pub').equal('G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU');
pair.should.have.property('sec').equal('58LDg8QLmF5pv6Dn9h7X4yFKfMTdP8fdAiWVcyDoTRJu454fwRihCLULH4MW37zncsg4ruoTGJPZneWk22QmG1w4');
}));
it('azerty // def', () => co(function*() {
const pair = yield scrypt('azerty', 'def');
pair.should.have.property('pub').equal('3dbw4NYVEm5mwTH6bFrqBhan1k39qNHubkQWdrw2C5AD');
pair.should.have.property('sec').equal('4kemdi17CPkkBPnjXiPFf6oBhdGiiqhCL3R4Tuafe9THK8mzBs1evHw5r9u3f8xts2zn6VCBJYVrRMzdaEaWn5Ch');
}));
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment