Skip to content

Commit

Permalink
Add CryptoSuite_ECDSA_SHA unit tests to headless-tests
Browse files Browse the repository at this point in the history
CryptoSuite functions that can be run without the network
should be added to headless-tests for better test
coverage.

Change-Id: I2beb3c0841e9c7ff44d1f815ed4f1801fbf9a7e3
Signed-off-by: Caroline Daughtrey <[email protected]>
  • Loading branch information
cdaughtr committed Oct 17, 2016
1 parent dbcdb46 commit fb38844
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 25 deletions.
18 changes: 11 additions & 7 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,24 +140,27 @@ module.exports.CryptoSuite = class {
asymmetricDecrypt(recipientPrivateKey, cipherText) {}

/**
* Packages the private key into a key pair to use for signing
* Packages the encoded private key into a key pair to use for
* signing
*
* @param {string} privateKey the private key
* @param {string} privateKey the encoded private key. For
* example, prvKeyHex of keyPair.prvKeyObj.prvKeyHex.
* @param {string} encoding "hex" or other encoding scheme
* @returns {Object} an associative array which has the following parameters:
* prvKeyObj - RSAKey or ECDSA object of private key
* pubKeyObj - null, as only the private key is needed for signing
* priv - RSAKey or ECDSA object of private key prvKeyObj
* pub - null, as only the private key is needed for signing
*/
getKeyPairForSigning(privateKey, encoding) {}

/**
* Packages the public key into a key pair to use for encryption
*
* @param {string} publicKey the public key
* @param {string} publicKey the encoded public key. For
* example, pubKeyHex of keyPair.pubKeyObj.pubKeyHex.
* @param {string} encoding "hex" or other encoding scheme
* @returns {Object} an associative array which has the following parameters:
* prvKeyObj - null, as only the public key is needed for encryption
* pubKeyObj - RSAKey or ECDSA object of public key
* priv - null, as only the public key is needed for encryption
* pub - RSAKey or ECDSA object of public key
*/
getKeyPairForEncryption(publicKey, encoding) {}

Expand Down Expand Up @@ -378,3 +381,4 @@ module.exports.TCert = class extends module.exports.Certificate {
super(publicKey, privateKey, module.exports.PrivacyLevel.Anonymous);
}
};

