/* * Copyright 2018 Scytl Secure Electronic Voting SA * * All rights reserved * * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package */ /* jshint node:true, jasmine:true */ 'use strict'; var EntropyManager = require('../../lib/entropy/manager'); var TestEntropyCollector = require('../testentropycollector'); var PrivateKeyCollector = require('../../lib/entropy/collectors/privatekey'); var forge = require('node-forge'); describe('The entropy manager should be able to ..', function() { var entropyManager = new EntropyManager(); it('fail if it has not been initialized', function() { expect(function() { entropyManager.nextRandom(1); }).toThrow(); }); it('support private key entropy collection', function() { var privateKeyPem = '-----BEGIN RSA PRIVATE KEY-----MIIEowIBAAKCAQEAglypZU45bnf2opnRI+Y51VqouBpvDT33xIB/OtbwKzwVpi+JrjBFtfk33tE9t/dSRs79CK94HRhCWcOiLa2qWPrjeZ9SBiEyScrhIvRZVBF41zBgwQNuRvJCsKmAqlZaFNJDZxEP4repmlBn1CfVFmfrXmOKqwP5F7l9ZtucveRzsfmF1yVPFkW8TMuB3YqMiyymyqHlS8ujCsu5I8tpgPbwuxdMOY94fNhSXrYkY8IuX1g1zdq/Z1jluOaR/UqK4UpnbuJaH/F0VgDNiWh6cTD0DFGEk0b70i5wU4Q3L/S6XZQRvSuADoCbhwBKuFL5pW5n865oLVb5S3wuVdWaGwIDAQABAoIBAC/tn34Wf3kE9BGeGc1oFLVDaqqdVVz5/oEpeR2J7q0GnzMFYUpAhzC7WvY52cYsUPyll1Q9Jx0TUTmteo/uvKWQQFfz4nVMeS+2PoXabolBDzuWlsv/1eiRo0FOYHa/3siu8YcQN9X0DpAkpbfTmT1uoZOHZ3EuucMmOFu7vGn38Grw8bSxpR0uvTtnb8ygC+aB51y38RMyhzQQanrM8FMeAfDAy6IB0Yo7b0c50Cxa6Ax4nqn9LXyGakr5WeAMkgTIOA/GId9SZD4e5eRpq+628pOeR4O9datFltgl6r1+A4ii2VrJsDqeatGtODlX6KRKqwFHoGIa2TjgSZLuorECgYEAxeSZDOOgFsI5mB7RkRzZaQ9znJ15sgdyZiAFZAOUah4hSGdAXNAnZTlrdacduXEu3EfkpuPToX7xZSv5FRYwfBwMwCLeytlGLPjQzWejZGbo4+KqgzWb9fECDYVtDPlJ/+yLih9nt67BHweJKxYydl18rVigdVyy22X86NijSykCgYEAqKPUrXZAo+TJvmTw4tgsibJgvXBYBhmsej8mGNQw+Nyp2gV28sgm61ifIeXKS8teq+MFwGA6cHQedbsCqhMHokdhESZmlbWxhSFLihQcewBxwvrBwbaxI23yXRzwMewznZFL032PpcbqrmwFmcSSEZ3nmbvTH6ShqLW+pzDNp6MCgYBQLzdgxJ7qedqSa/JohTMG4e7rh9d2rpPJE7J7ewPZF8pOpx+qO+Gqn2COdJ+Ts2vUcAETKn9nEaPIZc/wnmQY9dioxbhWo0FPGaaphBPtq9Ez/XUv4zoFppk5V1X/isdUPsmvttf00oeIBiqrXbwmv+yz5JRn2Z7TTXjz9Ev+OQKBgQCUuoCMRzl1EgcXIqEL/0kwW6BUEqufHa9u1Ri9Vw6lvL8T6DPipMEmWK9nzuid9gtVns/ovTVtDgv7GuabplLaPQePf4WDzY11c0rSyS/hDyBFrK+LL5uEOqhAlJAGB2HyOj1clWVF+GvrTpuV5LZKUS/79pmZU7G7QCaX/0Ow7wKBgC/kDH7cmWQnWvvJ5izrx/7PogQVPOLELeUIGLu/hjsSdDKiFCxCUZ948+9NuG+DnpXDWzw//r8mPBRRGGsqFws5Aipp7yjQ3kRDCCzGelPCVhHyfmKqA+8ewXPulKS3/wIyHIvaXmsuAtTfurHtpRyzjKmCBK1Y6WQ3trIXvo7s-----END RSA PRIVATE KEY-----'; var entropyManager = new EntropyManager(); entropyManager.addCollector(new PrivateKeyCollector( entropyManager.collectEntropy, privateKeyPem, 100)); entropyManager.startCollectors(); entropyManager.stopCollectors(); // The first collector should be the private key collector var lastCollector = entropyManager.getCollectors().slice(-1)[0]; var privateKey = forge.pki.privateKeyFromPem(privateKeyPem); expect(lastCollector).toBeDefined(); expect(lastCollector.getPrivateKey().d).toEqual(privateKey.d); }); it('support the WebKit entropy collector', function() { var entropyManager = new EntropyManager( {windowObject: {}, cryptoApi: {getRandomValues: {}}}); entropyManager.startCollectors(); entropyManager.stopCollectors(); expect(entropyManager.getCollectors().length).toBe(1); }); it('set up the default collectors', function() { var entropyManager = new EntropyManager({windowObject: {}, cryptoApi: {}}); expect(entropyManager.getCollectors().length).toBe(4); }); it('start and stop collectors manually', function() { var entropyManager = new EntropyManager( {windowObject: {}, cryptoApi: {getRandomValues: {}}}); entropyManager.startCollectors(); expect(entropyManager.isCollecting()).toBe(true); entropyManager.stopCollectors(); expect(entropyManager.isCollecting()).toBe(false); }); it('stop entropy collection when capacity is reached', function(done) { // Enough entropy when the counter hits 1. // Do not add any collectors on start. var entropyManager = new EntropyManager({maxEntropyCounter: 1, noDefaultCollectors: true}); // Only the test collectors contributes to entropy. var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); // Start collecting entropy, and call the following function when done. entropyManager.startCollectors(function() { expect(entropyManager.getEntropyPercentage()).toBe(100); done(); }); testEntropyCollector.entropyCounter = 2; }); it('report 100% entropy collected when maximum entropy is reached', function(done) { var entropyManager = new EntropyManager( {maxEntropyCounter: 2, noDefaultCollectors: true}); var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); testEntropyCollector.entropyCounter = 2; entropyManager.startCollectors(function() { expect(entropyManager.getEntropyPercentage()).toEqual(100); done(); }); }); it('report 100% entropy collected when counter surpasses the maximum entropy', function(done) { var entropyManager = new EntropyManager( {maxEntropyCounter: 2, noDefaultCollectors: true}); var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); testEntropyCollector.entropyCounter = 4; entropyManager.startCollectors(function() { expect(entropyManager.getEntropyPercentage()).toEqual(100); done(); }); }); it('report 0% entropy collected when no entropy has been collected', function() { var entropyManager = new EntropyManager({noDefaultCollectors: true}); var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); testEntropyCollector.entropyCounter = 0; expect(entropyManager.getEntropyPercentage()).toEqual(0); }); it('report 50% entropy collected when entropy counter = max entropy / 2', function() { var entropyManager = new EntropyManager( {maxEntropyCounter: 2, noDefaultCollectors: true}); var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); testEntropyCollector.entropyCounter = 1; entropyManager.startCollectors(function() { expect(entropyManager.getEntropyPercentage()).toEqual(50); }); }); it('report 10% entropy collected when entropy counter is 10% of maximum entropy', function() { var entropyManager = new EntropyManager( {maxEntropyCounter: 10, noDefaultCollectors: true}); var testEntropyCollector = entropyManager.addCollector(TestEntropyCollector); testEntropyCollector.entropyCounter = 1; entropyManager.startCollectors(function() { expect(entropyManager.getEntropyPercentage()).toEqual(10); }); }); });