15 changes: 7 additions & 8 deletions lib/impl/CryptoSuite_ECDSA_SHA.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ var EC = elliptic.ec;
var sha3_256 = require('js-sha3').sha3_256;
var sha3_384 = require('js-sha3').sha3_384;
var sjcl = require('sjcl');
var util = require('util');
var jsrsa = require('jsrsasign');
var KEYUTIL = jsrsa.KEYUTIL;
var hashPrimitives = require('../hash.js');
Expand Down Expand Up @@ -141,7 +140,6 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {
var self = this;
// debug('recipientPrivateKey=%s', util.inspect(recipientPrivateKey));//XXX
var level = recipientPrivateKey.ecparams.keylen;
var curveName = recipientPrivateKey.curveName;
// debug('=============> %d', level);
if (this._securityLevel != level) {
throw Error('Invalid key. It\'s security does not match the current security level ' + this._securityLevel + ' ' + level);
Expand Down Expand Up @@ -223,7 +221,7 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {
// enrollChainKey is a PEM. Extract the key from it.
var pem = new Buffer(chainKey, 'hex').toString();
debug('ChainKey %s', pem);
var chainKey = KEYUTIL.getHexFromPEM(pem, 'ECDSA PUBLIC KEY');
chainKey = KEYUTIL.getHexFromPEM(pem, 'ECDSA PUBLIC KEY');
// debug(chainKey);
var certBuffer = utils.toArrayBuffer(new Buffer(chainKey, 'hex'));
var asn1 = certParser.org.pkijs.fromBER(certBuffer);
Expand Down Expand Up @@ -375,8 +373,8 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {

}


hmac(key, bytes) {
var self = this;
debug('key: ', JSON.stringify(key));
debug('bytes: ', JSON.stringify(bytes));

Expand All @@ -399,7 +397,7 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {

_checkSecurityLevel(securityLevel) {
if (securityLevel != 256 && securityLevel != 384)
throw new Error('Illegal level: ' + this._securityLevel + ' - must be either 256 or 384');
throw new Error('Illegal level: ' + securityLevel + ' - must be either 256 or 384');
}

_checkHashFunction(hashAlgorithm) {
Expand Down Expand Up @@ -441,6 +439,8 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {
this._hashFunctionKeyDerivation = hashPrimitives.hash_sha2_256;
this._hashOutputSize = 32;
break;
default:
throw Error('Unsupported hash algorithm and security level pair ' + this._suite);
}

switch (this._securityLevel) {
Expand Down Expand Up @@ -522,7 +522,7 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {
var start = 0;
var end = BlockSize;
while (end <= encryptedBytes.length) {
var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
let aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
debug('start|end', start, end);
var encryptedBlock = encryptedBytes.slice(start, end);
var decryptedBlock = aesCbc.decrypt(encryptedBlock);
Expand All @@ -533,12 +533,11 @@ var CryptoSuite_ECDSA_SHA = class extends api.CryptoSuite {
start += BlockSize;
end += BlockSize;
}
;

decryptedBytes = Buffer.concat(decryptedBlocks);
}
else {
var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
let aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
decryptedBytes = aesCbc.decrypt(encryptedBytes);
}

Expand Down
10 changes: 2 additions & 8 deletions lib/impl/MemberServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,10 @@ var api = require('../api.js');
var utils = require('../utils');
var jsrsa = require('jsrsasign');
var asn1 = jsrsa.asn1;
var X509Certificate = require('../X509Certificate.js');
var path = require('path');

var CryptoSuite = utils.getCryptoSuite();

var grpc = require('grpc');
var _caProto = grpc.load(path.join(__dirname, '../../lib/protos/ca.proto')).protos;


/**
* This is the default implementation of a member services client.
*
Expand All @@ -55,7 +50,7 @@ var MemberServices = class extends api.MemberServices {
this._ecapClient = new _caProto.ECAP(ep.addr, ep.creds, options);
this._tcapClient = new _caProto.TCAP(ep.addr, ep.creds, options);
this._tlscapClient = new _caProto.TLSCAP(ep.addr, ep.creds, options);
this.cryptoPrimitives = new CryptoSuite();
this.cryptoPrimitives = utils.getCryptoSuite();
}

/**
Expand Down Expand Up @@ -281,12 +276,11 @@ function rolesToMask(roles /*string[]*/) {
}
}
}
if (mask === 0)
if (mask === 0)
mask = 1; // Client

return mask;
}

module.exports = MemberServices;


2 changes: 1 addition & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module.exports.getCryptoSuite = function() {
else
cryptoSuite = require('./impl/CryptoSuite_ECDSA_SHA.js');

return cryptoSuite;
return new cryptoSuite();
};

module.exports.newKeyValueStore = function(options) {
Expand Down
199 changes: 198 additions & 1 deletion test/unit/headless-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var hfc = require(path.join(__dirname,'../..'));
var fs = require('fs');
var execSync = require('child_process').execSync;
var utils = require('../../lib/utils.js');
var cryptoSuiteReq = require('../../lib/impl/CryptoSuite_ECDSA_SHA.js');
//var util = require('util');

// FileKeyValueStore tests /////////////
var FileKeyValueStore = require('../../lib/impl/FileKeyValueStore.js');
Expand Down Expand Up @@ -53,6 +55,10 @@ var memberCfg = {'enrollmentID': enrollmentID ,
'roles': roles,
'affiliation': affiliation};

// CryptoSuite_ECDSA_SHA tests //////////
var cryptoUtils = null;
// End: CryptoSuite_ECDSA_SHA tests /////

// Peer tests ////////
// var Peer = require('../../lib/Peer.js');
// var EventEmitter = require('events');
Expand All @@ -71,7 +77,7 @@ test('FileKeyValueStore read and write test', function(t){
}
});

var store = new FileKeyValueStore({
var store = utils.newKeyValueStore({
path: keyValStorePath
});

Expand Down Expand Up @@ -309,6 +315,197 @@ test('Member constructor set get tests', function(t) {

});

test('CryptoSuite_ECDSA_SHA constructor tests', function(t) {
cryptoUtils = utils.getCryptoSuite();

t.equal(256, cryptoUtils.getSecurityLevel(),
'CryptoSuite_ECDSA_SHA constructor tests: crytoUtils default getSecurityLevel() == 256');

var keyPair = cryptoUtils.generateKeyPair();
t.equal('secp256r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA constructor tests: cryptoUtils keyPair.pubKeyObj.curveName == secp256r1');

var cryptoReq = new cryptoSuiteReq();
t.equal(256, cryptoReq.getSecurityLevel(),
'CryptoSuite_ECDSA_SHA constructor tests: cryptoReq default getSecurityLevel() == 256');

keyPair = cryptoReq.generateKeyPair();
t.equal('secp256r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA constructor tests: cryptoReq keyPair.pubKeyObj.curveName == secp256r1');

t.end();
});

test('CryptoSuite_ECDSA_SHA function tests', function(t) {

t.equal('ECDSA', cryptoUtils.getPublicKeyAlgorithm(),
'CryptoSuite_ECDSA_SHA function tests: default getPublicKeyAlgorithm == "ECDSA"');

// Test SHA3-256 //
cryptoUtils.setHashAlgorithm('SHA3');
if (t.equal('SHA3', cryptoUtils.getHashAlgorithm(),
'CryptoSuite_ECDSA_SHA function tests: set/getHashAlgorithm("SHA3")'));
cryptoUtils.setSecurityLevel(256);
t.equal(256, cryptoUtils.getSecurityLevel(),
'CryptoSuite_ECDSA_SHA function tests: set/getSecurityLevel == 256');
var keyPair = cryptoUtils.generateKeyPair();
if (!!keyPair.pubKeyObj && !!keyPair.prvKeyObj)
t.pass('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');
else
t.fail('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');

t.equal('secp256r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair public curveName == secp256r1');
t.equal('secp256r1', keyPair.prvKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair private curveName == secp256r1');

// Test SHA3-384 //
cryptoUtils.setHashAlgorithm('SHA3');
cryptoUtils.setSecurityLevel(384);
t.equal(384, cryptoUtils.getSecurityLevel(),
'CryptoSuite_ECDSA_SHA function tests: set/getSecurityLevel == 384');
keyPair = cryptoUtils.generateKeyPair();
if (!!keyPair.pubKeyObj && !!keyPair.prvKeyObj)
t.pass('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');
else
t.fail('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');

t.equal('secp384r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair public curveName == secp384r1');
t.equal('secp384r1', keyPair.prvKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair private curveName == secp384r1');

// Test SHA2-256 //
cryptoUtils.setSecurityLevel(256);
cryptoUtils.setHashAlgorithm('SHA2');
t.equal(256, cryptoUtils.getSecurityLevel(),
'CryptoSuite_ECDSA_SHA function tests: set/getSecurityLevel == 256');
keyPair = cryptoUtils.generateKeyPair();
if (!!keyPair.pubKeyObj && !!keyPair.prvKeyObj)
t.pass('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');
else
t.fail('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');

t.equal('secp256r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair public curveName == secp256r1');
t.equal('secp256r1', keyPair.prvKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair private curveName == secp256r1');

cryptoUtils.setHashAlgorithm('sha2');//lower or upper case is allowed
if (t.equal('sha2', cryptoUtils.getHashAlgorithm(),
'CryptoSuite_ECDSA_SHA function tests: set/getHashAlgorithm("sha2")'));
keyPair = cryptoUtils.generateKeyPair();
if (!!keyPair.pubKeyObj && !!keyPair.prvKeyObj)
t.pass('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');
else
t.fail('CryptoSuite_ECDSA_SHA function tests: verify generateKeyPair pub/prvKeyObj');

t.equal('secp256r1', keyPair.pubKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair public curveName == secp256r1');
t.equal('secp256r1', keyPair.prvKeyObj.curveName,
'CryptoSuite_ECDSA_SHA function tests: cryptoReq generateKeyPair private curveName == secp256r1');

t.throws(
function() {
cryptoUtils.setHashAlgorithm('SHA2');
cryptoUtils.setSecurityLevel(384);
},
/^Error: Unsupported/,
'CryptoSuite_ECDSA_SHA function tests: SHA2 and 384 should throw '+
'Error: Unsupported hash algorithm and security level pair sha2-384'
);

t.throws(
function() {
cryptoUtils.setSecurityLevel(123);
},
/^Error: Illegal level/,
'CryptoSuite_ECDSA_SHA function tests: setSecurityLevel(123) should throw Illegal level error'
);

//SHA2 or SHA3

t.throws(
function() {
cryptoUtils.setHashAlgorithm(23456);//not a string is illegal
},
/^Error: Illegal Hash function family/,
'CryptoSuite_ECDSA_SHA function tests: setHashAlgorithm(23456) should throw Illegal Hash function family'
);

t.throws(
function() {
cryptoUtils.setHashAlgorithm('SHA5');
},
/^Error: Illegal Hash function family/,
'CryptoSuite_ECDSA_SHA function tests: setHashAlgorithm("SHA5") should throw Illegal Hash function family'
);

var nonce1 = cryptoUtils.generateNonce();
if (t.equal(24, nonce1.length,
'CryptoSuite_ECDSA_SHA function tests: generateNonce length'));

var nonce2 = cryptoUtils.generateNonce();
var nonce3 = cryptoUtils.generateNonce();
if (nonce1 != nonce2 && nonce2 != nonce3)
t.pass('CryptoSuite_ECDSA_SHA function tests: verify generateNonce buffers are different');
else
t.fail('CryptoSuite_ECDSA_SHA function tests: verify generateNonce buffers are different');

t.throws(
function() {
cryptoUtils.setHashAlgorithm('SHA3');
cryptoUtils.setSecurityLevel(256);
var keyPair = cryptoUtils.generateKeyPair();
cryptoUtils.setSecurityLevel(384);
cryptoUtils.asymmetricDecrypt(keyPair.prvKeyObj, 'fakeCipherText');
},
/^Error: Invalid key./,
'CryptoSuite_ECDSA_SHA function tests: asymmetricDecrypt should throw ' +
'"Error: Invalid key. It\'s security does not match the current security level 384 256"'
);

t.throws(
function() {
cryptoUtils.setHashAlgorithm('SHA3');
cryptoUtils.setSecurityLevel(256);
var keyPair = cryptoUtils.generateKeyPair();
cryptoUtils.asymmetricDecrypt(keyPair.prvKeyObj, 'fakeCipherText');
},
/^Error: Illegal cipherText length/,
'CryptoSuite_ECDSA_SHA function tests: asymmetricDecrypt should throw ' +
'"Error: Illegal cipherText length: 14 must be > 97"'
);

t.throws(
function() {
cryptoUtils.setHashAlgorithm('SHA3');
cryptoUtils.setSecurityLevel(256);
var keyPair = cryptoUtils.generateKeyPair();
cryptoUtils.asymmetricDecrypt(keyPair.prvKeyObj, '66616b654369706865725465787431323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930');
},
/^TypeError: Invalid hex string/,
'CryptoSuite_ECDSA_SHA function tests: asymmetricDecrypt should throw ' +
'"TypeError: Invalid hex string"'
);

cryptoUtils.setSecurityLevel(256);
cryptoUtils.setHashAlgorithm('SHA2');
keyPair = cryptoUtils.generateKeyPair();
//console.log('keyPair.prvKeyObj.prvKeyHex: '+keyPair.prvKeyObj.prvKeyHex);
var kps = cryptoUtils.getKeyPairForSigning(keyPair.prvKeyObj.prvKeyHex, 'hex');
//console.log(util.inspect(keyPair, false, null))
t.equal(keyPair.prvKeyObj.prvKeyHex.toString(16, 2), kps.priv.toString(16, 2),
'CryptoSuite_ECDSA_SHA function tests: getKeyPairForSigning prvKeyHex == priv');

var pubHex = kps.getPublic('hex');
var encryptKey = cryptoUtils.getKeyPairForEncryption(pubHex, 'hex');
//getKeyPairForEncryption (previously ecdsaKeyFromPublic)
t.ok(encryptKey.pub, 'Encrypted public key of getKeyPairForEncryption created');

t.end();
});

function getUserHome() {
return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
}
Expand Down

0 comments on commit fb38844

Please sign in to comment.