Added logging, changed some directory structure

This commit is contained in:
2018-01-13 21:33:40 -05:00
parent f079a5f067
commit 8e72ffb917
73656 changed files with 35284 additions and 53718 deletions

View File

@@ -0,0 +1,2 @@
instrumentation:
root: ..

View File

@@ -0,0 +1,34 @@
Running all the tests (headless-browser and node.js)
====================================================
npm install
npm test
Running the browser-based tests
===============================
npm install
node server.js
Then go to http://localhost:8083/.
Testing Require.js optimised version of the JavaScript
------------------------------------------------------
npm install -g requirejs
r.js -o build.js
You will now have a single optimised JS file at ui/test.min.js, containing the
tests and all the forge dependencies.
Now edit ui/index.html and change `data-main="test"` to `data-main="test.min"`,
then reload http://localhost:8083/.
Building a minimized single file for all forge modules
------------------------------------------------------
npm install -g requirejs
r.js -o minify.js
You will now have forge.min.js, in the 'js' directory, which will contain all
forge modules.

View File

@@ -0,0 +1,8 @@
({
paths: {
forge: '../js'
},
name: 'ui/test.js',
out: 'ui/test.min.js',
preserveLicenseComments: false
})

View File

@@ -0,0 +1,8 @@
({
paths: {
forge: '../js'
},
name: '../js/forge',
out: '../js/forge.min.js',
preserveLicenseComments: false
})

View File

@@ -0,0 +1,24 @@
{
"name": "forge-nodejs-example",
"version": "0.1.0",
"private": true,
"main": "server.js",
"dependencies": {
"express": "~3.1.0",
"mocha": "~1.21.5",
"chai": "~1.10.0",
"grunt": "~0.4.5",
"grunt-mocha": "~0.4.12"
},
"scripts": {
"run": "node server",
"test": "mocha -t 30000 -R spec test/*.js",
"coverage": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -u exports -t 30000 -R spec test/*.js",
"coverage-lcov": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- -u exports -t 30000 -R spec test/*.js",
"coverage-report": "./node_modules/.bin/istanbul report"
},
"devDependencies": {
"istanbul": "^0.3.14",
"mocha-lcov-reporter": "0.0.2"
}
}

View File

@@ -0,0 +1,46 @@
var PATH = require('path');
var express = require('express');
var PORT = 8083;
exports.main = function(callback) {
try {
var app = express();
mountStaticDir(app, /^\/forge\/(.*)$/, PATH.join(__dirname, '../js'));
mountStaticDir(app, /^\/test\/(.*)$/, PATH.join(__dirname, 'test'));
mountStaticDir(app, /^\/mocha\/(.*)$/, PATH.join(__dirname, 'node_modules/mocha'));
mountStaticDir(app, /^\/chai\/(.*)$/, PATH.join(__dirname, 'node_modules/chai'));
app.get(/^\//, express.static(PATH.join(__dirname, 'ui')));
var server = app.listen(PORT);
console.log('open http://localhost:' + PORT + '/');
return callback(null, {
server: server,
port: PORT
});
} catch(err) {
return callback(err);
}
};
function mountStaticDir(app, route, path) {
app.get(route, function(req, res, next) {
var originalUrl = req.url;
req.url = req.params[0];
express.static(path)(req, res, function() {
req.url = originalUrl;
return next.apply(null, arguments);
});
});
}
if(require.main === module) {
exports.main(function(err) {
if(err) {
console.error(err.stack);
process.exit(1);
}
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,262 @@
(function() {
function Tests(ASSERT, ASN1, UTIL) {
describe('asn1', function() {
// TODO: add more ASN.1 coverage
it('should convert an OID to DER', function() {
ASSERT.equal(ASN1.oidToDer('1.2.840.113549').toHex(), '2a864886f70d');
});
it('should convert an OID from DER', function() {
var der = UTIL.hexToBytes('2a864886f70d');
ASSERT.equal(ASN1.derToOid(der), '1.2.840.113549');
});
it('should convert INTEGER 0 to DER', function() {
ASSERT.equal(ASN1.integerToDer(0).toHex(), '00');
});
it('should convert INTEGER 1 to DER', function() {
ASSERT.equal(ASN1.integerToDer(1).toHex(), '01');
});
it('should convert INTEGER 127 to DER', function() {
ASSERT.equal(ASN1.integerToDer(127).toHex(), '7f');
});
it('should convert INTEGER 128 to DER', function() {
ASSERT.equal(ASN1.integerToDer(128).toHex(), '0080');
});
it('should convert INTEGER 256 to DER', function() {
ASSERT.equal(ASN1.integerToDer(256).toHex(), '0100');
});
it('should convert INTEGER -128 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-128).toHex(), '80');
});
it('should convert INTEGER -129 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-129).toHex(), 'ff7f');
});
it('should convert INTEGER 32768 to DER', function() {
ASSERT.equal(ASN1.integerToDer(32768).toHex(), '008000');
});
it('should convert INTEGER -32768 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-32768).toHex(), '8000');
});
it('should convert INTEGER -32769 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-32769).toHex(), 'ff7fff');
});
it('should convert INTEGER 8388608 to DER', function() {
ASSERT.equal(ASN1.integerToDer(8388608).toHex(), '00800000');
});
it('should convert INTEGER -8388608 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-8388608).toHex(), '800000');
});
it('should convert INTEGER -8388609 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-8388609).toHex(), 'ff7fffff');
});
it('should convert INTEGER 2147483647 to DER', function() {
ASSERT.equal(ASN1.integerToDer(2147483647).toHex(), '7fffffff');
});
it('should convert INTEGER -2147483648 to DER', function() {
ASSERT.equal(ASN1.integerToDer(-2147483648).toHex(), '80000000');
});
it('should convert INTEGER 0 from DER', function() {
var der = UTIL.hexToBytes('00');
ASSERT.equal(ASN1.derToInteger(der), 0);
});
it('should convert INTEGER 1 from DER', function() {
var der = UTIL.hexToBytes('01');
ASSERT.equal(ASN1.derToInteger(der), 1);
});
it('should convert INTEGER 127 from DER', function() {
var der = UTIL.hexToBytes('7f');
ASSERT.equal(ASN1.derToInteger(der), 127);
});
it('should convert INTEGER 128 from DER', function() {
var der = UTIL.hexToBytes('0080');
ASSERT.equal(ASN1.derToInteger(der), 128);
});
it('should convert INTEGER 256 from DER', function() {
var der = UTIL.hexToBytes('0100');
ASSERT.equal(ASN1.derToInteger(der), 256);
});
it('should convert INTEGER -128 from DER', function() {
var der = UTIL.hexToBytes('80');
ASSERT.equal(ASN1.derToInteger(der), -128);
});
it('should convert INTEGER -129 from DER', function() {
var der = UTIL.hexToBytes('ff7f');
ASSERT.equal(ASN1.derToInteger(der), -129);
});
it('should convert INTEGER 32768 from DER', function() {
var der = UTIL.hexToBytes('008000');
ASSERT.equal(ASN1.derToInteger(der), 32768);
});
it('should convert INTEGER -32768 from DER', function() {
var der = UTIL.hexToBytes('8000');
ASSERT.equal(ASN1.derToInteger(der), -32768);
});
it('should convert INTEGER -32769 from DER', function() {
var der = UTIL.hexToBytes('ff7fff');
ASSERT.equal(ASN1.derToInteger(der), -32769);
});
it('should convert INTEGER 8388608 from DER', function() {
var der = UTIL.hexToBytes('00800000');
ASSERT.equal(ASN1.derToInteger(der), 8388608);
});
it('should convert INTEGER -8388608 from DER', function() {
var der = UTIL.hexToBytes('800000');
ASSERT.equal(ASN1.derToInteger(der), -8388608);
});
it('should convert INTEGER -8388609 from DER', function() {
var der = UTIL.hexToBytes('ff7fffff');
ASSERT.equal(ASN1.derToInteger(der), -8388609);
});
it('should convert INTEGER 2147483647 from DER', function() {
var der = UTIL.hexToBytes('7fffffff');
ASSERT.equal(ASN1.derToInteger(der), 2147483647);
});
it('should convert INTEGER -2147483648 from DER', function() {
var der = UTIL.hexToBytes('80000000');
ASSERT.equal(ASN1.derToInteger(der), -2147483648);
});
(function() {
var tests = [{
in: '20110223123400',
out: 1298464440000
}, {
in: '20110223123400.1',
out: 1298464440100
}, {
in: '20110223123400.123',
out: 1298464440123
}];
for(var i = 0; i < tests.length; ++i) {
var test = tests[i];
it('should convert local generalized time "' + test.in + '" to a Date', function() {
var d = ASN1.generalizedTimeToDate(test.in);
var localOffset = d.getTimezoneOffset() * 60000;
ASSERT.equal(d.getTime(), test.out + localOffset);
});
}
})();
(function() {
var tests = [{
in: '20110223123400Z', // Wed Feb 23 12:34:00.000 UTC 2011
out: 1298464440000
}, {
in: '20110223123400.1Z', // Wed Feb 23 12:34:00.100 UTC 2011
out: 1298464440100
}, {
in: '20110223123400.123Z', // Wed Feb 23 12:34:00.123 UTC 2011
out: 1298464440123
}, {
in: '20110223123400+0200', // Wed Feb 23 10:34:00.000 UTC 2011
out: 1298457240000
}, {
in: '20110223123400.1+0200', // Wed Feb 23 10:34:00.100 UTC 2011
out: 1298457240100
}, {
in: '20110223123400.123+0200', // Wed Feb 23 10:34:00.123 UTC 2011
out: 1298457240123
}, {
in: '20110223123400-0200', // Wed Feb 23 14:34:00.000 UTC 2011
out: 1298471640000
}, {
in: '20110223123400.1-0200', // Wed Feb 23 14:34:00.100 UTC 2011
out: 1298471640100
}, {
in: '20110223123400.123-0200', // Wed Feb 23 14:34:00.123 UTC 2011
out: 1298471640123
}];
for(var i = 0; i < tests.length; ++i) {
var test = tests[i];
it('should convert utc generalized time "' + test.in + '" to a Date', function() {
var d = ASN1.generalizedTimeToDate(test.in);
ASSERT.equal(d.getTime(), test.out);
});
}
})();
(function() {
var tests = [{
in: '1102231234Z', // Wed Feb 23 12:34:00 UTC 2011
out: 1298464440000
}, {
in: '1102231234+0200', // Wed Feb 23 10:34:00 UTC 2011
out: 1298457240000
}, {
in: '1102231234-0200', // Wed Feb 23 14:34:00 UTC 2011
out: 1298471640000
}, {
in: '110223123456Z', // Wed Feb 23 12:34:56 UTC 2011
out: 1298464496000
}, {
in: '110223123456+0200', // Wed Feb 23 10:34:56 UTC 2011
out: 1298457296000
}, {
in: '110223123456-0200', // Wed Feb 23 14:34:56 UTC 2011
out: 1298471696000
}];
for(var i = 0; i < tests.length; ++i) {
var test = tests[i];
it('should convert utc time "' + test.in + '" to a Date', function() {
var d = ASN1.utcTimeToDate(test.in);
ASSERT.equal(d.getTime(), test.out);
});
}
})();
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/asn1',
'forge/util'
], function(ASN1, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
ASN1(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/asn1')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,41 @@
var server = require('../server');
var grunt = require('grunt');
describe('browser', function() {
it('should run tests', function(done) {
this.timeout(60 * 1000 * 5);
return server.main(function(err, info) {
if(err) {
return done(err);
}
grunt.initConfig({
mocha: {
all: {
options: {
reporter: 'List',
urls: ['http://localhost:' + info.port + '/index.html']
}
}
}
});
grunt.loadNpmTasks('grunt-mocha');
grunt.registerInitTask('default', function() {
grunt.task.run(['mocha']);
});
grunt.tasks(['default'], {
//debug: true
}, function() {
if(err) {
return done(err);
}
// finish immediately
done(null);
return info.server.close();
});
});
});
});

View File

@@ -0,0 +1,148 @@
(function() {
function Tests(ASSERT, PKI) {
var _pem = {
privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICXQIBAAKBgQDL0EugUiNGMWscLAVM0VoMdhDZEJOqdsUMpx9U0YZI7szokJqQ\r\n' +
'NIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMGTkP3VF29vXBo+dLq5e+8VyAy\r\n' +
'Q3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGtvnM+z0MYDdKo80efzwIDAQAB\r\n' +
'AoGAIzkGONi5G+JifmXlLJdplom486p3upf4Ce2/7mqfaG9MnkyPSairKD/JXvfh\r\n' +
'NNWkkN8DKKDKBcVVElPgORYT0qwrWc7ueLBMUCbRXb1ZyfEulimG0R3kjUh7NYau\r\n' +
'DaIkVgfykXGSQMZx8FoaT6L080zd+0emKDDYRrb+/kgJNJECQQDoUZoiC2K/DWNY\r\n' +
'h3/ppZ0ane2y4SBmJUHJVMPQ2CEgxsrJTxet668ckNCKaOP/3VFPoWC41f17DvKq\r\n' +
'noYINNntAkEA4JbZBZBVUrQFhHlrpXT4jzqtO2RlKZzEq8qmFZfEErxOT1WMyyCi\r\n' +
'lAQ5gUKardo1Kf0omC8Xq/uO9ZYdED55KwJBALs6cJ65UFaq4oLJiQPzLd7yokuE\r\n' +
'dcj8g71PLBTW6jPxIiMFNA89nz3FU9wIVp+xbMNhSoMMKqIPVPC+m0Rn260CQQDA\r\n' +
'I83fWK/mZWUjBM33a68KumRiH238v8XyQxj7+C8i6D8G2GXvkigFAehAkb7LZZd+\r\n' +
'KLuGFyPlWv3fVWHf99KpAkBQFKk3MRMl6IGJZUEFQe4l5whm8LkGU4acSqv9B3xt\r\n' +
'qROkCrsFrMPqjuuzEmyHoQZ64r2PLJg7FOuyhBnQUOt4\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKey: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL0EugUiNGMWscLAVM0VoMdhDZ\r\n' +
'EJOqdsUMpx9U0YZI7szokJqQNIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMG\r\n' +
'TkP3VF29vXBo+dLq5e+8VyAyQ3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGt\r\n' +
'vnM+z0MYDdKo80efzwIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n'
};
describe('csr', function() {
it('should generate a certification request', function() {
var keys = {
privateKey: PKI.privateKeyFromPem(_pem.privateKey),
publicKey: PKI.publicKeyFromPem(_pem.publicKey)
};
var csr = PKI.createCertificationRequest();
csr.publicKey = keys.publicKey;
csr.setSubject([{
name: 'commonName',
value: 'example.org'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}]);
// add optional attributes
csr.setAttributes([{
name: 'challengePassword',
value: 'password'
}, {
name: 'unstructuredName',
value: 'My company'
}, {
name: 'extensionRequest',
extensions: [{
name: 'subjectAltName',
altNames: [{
// type 2 is DNS
type: 2,
value: 'test.domain.com'
}, {
type: 2,
value: 'other.domain.com'
}, {
type: 2,
value: 'www.domain.net'
}]
}]
}]);
// sign certification request
csr.sign(keys.privateKey);
var pem = PKI.certificationRequestToPem(csr);
csr = PKI.certificationRequestFromPem(pem);
ASSERT.ok(csr.getAttribute({name: 'extensionRequest'}));
ASSERT.equal(csr.getAttribute({name: 'extensionRequest'}).extensions[0].name, 'subjectAltName');
ASSERT.deepEqual(csr.getAttribute({name: 'extensionRequest'}).extensions[0].altNames, [{
// type 2 is DNS
type: 2,
value: 'test.domain.com'
}, {
type: 2,
value: 'other.domain.com'
}, {
type: 2,
value: 'www.domain.net'
}]);
ASSERT.ok(csr.verify());
});
it('should load an OpenSSL-generated certification request', function() {
var pem = '-----BEGIN CERTIFICATE REQUEST-----\r\n' +
'MIICdTCCAV0CAQAwMDEVMBMGA1UEAwwMTXlDb21tb25OYW1lMRcwFQYDVQQKDA5N\r\n' +
'eU9yZ2FuaXphdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRU\r\n' +
'zrAMbiiSjAYYl3PWsOrNwY0VtemgRZc0t7+3FlWp1e8uIA3KxZFZY875wo0QOvD+\r\n' +
'AdNv5+YnokgzOi83F3T4yewBSR0TiO3Pa4tL4C7CzWnhYliC/owk5bHCV0HLkYUW\r\n' +
'F6z7Lx3HyhoxlKmrHySSPPZRLKp7KcwxbjFc2EfhQV21I73Z1mCG6MEp7cN2qBbQ\r\n' +
'PyOMNjAUibOWs4JJEdUjWhm86EZm9+qfgpL5tlpZCe+kXySrKTp56mMsfSOQvlol\r\n' +
'pRO8pP9AUjaEqRikCZ745I/9W7dHNPUoyxkWV5jRDwcT7s652+L6oxtoqVOXpg28\r\n' +
'uAL0kUZQMa8wkYUKZiMCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQCXQH+ut6tr\r\n' +
'Z/FdIDOljrc7uh8XpFRKS3GqC/PJsEwrV7d3CX5HuWPTuPc9FU5FQ88w6evXEA0o\r\n' +
'ijxHuydeXmdjpy433vXWo1TaRSXh1WaBMG5pW/SlGZK9/Hr1P0v7KN/KCY5nXxoQ\r\n' +
'k3Ndg9HzGrYnRoJVXzvdQeBGwCoJFk4FH+Rxa/F03VTUU5nwx66TsL9JUp9pnbI7\r\n' +
'MR6DIA97LnTmut8Xp0Uurw+zsS5rif9iv0BKHd7eGpNNGl0RXu8E5dbT0zD90TSa\r\n' +
'P5WjxjvY+Udg8XZU+UwT3kcyTEFpiQdkzTIKXg0dFurfUE9XG/9aic9oMZ/IBZz9\r\n' +
'a535a7e9RkbJ\r\n' +
'-----END CERTIFICATE REQUEST-----\r\n';
var csr = PKI.certificationRequestFromPem(pem);
ASSERT.equal(csr.subject.getField('CN').value, 'MyCommonName');
ASSERT.equal(csr.subject.getField('O').value, 'MyOrganization');
ASSERT.equal(csr.signatureOid, PKI.oids.sha1WithRSAEncryption);
ASSERT.equal(csr.publicKey.e.toString(16), '10001');
ASSERT.equal(csr.publicKey.n.toString(16).toUpperCase(), 'A454CEB00C6E28928C06189773D6B0EACDC18D15B5E9A0459734B7BFB71655A9D5EF2E200DCAC5915963CEF9C28D103AF0FE01D36FE7E627A248333A2F371774F8C9EC01491D1388EDCF6B8B4BE02EC2CD69E1625882FE8C24E5B1C25741CB91851617ACFB2F1DC7CA1A3194A9AB1F24923CF6512CAA7B29CC316E315CD847E1415DB523BDD9D66086E8C129EDC376A816D03F238C36301489B396B3824911D5235A19BCE84666F7EA9F8292F9B65A5909EFA45F24AB293A79EA632C7D2390BE5A25A513BCA4FF40523684A918A4099EF8E48FFD5BB74734F528CB19165798D10F0713EECEB9DBE2FAA31B68A95397A60DBCB802F491465031AF3091850A6623');
ASSERT.ok(csr.verify());
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pki'
], function(PKI) {
Tests(
// Global provided by test harness
ASSERT,
PKI()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pki')());
}
})();

View File

@@ -0,0 +1,155 @@
(function() {
function Tests(ASSERT, CIPHER, DES, UTIL) {
describe('des', function() {
// OpenSSL equivalent:
// openssl enc -des-ecb -K a1c06b381adf3651 -nosalt
it('should des-ecb encrypt: foobar', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf3651'));
var cipher = CIPHER.createCipher('DES-ECB', key);
cipher.start();
cipher.update(UTIL.createBuffer('foobar'));
cipher.finish();
ASSERT.equal(cipher.output.toHex(), 'b705ffcf3dff06b3');
});
// OpenSSL equivalent:
// openssl enc -d -des-ecb -K a1c06b381adf3651 -nosalt
it('should des-ecb decrypt: b705ffcf3dff06b3', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf3651'));
var decipher = CIPHER.createDecipher('DES-ECB', key);
decipher.start();
decipher.update(UTIL.createBuffer(UTIL.hexToBytes('b705ffcf3dff06b3')));
decipher.finish();
ASSERT.equal(decipher.output.getBytes(), 'foobar');
});
// OpenSSL equivalent:
// openssl enc -des -K a1c06b381adf3651 -iv 818bcf76efc59662 -nosalt
it('should des-cbc encrypt: foobar', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf3651'));
var iv = new UTIL.createBuffer(
UTIL.hexToBytes('818bcf76efc59662'));
var cipher = CIPHER.createCipher('DES-CBC', key);
cipher.start({iv: iv});
cipher.update(UTIL.createBuffer('foobar'));
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '3261e5839a990454');
});
// OpenSSL equivalent:
// openssl enc -d -des -K a1c06b381adf3651 -iv 818bcf76efc59662 -nosalt
it('should des-cbc decrypt: 3261e5839a990454', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf3651'));
var iv = new UTIL.createBuffer(
UTIL.hexToBytes('818bcf76efc59662'));
var decipher = CIPHER.createDecipher('DES-CBC', key);
decipher.start({iv: iv});
decipher.update(UTIL.createBuffer(UTIL.hexToBytes('3261e5839a990454')));
decipher.finish();
ASSERT.equal(decipher.output.getBytes(), 'foobar');
});
// OpenSSL equivalent:
// openssl enc -des-ede3 -K a1c06b381adf36517e84575552777779da5e3d9f994b05b5 -nosalt
it('should 3des-ecb encrypt: foobar', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf36517e84575552777779da5e3d9f994b05b5'));
var cipher = CIPHER.createCipher('3DES-ECB', key);
cipher.start();
cipher.update(UTIL.createBuffer('foobar'));
cipher.finish();
ASSERT.equal(cipher.output.toHex(), 'fce8b1ee8c6440d1');
});
// OpenSSL equivalent:
// openssl enc -d -des-ede3 -K a1c06b381adf36517e84575552777779da5e3d9f994b05b5 -nosalt
it('should 3des-ecb decrypt: fce8b1ee8c6440d1', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf36517e84575552777779da5e3d9f994b05b5'));
var decipher = CIPHER.createDecipher('3DES-ECB', key);
decipher.start();
decipher.update(UTIL.createBuffer(UTIL.hexToBytes('fce8b1ee8c6440d1')));
decipher.finish();
ASSERT.equal(decipher.output.getBytes(), 'foobar');
});
// OpenSSL equivalent:
// openssl enc -des3 -K a1c06b381adf36517e84575552777779da5e3d9f994b05b5 -iv 818bcf76efc59662 -nosalt
it('should 3des-cbc encrypt "foobar", restart, and encrypt "foobar,,"', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf36517e84575552777779da5e3d9f994b05b5'));
var iv = new UTIL.createBuffer(
UTIL.hexToBytes('818bcf76efc59662'));
var cipher = CIPHER.createCipher('3DES-CBC', key);
cipher.start({iv: iv.copy()});
cipher.update(UTIL.createBuffer('foobar'));
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '209225f7687ca0b2');
cipher.start({iv: iv.copy()});
cipher.update(UTIL.createBuffer('foobar,,'));
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '57156174c48dfc37293831bf192a6742');
});
// OpenSSL equivalent:
// openssl enc -d -des3 -K a1c06b381adf36517e84575552777779da5e3d9f994b05b5 -iv 818bcf76efc59662 -nosalt
it('should 3des-cbc decrypt "209225f7687ca0b2", restart, and decrypt "57156174c48dfc37293831bf192a6742,,"', function() {
var key = new UTIL.createBuffer(
UTIL.hexToBytes('a1c06b381adf36517e84575552777779da5e3d9f994b05b5'));
var iv = new UTIL.createBuffer(
UTIL.hexToBytes('818bcf76efc59662'));
var decipher = CIPHER.createDecipher('3DES-CBC', key);
decipher.start({iv: iv.copy()});
decipher.update(UTIL.createBuffer(UTIL.hexToBytes('209225f7687ca0b2')));
decipher.finish();
ASSERT.equal(decipher.output.getBytes(), 'foobar');
decipher.start({iv: iv.copy()});
decipher.update(
UTIL.createBuffer(UTIL.hexToBytes('57156174c48dfc37293831bf192a6742')));
decipher.finish();
ASSERT.equal(decipher.output.getBytes(), 'foobar,,');
});
});
}
// check for AMD
var forge = {};
if(typeof define === 'function') {
define([
'forge/cipher',
'forge/des',
'forge/util'
], function(CIPHER, DES, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
CIPHER(forge),
DES(forge),
UTIL(forge)
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/cipher')(forge),
require('../../js/des')(forge),
require('../../js/util')(forge));
}
})();

View File

@@ -0,0 +1,85 @@
(function() {
function Tests(ASSERT, HMAC, UTIL) {
describe('hmac', function() {
it('should md5 hash "Hi There", 16-byte key', function() {
var key = UTIL.hexToBytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
var hmac = HMAC.create();
hmac.start('MD5', key);
hmac.update('Hi There');
ASSERT.equal(hmac.digest().toHex(), '9294727a3638bb1c13f48ef8158bfc9d');
});
it('should md5 hash "what do ya want for nothing?", "Jefe" key', function() {
var hmac = HMAC.create();
hmac.start('MD5', 'Jefe');
hmac.update('what do ya want for nothing?');
ASSERT.equal(hmac.digest().toHex(), '750c783e6ab0b503eaa86e310a5db738');
});
it('should md5 hash "Test Using Larger Than Block-Size Key - Hash Key First", 80-byte key', function() {
var key = UTIL.hexToBytes(
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
var hmac = HMAC.create();
hmac.start('MD5', key);
hmac.update('Test Using Larger Than Block-Size Key - Hash Key First');
ASSERT.equal(hmac.digest().toHex(), '6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd');
});
it('should sha1 hash "Hi There", 20-byte key', function() {
var key = UTIL.hexToBytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
var hmac = HMAC.create();
hmac.start('SHA1', key);
hmac.update('Hi There');
ASSERT.equal(
hmac.digest().toHex(), 'b617318655057264e28bc0b6fb378c8ef146be00');
});
it('should sha1 hash "what do ya want for nothing?", "Jefe" key', function() {
var hmac = HMAC.create();
hmac.start('SHA1', 'Jefe');
hmac.update('what do ya want for nothing?');
ASSERT.equal(
hmac.digest().toHex(), 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79');
});
it('should sha1 hash "Test Using Larger Than Block-Size Key - Hash Key First", 80-byte key', function() {
var key = UTIL.hexToBytes(
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
var hmac = HMAC.create();
hmac.start('SHA1', key);
hmac.update('Test Using Larger Than Block-Size Key - Hash Key First');
ASSERT.equal(
hmac.digest().toHex(), 'aa4ae5e15272d00e95705637ce8a3b55ed402112');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/hmac',
'forge/util'
], function(HMAC, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
HMAC(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/hmac')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,198 @@
(function() {
function Tests(ASSERT, KEM, MD, RSA, UTIL, JSBN, RANDOM) {
function FixedSecureRandom(str) {
var bytes = UTIL.hexToBytes(str);
this.getBytesSync = function(count) {
// prepend zeros
return UTIL.fillString(String.fromCharCode(0), bytes.length - count) +
bytes;
};
}
describe('kem', function() {
it('should generate and encrypt a symmetric key and decrypt it 10x', function() {
for(var i = 0; i < 10; ++i) {
var kdf = new KEM.kdf1(MD.sha256.create());
var kem = KEM.rsa.create(kdf);
var pair = RSA.generateKeyPair(512);
var result = kem.encrypt(pair.publicKey, 256);
var key1 = result.key;
var key2 = kem.decrypt(pair.privateKey, result.encapsulation, 256);
ASSERT.equal(UTIL.bytesToHex(key1), UTIL.bytesToHex(key2));
}
});
});
/**
* According to section "C.6 Test vectors for RSA-KEM" from ISO-18033-2 final
* draft.
*/
describe('C.6 Test vectors for RSA-KEM from ISO-18033-2 final', function() {
it('should pass test vector C.6.1', function() {
var n = '5888113332502691251761936431009284884966640757179802337490546478326238537107326596800820237597139824869184990638749556269785797065508097452399642780486933';
var e = '65537';
var d = '3202313555859948186315374524474173995679783580392140237044349728046479396037520308981353808895461806395564474639124525446044708705259675840210989546479265';
var C0 = '4603e5324cab9cef8365c817052d954d44447b1667099edc69942d32cd594e4ffcf268ae3836e2c35744aaa53ae201fe499806b67dedaa26bf72ecbd117a6fc0';
var K = '5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04';
var kdf = new KEM.kdf1(MD.sha1.create());
var rnd = new FixedSecureRandom('032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var kem = KEM.rsa.create(kdf, {prng: rnd});
var rsaPublicKey = RSA.setPublicKey(
new JSBN.BigInteger(n), new JSBN.BigInteger(e));
var rsaPrivateKey = RSA.setPrivateKey(
new JSBN.BigInteger(n), null, new JSBN.BigInteger(d));
var result = kem.encrypt(rsaPublicKey, 128);
ASSERT.equal(UTIL.bytesToHex(result.encapsulation), C0);
ASSERT.equal(UTIL.bytesToHex(result.key), K);
var decryptedKey = kem.decrypt(rsaPrivateKey, result.encapsulation, 128);
ASSERT.equal(UTIL.bytesToHex(decryptedKey), K);
});
it('should pass test vector C.6.2', function() {
var n = '5888113332502691251761936431009284884966640757179802337490546478326238537107326596800820237597139824869184990638749556269785797065508097452399642780486933';
var e = '65537';
var d = '3202313555859948186315374524474173995679783580392140237044349728046479396037520308981353808895461806395564474639124525446044708705259675840210989546479265';
var C0 = '4603e5324cab9cef8365c817052d954d44447b1667099edc69942d32cd594e4ffcf268ae3836e2c35744aaa53ae201fe499806b67dedaa26bf72ecbd117a6fc0';
var K = '0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807';
var kdf = new KEM.kdf2(MD.sha1.create());
var rnd = new FixedSecureRandom('032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var kem = KEM.rsa.create(kdf, {prng: rnd});
var rsaPublicKey = RSA.setPublicKey(
new JSBN.BigInteger(n), new JSBN.BigInteger(e));
var rsaPrivateKey = RSA.setPrivateKey(
new JSBN.BigInteger(n), null, new JSBN.BigInteger(d));
var result = kem.encrypt(rsaPublicKey, 128);
ASSERT.equal(UTIL.bytesToHex(result.encapsulation), C0);
ASSERT.equal(UTIL.bytesToHex(result.key), K);
var decryptedKey = kem.decrypt(rsaPrivateKey, result.encapsulation, 128);
ASSERT.equal(UTIL.bytesToHex(decryptedKey), K);
});
it('should pass test vector C.6.3', function() {
var n = '5888113332502691251761936431009284884966640757179802337490546478326238537107326596800820237597139824869184990638749556269785797065508097452399642780486933';
var e = '65537';
var d = '3202313555859948186315374524474173995679783580392140237044349728046479396037520308981353808895461806395564474639124525446044708705259675840210989546479265';
var C0 = '4603e5324cab9cef8365c817052d954d44447b1667099edc69942d32cd594e4ffcf268ae3836e2c35744aaa53ae201fe499806b67dedaa26bf72ecbd117a6fc0';
var K = '09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb';
var kdf = new KEM.kdf1(MD.sha256.create(), 20);
var rnd = new FixedSecureRandom('032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var kem = KEM.rsa.create(kdf, {prng: rnd});
var rsaPublicKey = RSA.setPublicKey(
new JSBN.BigInteger(n), new JSBN.BigInteger(e));
var rsaPrivateKey = RSA.setPrivateKey(
new JSBN.BigInteger(n), null, new JSBN.BigInteger(d));
var result = kem.encrypt(rsaPublicKey, 128);
ASSERT.equal(UTIL.bytesToHex(result.encapsulation), C0);
ASSERT.equal(UTIL.bytesToHex(result.key), K);
var decryptedKey = kem.decrypt(rsaPrivateKey, result.encapsulation, 128);
ASSERT.equal(UTIL.bytesToHex(decryptedKey), K);
});
it('should pass test vector C.6.4', function() {
var n = '5888113332502691251761936431009284884966640757179802337490546478326238537107326596800820237597139824869184990638749556269785797065508097452399642780486933';
var e = '65537';
var d = '3202313555859948186315374524474173995679783580392140237044349728046479396037520308981353808895461806395564474639124525446044708705259675840210989546479265';
var C0 = '4603e5324cab9cef8365c817052d954d44447b1667099edc69942d32cd594e4ffcf268ae3836e2c35744aaa53ae201fe499806b67dedaa26bf72ecbd117a6fc0';
var K = '10a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb260892670e0814c348664f6a7248aaf998a3acc6';
var kdf = new KEM.kdf2(MD.sha256.create(), 20);
var rnd = new FixedSecureRandom('00032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var kem = KEM.rsa.create(kdf, {prng: rnd});
var rsaPublicKey = RSA.setPublicKey(
new JSBN.BigInteger(n), new JSBN.BigInteger(e));
var rsaPrivateKey = RSA.setPrivateKey(
new JSBN.BigInteger(n), null, new JSBN.BigInteger(d));
var result = kem.encrypt(rsaPublicKey, 128);
ASSERT.equal(UTIL.bytesToHex(result.encapsulation), C0);
ASSERT.equal(UTIL.bytesToHex(result.key), K);
var decryptedKey = kem.decrypt(rsaPrivateKey, result.encapsulation, 128);
ASSERT.equal(UTIL.bytesToHex(decryptedKey), K);
});
});
describe('prepended zeros test', function() {
it('should pass when random has leading zeros', function() {
var n = '5888113332502691251761936431009284884966640757179802337490546478326238537107326596800820237597139824869184990638749556269785797065508097452399642780486933';
var e = '65537';
var d = '3202313555859948186315374524474173995679783580392140237044349728046479396037520308981353808895461806395564474639124525446044708705259675840210989546479265';
var C0 = '5f268a76c1aed04bc195a143d7ee768bee0aad308d16196274a02d9c1a72bbe10cbf718de323fc0135c5f8129f96ac8f504d9623960dc54cd87bddee94f5a0b2';
var K = '8bf41e59dc1b83142ee32569a347a94539e48c98347c685a29e3aa8b7a3ea714d68c1a43c4a760c9d4a45149b0ce8b681e98076bdd4393394c7832a7fa71848257772ac38a4e7fbe96e8bb383becbb7242841946e82e35d9ef1667245fc82601e7edf53b897f5ce2b6bce8e1e3212abd5a8a99a0c9b99472e22a313dac396383';
var kdf = new KEM.kdf1(MD.sha1.create());
var rnd = new FixedSecureRandom('000e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var kem = KEM.rsa.create(kdf, {prng: rnd});
var rsaPublicKey = RSA.setPublicKey(
new JSBN.BigInteger(n), new JSBN.BigInteger(e));
var rsaPrivateKey = RSA.setPrivateKey(
new JSBN.BigInteger(n), null, new JSBN.BigInteger(d));
var result = kem.encrypt(rsaPublicKey, 128);
ASSERT.equal(UTIL.bytesToHex(result.encapsulation), C0);
ASSERT.equal(UTIL.bytesToHex(result.key), K);
var decryptedKey = kem.decrypt(rsaPrivateKey, result.encapsulation, 128);
ASSERT.equal(UTIL.bytesToHex(decryptedKey), K);
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/kem',
'forge/md',
'forge/rsa',
'forge/util',
'forge/jsbn',
'forge/random'
], function(KEM, MD, RSA, UTIL, JSBN, RANDOM) {
Tests(
// Global provided by test harness
ASSERT,
KEM(),
MD(),
RSA(),
UTIL(),
JSBN(),
RANDOM()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/kem')(),
require('../../js/md')(),
require('../../js/rsa')(),
require('../../js/util')(),
require('../../js/jsbn')(),
require('../../js/random')());
}
})();

View File

@@ -0,0 +1,117 @@
(function() {
function Tests(ASSERT, MD5, UTIL) {
describe('md5', function() {
it('should digest the empty string', function() {
var md = MD5.create();
ASSERT.equal(md.digest().toHex(), 'd41d8cd98f00b204e9800998ecf8427e');
});
it('should digest "abc"', function() {
var md = MD5.create();
md.update('abc');
ASSERT.equal(md.digest().toHex(), '900150983cd24fb0d6963f7d28e17f72');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = MD5.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(md.digest().toHex(), '9e107d9d372bb6826bd81d3542a419d6');
});
it('should digest "c\'\u00e8"', function() {
var md = MD5.create();
md.update("c\'\u00e8", 'utf8');
ASSERT.equal(md.digest().toHex(), '8ef7c2941d78fe89f31e614437c9db59');
});
it('should digest "THIS IS A MESSAGE"', function() {
var md = MD5.create();
md.start();
md.update('THIS IS ');
md.update('A MESSAGE');
// do twice to check continuing digest
ASSERT.equal(md.digest().toHex(), '78eebfd9d42958e3f31244f116ab7bbe');
ASSERT.equal(md.digest().toHex(), '78eebfd9d42958e3f31244f116ab7bbe');
});
it('should digest a long message', function() {
var input = UTIL.hexToBytes(
'0100002903018d32e9c6dc423774c4c39a5a1b78f44cc2cab5f676d39' +
'f703d29bfa27dfeb870000002002f01000200004603014c2c1e835d39' +
'da71bc0857eb04c2b50fe90dbb2a8477fe7364598d6f0575999c20a6c' +
'7248c5174da6d03ac711888f762fc4ed54f7254b32273690de849c843' +
'073d002f000b0003d20003cf0003cc308203c8308202b0a0030201020' +
'20100300d06092a864886f70d0101050500308186310b300906035504' +
'0613025553311d301b060355040a13144469676974616c2042617a616' +
'1722c20496e632e31443042060355040b133b4269746d756e6b206c6f' +
'63616c686f73742d6f6e6c7920436572746966696361746573202d204' +
'17574686f72697a6174696f6e20766961204254503112301006035504' +
'0313096c6f63616c686f7374301e170d3130303231343137303931395' +
'a170d3230303231333137303931395a308186310b3009060355040613' +
'025553311d301b060355040a13144469676974616c2042617a6161722' +
'c20496e632e31443042060355040b133b4269746d756e6b206c6f6361' +
'6c686f73742d6f6e6c7920436572746966696361746573202d2041757' +
'4686f72697a6174696f6e207669612042545031123010060355040313' +
'096c6f63616c686f737430820122300d06092a864886f70d010101050' +
'00382010f003082010a0282010100dc436f17d6909d8a9d6186ea218e' +
'b5c86b848bae02219bd56a71203daf07e81bc19e7e98134136bcb0128' +
'81864bf03b3774652ad5eab85dba411a5114ffeac09babce75f313143' +
'45512cd87c91318b2e77433270a52185fc16f428c3ca412ad6e9484bc' +
'2fb87abb4e8fb71bf0f619e31a42340b35967f06c24a741a31c979c0b' +
'b8921a90a47025fbeb8adca576979e70a56830c61170c9647c18c0794' +
'd68c0df38f3aac5fc3b530e016ea5659715339f3f3c209cdee9dbe794' +
'b5af92530c5754c1d874b78974bfad994e0dfc582275e79feb522f6e4' +
'bcc2b2945baedfb0dbdaebb605f9483ff0bea29ecd5f4d6f2769965d1' +
'b3e04f8422716042680011ff676f0203010001a33f303d300c0603551' +
'd130101ff04023000300e0603551d0f0101ff0404030204f0301d0603' +
'551d250416301406082b0601050507030106082b06010505070302300' +
'd06092a864886f70d010105050003820101009c4562be3f2d8d8e3880' +
'85a697f2f106eaeff4992a43f198fe3dcf15c8229cf1043f061a38204' +
'f73d86f4fb6348048cc5279ed719873aa10e3773d92b629c2c3fcce04' +
'012c81ba3b4ec451e9644ec5191078402d845e05d02c7b4d974b45882' +
'76e5037aba7ef26a8bddeb21e10698c82f425e767dc401adf722fa73a' +
'b78cfa069bd69052d7ca6a75cc9225550e315d71c5f8764362ea4dbc6' +
'ecb837a8471043c5a7f826a71af145a053090bd4bccca6a2c552841cd' +
'b1908a8352f49283d2e641acdef667c7543af441a16f8294251e2ac37' +
'6fa507b53ae418dd038cd20cef1e7bfbf5ae03a7c88d93d843abaabbd' +
'c5f3431132f3e559d2dd414c3eda38a210b80e0000001000010201002' +
'6a220b7be857402819b78d81080d01a682599bbd00902985cc64edf8e' +
'520e4111eb0e1729a14ffa3498ca259cc9ad6fc78fa130d968ebdb78d' +
'c0b950c0aa44355f13ba678419185d7e4608fe178ca6b2cef33e41937' +
'78d1a70fe4d0dfcb110be4bbb4dbaa712177655728f914ab4c0f6c4ae' +
'f79a46b3d996c82b2ebe9ed1748eb5cace7dc44fb67e73f452a047f2e' +
'd199b3d50d5db960acf03244dc8efa4fc129faf8b65f9e52e62b55447' +
'22bd17d2358e817a777618a4265a3db277fc04851a82a91fe6cdcb812' +
'7f156e0b4a5d1f54ce2742eb70c895f5f8b85f5febe69bc73e891f928' +
'0826860a0c2ef94c7935e6215c3c4cd6b0e43e80cca396d913d36be');
var md = MD5.create();
md.update(input);
ASSERT.equal(md.digest().toHex(), 'd15a2da0e92c3da55dc573f885b6e653');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/md5',
'forge/util'
], function(MD5, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
MD5(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/md5')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,39 @@
(function() {
function Tests(ASSERT, MGF, MD, UTIL) {
describe('mgf1', function() {
it('should digest the empty string', function() {
var seed = UTIL.hexToBytes('032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d764374152e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4');
var expect = UTIL.hexToBytes('5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04');
var mgf = MGF.mgf1.create(MD.sha1.create());
var result = mgf.generate(seed, expect.length);
ASSERT.equal(result, expect);
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/mgf',
'forge/md',
'forge/util'
], function(MGF, MD, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
MGF(),
MD(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/mgf')(),
require('../../js/md')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,140 @@
(function() {
function Tests(ASSERT, PBKDF2, MD, UTIL) {
describe('pbkdf2', function() {
it('should derive a password with hmac-sha-1 c=1', function() {
var dkHex = UTIL.bytesToHex(PBKDF2('password', 'salt', 1, 20));
ASSERT.equal(dkHex, '0c60c80f961f0e71f3a9b524af6012062fe037a6');
});
it('should derive a password with hmac-sha-1 c=2', function() {
var dkHex = UTIL.bytesToHex(PBKDF2('password', 'salt', 2, 20));
ASSERT.equal(dkHex, 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957');
});
it('should derive a password with hmac-sha-1 c=5 keylen=8', function() {
var salt = UTIL.hexToBytes('1234567878563412');
var dkHex = UTIL.bytesToHex(PBKDF2('password', salt, 5, 8));
ASSERT.equal(dkHex, 'd1daa78615f287e6');
});
it('should derive a password with hmac-sha-1 c=4096', function() {
// Note: might be too slow on old browsers
var dkHex = UTIL.bytesToHex(PBKDF2('password', 'salt', 4096, 20));
ASSERT.equal(dkHex, '4b007901b765489abead49d926f721d065a429c1');
});
/*
it('should derive a password with hmac-sha-1 c=16777216', function() {
// Note: too slow
var dkHex = UTIL.bytesToHex(PBKDF2('password', 'salt', 16777216, 20));
ASSERT.equal(dkHex, 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984');
});*/
it('should derive a password with hmac-sha-256 c=1000', function() {
// Note: might be too slow on old browsers
var salt = '4bcda0d1c689fe465c5b8a817f0ddf3d';
var md = MD.sha256.create();
var dkHex = UTIL.bytesToHex(PBKDF2('password', salt, 1000, 48, md));
ASSERT.equal(dkHex, '9da8a5f4ae605f35e82e5beac5f362df15c4255d88f738d641466a4107f9970238e768e72af29ac89a1b16ff277b31d2');
});
it('should derive a password with hmac-sha-256 (passed as an algorithm identifier) c=1000', function() {
// Note: might be too slow on old browsers
var salt = '4bcda0d1c689fe465c5b8a817f0ddf3d';
var dkHex = UTIL.bytesToHex(PBKDF2('password', salt, 1000, 48, 'sha256'));
ASSERT.equal(dkHex, '9da8a5f4ae605f35e82e5beac5f362df15c4255d88f738d641466a4107f9970238e768e72af29ac89a1b16ff277b31d2');
});
it('should asynchronously derive a password with hmac-sha-1 c=1', function(done) {
PBKDF2('password', 'salt', 1, 20, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, '0c60c80f961f0e71f3a9b524af6012062fe037a6');
done();
});
});
it('should asynchronously derive a password with hmac-sha-1 c=2', function(done) {
PBKDF2('password', 'salt', 2, 20, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957');
done();
});
});
it('should asynchronously derive a password with hmac-sha-1 c=5 keylen=8', function(done) {
var salt = UTIL.hexToBytes('1234567878563412');
PBKDF2('password', salt, 5, 8, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, 'd1daa78615f287e6');
done();
});
});
it('should asynchronously derive a password with hmac-sha-1 c=4096', function(done) {
// Note: might be too slow on old browsers
PBKDF2('password', 'salt', 4096, 20, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, '4b007901b765489abead49d926f721d065a429c1');
done();
});
});
/*
it('should asynchronously derive a password with hmac-sha-1 c=16777216', function(done) {
// Note: too slow
PBKDF2('password', 'salt', 16777216, 20, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984');
done();
});
});*/
it('should asynchronously derive a password with hmac-sha-256 c=1000', function(done) {
// Note: might be too slow on old browsers
var salt = '4bcda0d1c689fe465c5b8a817f0ddf3d';
var md = MD.sha256.create();
PBKDF2('password', salt, 1000, 48, md, function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, '9da8a5f4ae605f35e82e5beac5f362df15c4255d88f738d641466a4107f9970238e768e72af29ac89a1b16ff277b31d2');
done();
});
});
it('should asynchronously derive a password with hmac-sha-256 (passed as an algorithm identifier) c=1000', function(done) {
// Note: might be too slow on old browsers
var salt = '4bcda0d1c689fe465c5b8a817f0ddf3d';
PBKDF2('password', salt, 1000, 48, 'sha256', function(err, dk) {
var dkHex = UTIL.bytesToHex(dk);
ASSERT.equal(dkHex, '9da8a5f4ae605f35e82e5beac5f362df15c4255d88f738d641466a4107f9970238e768e72af29ac89a1b16ff277b31d2');
done();
});
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pbkdf2',
'forge/md',
'forge/util'
], function(PBKDF2, MD, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
PBKDF2(),
MD(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pbkdf2')(),
require('../../js/md')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,104 @@
(function() {
function Tests(ASSERT, PEM) {
var _input = '-----BEGIN PRIVACY-ENHANCED MESSAGE-----\r\n' +
'Proc-Type: 4,ENCRYPTED\r\n' +
'Content-Domain: RFC822\r\n' +
'DEK-Info: DES-CBC,F8143EDE5960C597\r\n' +
'Originator-ID-Symmetric: linn@zendia.enet.dec.com,,\r\n' +
'Recipient-ID-Symmetric: linn@zendia.enet.dec.com,ptf-kmc,3\r\n' +
'Key-Info: DES-ECB,RSA-MD2,9FD3AAD2F2691B9A,\r\n' +
' B70665BB9BF7CBCDA60195DB94F727D3\r\n' +
'Recipient-ID-Symmetric: pem-dev@tis.com,ptf-kmc,4\r\n' +
'Key-Info: DES-ECB,RSA-MD2,161A3F75DC82EF26,\r\n' +
' E2EF532C65CBCFF79F83A2658132DB47\r\n' +
'\r\n' +
'LLrHB0eJzyhP+/fSStdW8okeEnv47jxe7SJ/iN72ohNcUk2jHEUSoH1nvNSIWL9M\r\n' +
'8tEjmF/zxB+bATMtPjCUWbz8Lr9wloXIkjHUlBLpvXR0UrUzYbkNpk0agV2IzUpk\r\n' +
'J6UiRRGcDSvzrsoK+oNvqu6z7Xs5Xfz5rDqUcMlK1Z6720dcBWGGsDLpTpSCnpot\r\n' +
'dXd/H5LMDWnonNvPCwQUHg==\r\n' +
'-----END PRIVACY-ENHANCED MESSAGE-----\r\n' +
'-----BEGIN PRIVACY-ENHANCED MESSAGE-----\r\n' +
'Proc-Type: 4,ENCRYPTED\r\n' +
'Content-Domain: RFC822\r\n' +
'DEK-Info: DES-CBC,BFF968AA74691AC1\r\n' +
'Originator-Certificate:\r\n' +
' MIIBlTCCAScCAWUwDQYJKoZIhvcNAQECBQAwUTELMAkGA1UEBhMCVVMxIDAeBgNV\r\n' +
' BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMQ8wDQYDVQQLEwZCZXRhIDExDzAN\r\n' +
' BgNVBAsTBk5PVEFSWTAeFw05MTA5MDQxODM4MTdaFw05MzA5MDMxODM4MTZaMEUx\r\n' +
' CzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEU\r\n' +
' MBIGA1UEAxMLVGVzdCBVc2VyIDEwWTAKBgRVCAEBAgICAANLADBIAkEAwHZHl7i+\r\n' +
' yJcqDtjJCowzTdBJrdAiLAnSC+CnnjOJELyuQiBgkGrgIh3j8/x0fM+YrsyF1u3F\r\n' +
' LZPVtzlndhYFJQIDAQABMA0GCSqGSIb3DQEBAgUAA1kACKr0PqphJYw1j+YPtcIq\r\n' +
' iWlFPuN5jJ79Khfg7ASFxskYkEMjRNZV/HZDZQEhtVaU7Jxfzs2wfX5byMp2X3U/\r\n' +
' 5XUXGx7qusDgHQGs7Jk9W8CW1fuSWUgN4w==\r\n' +
'Key-Info: RSA,\r\n' +
' I3rRIGXUGWAF8js5wCzRTkdhO34PTHdRZY9Tuvm03M+NM7fx6qc5udixps2Lng0+\r\n' +
' wGrtiUm/ovtKdinz6ZQ/aQ==\r\n' +
'Issuer-Certificate:\r\n' +
' MIIB3DCCAUgCAQowDQYJKoZIhvcNAQECBQAwTzELMAkGA1UEBhMCVVMxIDAeBgNV\r\n' +
' BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMQ8wDQYDVQQLEwZCZXRhIDExDTAL\r\n' +
' BgNVBAsTBFRMQ0EwHhcNOTEwOTAxMDgwMDAwWhcNOTIwOTAxMDc1OTU5WjBRMQsw\r\n' +
' CQYDVQQGEwJVUzEgMB4GA1UEChMXUlNBIERhdGEgU2VjdXJpdHksIEluYy4xDzAN\r\n' +
' BgNVBAsTBkJldGEgMTEPMA0GA1UECxMGTk9UQVJZMHAwCgYEVQgBAQICArwDYgAw\r\n' +
' XwJYCsnp6lQCxYykNlODwutF/jMJ3kL+3PjYyHOwk+/9rLg6X65B/LD4bJHtO5XW\r\n' +
' cqAz/7R7XhjYCm0PcqbdzoACZtIlETrKrcJiDYoP+DkZ8k1gCk7hQHpbIwIDAQAB\r\n' +
' MA0GCSqGSIb3DQEBAgUAA38AAICPv4f9Gx/tY4+p+4DB7MV+tKZnvBoy8zgoMGOx\r\n' +
' dD2jMZ/3HsyWKWgSF0eH/AJB3qr9zosG47pyMnTf3aSy2nBO7CMxpUWRBcXUpE+x\r\n' +
' EREZd9++32ofGBIXaialnOgVUn0OzSYgugiQ077nJLDUj0hQehCizEs5wUJ35a5h\r\n' +
'MIC-Info: RSA-MD5,RSA,\r\n' +
' UdFJR8u/TIGhfH65ieewe2lOW4tooa3vZCvVNGBZirf/7nrgzWDABz8w9NsXSexv\r\n' +
' AjRFbHoNPzBuxwmOAFeA0HJszL4yBvhG\r\n' +
'Recipient-ID-Asymmetric:\r\n' +
' MFExCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5j\r\n' +
' LjEPMA0GA1UECxMGQmV0YSAxMQ8wDQYDVQQLEwZOT1RBUlk=,66\r\n' +
'Key-Info: RSA,\r\n' +
' O6BS1ww9CTyHPtS3bMLD+L0hejdvX6Qv1HK2ds2sQPEaXhX8EhvVphHYTjwekdWv\r\n' +
' 7x0Z3Jx2vTAhOYHMcqqCjA==\r\n' +
'\r\n' +
'qeWlj/YJ2Uf5ng9yznPbtD0mYloSwIuV9FRYx+gzY+8iXd/NQrXHfi6/MhPfPF3d\r\n' +
'jIqCJAxvld2xgqQimUzoS1a4r7kQQ5c/Iua4LqKeq3ciFzEv/MbZhA==\r\n' +
'-----END PRIVACY-ENHANCED MESSAGE-----\r\n' +
'-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIIBPAIBAAJBALjXU+IdHkSkdBscgXf+EBoa55ruAIsU50uDFjFBkp+rWFt5AOGF\r\n' +
'9xL1/HNIby5M64BCw021nJTZKEOmXKdmzYsCAwEAAQJBAApyYRNOgf9vLAC8Q7T8\r\n' +
'bvyKuLxQ50b1D319EywFgLv1Yn0s/F9F+Rew6c04Q0pIqmuOGUM7z94ul/y5OlNJ\r\n' +
'2cECIQDveEW1ib2+787l7Y0tMeDzf/HQl4MAWdcxXWOeUFK+7QIhAMWZsukutEn9\r\n' +
'9/yqFMt8bL/dclfNn1IAgUL4+dMJ7zdXAiEAhaxGhVKxN28XuCOFhe/s2R/XdQ/O\r\n' +
'UZjU1bqCzDGcLvUCIGYmxu71Tg7SVFkyM/3eHPozKOFrU2m5CRnuTHhlMl2RAiEA\r\n' +
'0vhM5TEmmNWz0anPVabqDj9TA0z5MsDJQcn5NmO9xnw=\r\n' +
'-----END RSA PRIVATE KEY-----\r\n';
describe('pem', function() {
it('should decode and re-encode PEM messages', function() {
var msgs = PEM.decode(_input);
var output = '';
for(var i = 0; i < msgs.length; ++i) {
output += PEM.encode(msgs[i]);
}
ASSERT.equal(output, _input);
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pem'
], function(PEM) {
Tests(
// Global provided by test harness
ASSERT,
PEM()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pem')());
}
})();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,687 @@
(function() {
function Tests(ASSERT, FORGE) {
var forge = FORGE();
var PKCS12 = forge.pkcs12;
var ASN1 = forge.asn1;
var PEM = forge.pem;
var PKI = forge.pki;
var UTIL = forge.util;
var _data;
describe('pkcs12', function() {
it('should create certificate-only p12', function() {
var p12Asn = PKCS12.toPkcs12Asn1(null, _data.certificate, null, {
useMac: false,
generateLocalKeyId: false
});
var p12Der = ASN1.toDer(p12Asn).getBytes();
/* The generated PKCS#12 file lacks a MAC, therefore pass -nomacver to
OpenSSL: openssl pkcs12 -nomacver -nodes -in pkcs12_certonly.p12 */
ASSERT.equal(p12Der, UTIL.decode64(_data.p12certonly));
});
it('should create key-only p12', function() {
var privateKey = PKI.privateKeyFromPem(_data.privateKey);
var p12Asn = PKCS12.toPkcs12Asn1(privateKey, null, null, {
useMac: false,
generateLocalKeyId: false
});
var p12Der = ASN1.toDer(p12Asn).getBytes();
/* The generated PKCS#12 file lacks a MAC, therefore pass -nomacver to
OpenSSL: openssl pkcs12 -nomacver -nodes -in pkcs12_keyonly.p12 */
ASSERT.equal(p12Der, UTIL.decode64(_data.p12keyonly));
});
it('should create encrypted-key-only p12', function() {
/* Note we need to mock the PRNG, since the PKCS#12 file uses encryption
which otherwise would differ each time due to the randomized IV. */
var oldRandomGenerate = forge.random.generate;
forge.random.generate = function(num) {
return UTIL.createBuffer().fillWithByte(0, num).getBytes();
};
var privateKey = PKI.privateKeyFromPem(_data.privateKey);
var p12Asn = PKCS12.toPkcs12Asn1(privateKey, null, 'nopass', {
useMac: false,
generateLocalKeyId: false
});
var p12Der = ASN1.toDer(p12Asn).getBytes();
// restore old random function
forge.random.generate = oldRandomGenerate;
/* The generated PKCS#12 file lacks a MAC, therefore pass -nomacver to
OpenSSL: openssl pkcs12 -nomacver -in pkcs12_enckeyonly.p12 */
ASSERT.equal(p12Der, UTIL.decode64(_data.p12enckeyonly));
});
it('should import certificate-only p12', function() {
var p12Der = UTIL.decode64(_data.p12certonly);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1);
ASSERT.equal(p12.version, 3);
// PKCS#12 PFX has exactly one SafeContents; it is not encrypted
ASSERT.equal(p12.safeContents.length, 1);
ASSERT.equal(p12.safeContents[0].encrypted, false);
// SafeContents has one SafeBag which has one CertBag with the cert
ASSERT.equal(p12.safeContents[0].safeBags.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[0].type, PKI.oids.certBag);
// check cert's serial number
ASSERT.equal(
p12.safeContents[0].safeBags[0].cert.serialNumber,
'00d4541c40d835e2f3');
});
it('should import key-only p12', function() {
var p12Der = UTIL.decode64(_data.p12keyonly);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1);
ASSERT.equal(p12.version, 3);
// PKCS#12 PFX has exactly one SafeContents; it is not encrypted
ASSERT.equal(p12.safeContents.length, 1);
ASSERT.equal(p12.safeContents[0].encrypted, false);
// SafeContents has one SafeBag which has one KeyBag with the key
ASSERT.equal(p12.safeContents[0].safeBags.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[0].type, PKI.oids.keyBag);
// compare the key from the PFX by comparing both primes
var expected = PKI.privateKeyFromPem(_data.privateKey);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.p, expected.p);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.q, expected.q);
});
it('should import encrypted-key-only p12', function() {
var p12Der = UTIL.decode64(_data.p12enckeyonly);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, 'nopass');
ASSERT.equal(p12.version, 3);
// PKCS#12 PFX has exactly one SafeContents; it is *not* encrypted,
// only the key itself is encrypted (shrouded)
ASSERT.equal(p12.safeContents.length, 1);
ASSERT.equal(p12.safeContents[0].encrypted, false);
// SafeContents has one SafeBag which has one shrouded KeyBag with the key
ASSERT.equal(p12.safeContents[0].safeBags.length, 1);
ASSERT.equal(
p12.safeContents[0].safeBags[0].type, PKI.oids.pkcs8ShroudedKeyBag);
// compare the key from the PFX by comparing both primes
var expected = PKI.privateKeyFromPem(_data.privateKey);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.p, expected.p);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.q, expected.q);
});
it('should import an encrypted-key-only p12', function() {
var p12Der = UTIL.decode64(_data.p12enckeyonly);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, 'nopass');
ASSERT.equal(p12.version, 3);
// PKCS#12 PFX has exactly one SafeContents; it is *not* encrypted,
// only the key itself is encrypted (shrouded)
ASSERT.equal(p12.safeContents.length, 1);
ASSERT.equal(p12.safeContents[0].encrypted, false);
// SafeContents has one SafeBag which has one shrouded KeyBag with the key
ASSERT.equal(p12.safeContents[0].safeBags.length, 1);
ASSERT.equal(
p12.safeContents[0].safeBags[0].type, PKI.oids.pkcs8ShroudedKeyBag);
// compare the key from the PFX by comparing both primes
var expected = PKI.privateKeyFromPem(_data.privateKey);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.p, expected.p);
ASSERT.deepEqual(p12.safeContents[0].safeBags[0].key.q, expected.q);
});
it('should import an encrypted p12 with keys and certificates', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
ASSERT.equal(p12.version, 3);
// PKCS#12 PFX has two SafeContents; first is *not* encrypted but
// contains two shrouded keys, second is encrypted and has six
// certificates
ASSERT.equal(p12.safeContents.length, 2);
ASSERT.equal(p12.safeContents[0].encrypted, false);
ASSERT.equal(p12.safeContents[0].safeBags.length, 2);
ASSERT.equal(p12.safeContents[0].safeBags[0].type, PKI.oids.pkcs8ShroudedKeyBag);
ASSERT.equal(p12.safeContents[0].safeBags[0].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[0].attributes.friendlyName[0], 'encryptionkey');
ASSERT.equal(p12.safeContents[0].safeBags[0].attributes.localKeyId.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[0].attributes.localKeyId[0], 'Time 1311855238964');
ASSERT.equal(p12.safeContents[0].safeBags[1].type, PKI.oids.pkcs8ShroudedKeyBag);
ASSERT.equal(p12.safeContents[0].safeBags[1].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[1].attributes.friendlyName[0], 'signaturekey');
ASSERT.equal(p12.safeContents[0].safeBags[1].attributes.localKeyId.length, 1);
ASSERT.equal(p12.safeContents[0].safeBags[1].attributes.localKeyId[0], 'Time 1311855238863');
ASSERT.equal(p12.safeContents[1].encrypted, true);
ASSERT.equal(p12.safeContents[1].safeBags.length, 6);
ASSERT.equal(p12.safeContents[1].safeBags[0].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[0].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[0].attributes.friendlyName[0], 'CN=1002753325,2.5.4.5=#130b3130303237353333323543');
ASSERT.equal(p12.safeContents[1].safeBags[0].attributes.localKeyId.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[0].attributes.localKeyId[0], 'Time 1311855238964');
ASSERT.equal(p12.safeContents[1].safeBags[1].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[1].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[1].attributes.friendlyName[0], 'CN=ElsterSoftTestCA,OU=CA,O=Elster,C=DE');
ASSERT.equal(p12.safeContents[1].safeBags[2].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[2].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[2].attributes.friendlyName[0], 'CN=ElsterRootCA,OU=RootCA,O=Elster,C=DE');
ASSERT.equal(p12.safeContents[1].safeBags[3].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[3].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[3].attributes.friendlyName[0], 'CN=1002753325,2.5.4.5=#130b3130303237353333323541');
ASSERT.equal(p12.safeContents[1].safeBags[3].attributes.localKeyId.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[3].attributes.localKeyId[0], 'Time 1311855238863');
ASSERT.equal(p12.safeContents[1].safeBags[4].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[4].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[4].attributes.friendlyName[0], 'CN=ElsterSoftTestCA,OU=CA,O=Elster,C=DE');
ASSERT.equal(p12.safeContents[1].safeBags[5].type, PKI.oids.certBag);
ASSERT.equal(p12.safeContents[1].safeBags[5].attributes.friendlyName.length, 1);
ASSERT.equal(p12.safeContents[1].safeBags[5].attributes.friendlyName[0], 'CN=ElsterRootCA,OU=RootCA,O=Elster,C=DE');
});
it('should get bags by friendly name', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
var bags = p12.getBags({friendlyName: 'signaturekey'});
ASSERT.equal(bags.friendlyName.length, 1);
ASSERT.equal(bags.friendlyName[0].attributes.friendlyName[0], 'signaturekey');
});
it('should get cert bags by friendly name', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
var bags = p12.getBags({
friendlyName: 'CN=1002753325,2.5.4.5=#130b3130303237353333323543',
bagType: PKI.oids.certBag
});
ASSERT.equal(bags.friendlyName.length, 1);
ASSERT.equal(bags.friendlyName[0].attributes.friendlyName[0], 'CN=1002753325,2.5.4.5=#130b3130303237353333323543');
});
it('should get all cert bags', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
var bags = p12.getBags({
bagType: PKI.oids.certBag
});
ASSERT.equal(bags[PKI.oids.certBag].length, 6);
for(var i = 0; i < bags[PKI.oids.certBag].length; ++i) {
ASSERT.equal(bags[PKI.oids.certBag][i].type, PKI.oids.certBag);
}
});
it('should get bags by local key ID', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
var bags = p12.getBags({localKeyId: 'Time 1311855238863'});
ASSERT.equal(bags.localKeyId.length, 2);
ASSERT.equal(bags.localKeyId[0].attributes.localKeyId[0], 'Time 1311855238863');
ASSERT.equal(bags.localKeyId[1].attributes.localKeyId[0], 'Time 1311855238863');
});
it('should get cert bags by local key ID', function() {
var p12Der = UTIL.decode64(_data.p12encmixed);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123456');
var bags = p12.getBags({
localKeyId: 'Time 1311855238863',
bagType: PKI.oids.certBag
});
ASSERT.equal(bags.localKeyId.length, 1);
ASSERT.equal(bags.localKeyId[0].attributes.localKeyId[0], 'Time 1311855238863');
ASSERT.equal(bags.localKeyId[0].type, PKI.oids.certBag);
});
it('should generate a PKCS#12 mac key', function() {
var salt = 'A15D6AA8F8DAFC352F9EE1C192F09966EB85D17B';
salt = UTIL.createBuffer(UTIL.hexToBytes(salt));
var expected = '03e46727268575c6ebd6bff828d0d09b0c914201263ca543';
var key = PKCS12.generateKey('123456', salt, 1, 1024, 24);
ASSERT.equal(key.toHex(), expected);
});
it('should load a PKCS#12 with an ECDSA key in a certificate (unsupported key format)', function() {
var p12Der = UTIL.decode64(_data.p12ecdsa);
var p12Asn1 = ASN1.fromDer(p12Der);
var p12 = PKCS12.pkcs12FromAsn1(p12Asn1, '123321');
var bags = p12.getBags({bagType: PKI.oids.certBag});
ASSERT.equal(bags[PKI.oids.certBag].length, 1);
var bag = bags[PKI.oids.certBag][0];
ASSERT.equal(bag.cert, null);
ASSERT.equal('asn1' in bag, true);
// convert to ASN.1, then DER, then PEM-encode
var msg = {
type: 'CERTIFICATE',
body: ASN1.toDer(bag.asn1).getBytes()
};
var pem = PEM.encode(msg);
ASSERT.equal(pem, _data.p12ecdsaCert);
});
});
_data = {
certificate: '-----BEGIN CERTIFICATE-----\r\n' +
'MIIDtDCCApwCCQDUVBxA2DXi8zANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC\r\n' +
'REUxEjAQBgNVBAgMCUZyYW5jb25pYTEQMA4GA1UEBwwHQW5zYmFjaDEVMBMGA1UE\r\n' +
'CgwMU3RlZmFuIFNpZWdsMRIwEAYDVQQLDAlHZWllcmxlaW4xFjAUBgNVBAMMDUdl\r\n' +
'aWVybGVpbiBERVYxIzAhBgkqhkiG9w0BCQEWFHN0ZXNpZUBicm9rZW5waXBlLmRl\r\n' +
'MB4XDTEyMDMxODIyNTc0M1oXDTEzMDMxODIyNTc0M1owgZsxCzAJBgNVBAYTAkRF\r\n' +
'MRIwEAYDVQQIDAlGcmFuY29uaWExEDAOBgNVBAcMB0Fuc2JhY2gxFTATBgNVBAoM\r\n' +
'DFN0ZWZhbiBTaWVnbDESMBAGA1UECwwJR2VpZXJsZWluMRYwFAYDVQQDDA1HZWll\r\n' +
'cmxlaW4gREVWMSMwIQYJKoZIhvcNAQkBFhRzdGVzaWVAYnJva2VucGlwZS5kZTCC\r\n' +
'ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMsAbQ4fWevHqP1K1y/ewpMS\r\n' +
'3vYovBto7IsKBq0v3NmC2kPf3NhyaSKfjOOS5uAPONLffLck+iGdOLLFia6OSpM6\r\n' +
'0tyQIV9lHoRh7fOEYORab0Z+aBUZcEGT9yotBOraX1YbKc5f9XO+80eG4XYvb5ua\r\n' +
'1NHrxWqe4w2p3zGJCKO+wHpvGkbKz0nfu36jwWz5aihfHi9hp/xs8mfH86mIKiD7\r\n' +
'f2X2KeZ1PK9RvppA0X3lLb2VLOqMt+FHWicyZ/wjhQZ4oW55ln2yYJUQ+adlgaYn\r\n' +
'PrtnsxmbTxM+99oF0F2/HmGrNs8nLZSva1Vy+hmjmWz6/O8ZxhiIj7oBRqYcAocC\r\n' +
'AwEAATANBgkqhkiG9w0BAQUFAAOCAQEAvfvtu31GFBO5+mFjPAoR4BlzKq/H3EPO\r\n' +
'qS8cm/TjHgDRALwSnwKYCFs/bXqE4iOTD6otV4TusX3EPbqL2vzZQEcZn6paU/oZ\r\n' +
'ZVXwQqMqY5tf2teQiNxqxNmSIEPRHOr2QVBVIx2YF4Po89KGUqJ9u/3/10lDqRwp\r\n' +
'sReijr5UKv5aygEcnwcW8+Ne4rTx934UDsutKG20dr5trZfWQRVS9fS9CFwJehEX\r\n' +
'HAMUc/0++80NhfQthmWZWlWM1R3dr4TrIPtWdn5z0MtGeDvqBk7HjGrhcVS6kAsy\r\n' +
'Z9y/lfLPjBuxlQAHztEJCWgI4TW3/RLhgfg2gI1noM2n84Cdmisfkg==\r\n' +
'-----END CERTIFICATE-----\r\n',
privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIIEowIBAAKCAQEAywBtDh9Z68eo/UrXL97CkxLe9ii8G2jsiwoGrS/c2YLaQ9/c\r\n' +
'2HJpIp+M45Lm4A840t98tyT6IZ04ssWJro5KkzrS3JAhX2UehGHt84Rg5FpvRn5o\r\n' +
'FRlwQZP3Ki0E6tpfVhspzl/1c77zR4bhdi9vm5rU0evFap7jDanfMYkIo77Aem8a\r\n' +
'RsrPSd+7fqPBbPlqKF8eL2Gn/GzyZ8fzqYgqIPt/ZfYp5nU8r1G+mkDRfeUtvZUs\r\n' +
'6oy34UdaJzJn/COFBnihbnmWfbJglRD5p2WBpic+u2ezGZtPEz732gXQXb8eYas2\r\n' +
'zyctlK9rVXL6GaOZbPr87xnGGIiPugFGphwChwIDAQABAoIBAAjMA+3QvfzRsikH\r\n' +
'zTtt09C7yJ2yNjSZ32ZHEPMAV/m1CfBXCyL2EkhF0b0q6IZdIoFA3g6xs4UxYvuc\r\n' +
'Q9Mkp2ap7elQ9aFEqIXkGIOtAOXkZV4QrEH90DeHSfax7LygqfD5TF59Gg3iAHjh\r\n' +
'B3Qvqg58LyzJosx0BjLZYaqr3Yv67GkqyflpF/roPGdClHpahAi5PBkHiNhNTAUU\r\n' +
'LJRGvMegXGZkUKgGMAiGCk0N96OZwrinMKO6YKGdtgwVWC2wbJY0trElaiwXozSt\r\n' +
'NmP6KTQp94C7rcVO6v1lZiOfhBe5Kc8QHUU+GYydgdjqm6Rdow/yLHOALAVtXSeb\r\n' +
'U+tPfcECgYEA6Qi+qF+gtPincEDBxRtoKwAlRkALt8kly8bYiGcUmd116k/5bmPw\r\n' +
'd0tBUOQbqRa1obYC88goOVzp9LInAcBSSrexhVaPAF4nrkwYXMOq+76MiH17WUfQ\r\n' +
'MgVM2IB48PBjNk1s3Crj6j1cxxkctqmCnVaI9HlU2PPZ3xjaklfv/NsCgYEA3wH8\r\n' +
'mehUhiAp7vuhd+hfomFw74cqgHC9v0saiYGckpMafh9MJGc4U5GrN1kYeb/CFkSx\r\n' +
'1hOytD3YBKoaKKoYagaMQcjxf6HnEF0f/5OiQkUQpWmgC9lNnE4XTWjnwqaTS5L9\r\n' +
'D+H50SiI3VjHymGXTRJeKpAIwV74AxxrnVofqsUCgYAwmL1B2adm9g/c7fQ6yatg\r\n' +
'hEhBrSuEaTMzmsUfNPfr2m4zrffjWH4WMqBtYRSPn4fDMHTPJ+eThtfXSqutxtCi\r\n' +
'ekpP9ywdNIVr6LyP49Ita6Bc+mYVyU8Wj1pmL+yIumjGM0FHbL5Y4/EMKCV/xjvR\r\n' +
'2fD3orHaCIhf6QvzxtjqTwKBgFm6UemXKlMhI94tTsWRMNGEBU3LA9XUBvSuAkpr\r\n' +
'ZRUwrQssCpXnFinBxbMqXQe3mR8emrM5D8En1P/jdU0BS3t1kP9zG4AwI2lZHuPV\r\n' +
'ggbKBS2Y9zVtRKXsYcHawM13+nIA/WNjmAGJHrB45UJPy/HNvye+9lbfoEiYKdCR\r\n' +
'D4bFAoGBAIm9jcZkIwLa9kLAWH995YYYSGRY4KC29XZr2io2mog+BAjhFt1sqebt\r\n' +
'R8sRHNiIP2mcUECMOcaS+tcayi+8KTHWxIEed9qDmFu6XBbePfe/L6yxPSagcixH\r\n' +
'BK0KuK/fgTPvZCmIs8hUIC+AxhXKnqn4fIWoO54xLsALc0gEjs2d\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
p12certonly:
'MIIEHgIBAzCCBBcGCSqGSIb3DQEHAaCCBAgEggQEMIIEADCCA/wGCSqGSIb3DQEH\r\n' +
'AaCCA+0EggPpMIID5TCCA+EGCyqGSIb3DQEMCgEDoIID0DCCA8wGCiqGSIb3DQEJ\r\n' +
'FgGgggO8BIIDuDCCA7QwggKcAgkA1FQcQNg14vMwDQYJKoZIhvcNAQEFBQAwgZsx\r\n' +
'CzAJBgNVBAYTAkRFMRIwEAYDVQQIDAlGcmFuY29uaWExEDAOBgNVBAcMB0Fuc2Jh\r\n' +
'Y2gxFTATBgNVBAoMDFN0ZWZhbiBTaWVnbDESMBAGA1UECwwJR2VpZXJsZWluMRYw\r\n' +
'FAYDVQQDDA1HZWllcmxlaW4gREVWMSMwIQYJKoZIhvcNAQkBFhRzdGVzaWVAYnJv\r\n' +
'a2VucGlwZS5kZTAeFw0xMjAzMTgyMjU3NDNaFw0xMzAzMTgyMjU3NDNaMIGbMQsw\r\n' +
'CQYDVQQGEwJERTESMBAGA1UECAwJRnJhbmNvbmlhMRAwDgYDVQQHDAdBbnNiYWNo\r\n' +
'MRUwEwYDVQQKDAxTdGVmYW4gU2llZ2wxEjAQBgNVBAsMCUdlaWVybGVpbjEWMBQG\r\n' +
'A1UEAwwNR2VpZXJsZWluIERFVjEjMCEGCSqGSIb3DQEJARYUc3Rlc2llQGJyb2tl\r\n' +
'bnBpcGUuZGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLAG0OH1nr\r\n' +
'x6j9Stcv3sKTEt72KLwbaOyLCgatL9zZgtpD39zYcmkin4zjkubgDzjS33y3JPoh\r\n' +
'nTiyxYmujkqTOtLckCFfZR6EYe3zhGDkWm9GfmgVGXBBk/cqLQTq2l9WGynOX/Vz\r\n' +
'vvNHhuF2L2+bmtTR68VqnuMNqd8xiQijvsB6bxpGys9J37t+o8Fs+WooXx4vYaf8\r\n' +
'bPJnx/OpiCog+39l9inmdTyvUb6aQNF95S29lSzqjLfhR1onMmf8I4UGeKFueZZ9\r\n' +
'smCVEPmnZYGmJz67Z7MZm08TPvfaBdBdvx5hqzbPJy2Ur2tVcvoZo5ls+vzvGcYY\r\n' +
'iI+6AUamHAKHAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAL377bt9RhQTufphYzwK\r\n' +
'EeAZcyqvx9xDzqkvHJv04x4A0QC8Ep8CmAhbP216hOIjkw+qLVeE7rF9xD26i9r8\r\n' +
'2UBHGZ+qWlP6GWVV8EKjKmObX9rXkIjcasTZkiBD0Rzq9kFQVSMdmBeD6PPShlKi\r\n' +
'fbv9/9dJQ6kcKbEXoo6+VCr+WsoBHJ8HFvPjXuK08fd+FA7LrShttHa+ba2X1kEV\r\n' +
'UvX0vQhcCXoRFxwDFHP9PvvNDYX0LYZlmVpVjNUd3a+E6yD7VnZ+c9DLRng76gZO\r\n' +
'x4xq4XFUupALMmfcv5Xyz4wbsZUAB87RCQloCOE1t/0S4YH4NoCNZ6DNp/OAnZor\r\n' +
'H5I=',
p12enckeyonly:
'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\r\n' +
'H4/s3xo=',
p12keyonly:
'MIIFEAIBAzCCBQkGCSqGSIb3DQEHAaCCBPoEggT2MIIE8jCCBO4GCSqGSIb3DQEH\r\n' +
'AaCCBN8EggTbMIIE1zCCBNMGCyqGSIb3DQEMCgEBoIIEwjCCBL4CAQAwDQYJKoZI\r\n' +
'hvcNAQEBBQAEggSoMIIEpAIBAAKCAQEAywBtDh9Z68eo/UrXL97CkxLe9ii8G2js\r\n' +
'iwoGrS/c2YLaQ9/c2HJpIp+M45Lm4A840t98tyT6IZ04ssWJro5KkzrS3JAhX2Ue\r\n' +
'hGHt84Rg5FpvRn5oFRlwQZP3Ki0E6tpfVhspzl/1c77zR4bhdi9vm5rU0evFap7j\r\n' +
'DanfMYkIo77Aem8aRsrPSd+7fqPBbPlqKF8eL2Gn/GzyZ8fzqYgqIPt/ZfYp5nU8\r\n' +
'r1G+mkDRfeUtvZUs6oy34UdaJzJn/COFBnihbnmWfbJglRD5p2WBpic+u2ezGZtP\r\n' +
'Ez732gXQXb8eYas2zyctlK9rVXL6GaOZbPr87xnGGIiPugFGphwChwIDAQABAoIB\r\n' +
'AQAIzAPt0L380bIpB807bdPQu8idsjY0md9mRxDzAFf5tQnwVwsi9hJIRdG9KuiG\r\n' +
'XSKBQN4OsbOFMWL7nEPTJKdmqe3pUPWhRKiF5BiDrQDl5GVeEKxB/dA3h0n2sey8\r\n' +
'oKnw+UxefRoN4gB44Qd0L6oOfC8syaLMdAYy2WGqq92L+uxpKsn5aRf66DxnQpR6\r\n' +
'WoQIuTwZB4jYTUwFFCyURrzHoFxmZFCoBjAIhgpNDfejmcK4pzCjumChnbYMFVgt\r\n' +
'sGyWNLaxJWosF6M0rTZj+ik0KfeAu63FTur9ZWYjn4QXuSnPEB1FPhmMnYHY6puk\r\n' +
'XaMP8ixzgCwFbV0nm1PrT33BAoGBAOkIvqhfoLT4p3BAwcUbaCsAJUZAC7fJJcvG\r\n' +
'2IhnFJnddepP+W5j8HdLQVDkG6kWtaG2AvPIKDlc6fSyJwHAUkq3sYVWjwBeJ65M\r\n' +
'GFzDqvu+jIh9e1lH0DIFTNiAePDwYzZNbNwq4+o9XMcZHLapgp1WiPR5VNjz2d8Y\r\n' +
'2pJX7/zbAoGBAN8B/JnoVIYgKe77oXfoX6JhcO+HKoBwvb9LGomBnJKTGn4fTCRn\r\n' +
'OFORqzdZGHm/whZEsdYTsrQ92ASqGiiqGGoGjEHI8X+h5xBdH/+TokJFEKVpoAvZ\r\n' +
'TZxOF01o58Kmk0uS/Q/h+dEoiN1Yx8phl00SXiqQCMFe+AMca51aH6rFAoGAMJi9\r\n' +
'QdmnZvYP3O30OsmrYIRIQa0rhGkzM5rFHzT369puM63341h+FjKgbWEUj5+HwzB0\r\n' +
'zyfnk4bX10qrrcbQonpKT/csHTSFa+i8j+PSLWugXPpmFclPFo9aZi/siLpoxjNB\r\n' +
'R2y+WOPxDCglf8Y70dnw96Kx2giIX+kL88bY6k8CgYBZulHplypTISPeLU7FkTDR\r\n' +
'hAVNywPV1Ab0rgJKa2UVMK0LLAqV5xYpwcWzKl0Ht5kfHpqzOQ/BJ9T/43VNAUt7\r\n' +
'dZD/cxuAMCNpWR7j1YIGygUtmPc1bUSl7GHB2sDNd/pyAP1jY5gBiR6weOVCT8vx\r\n' +
'zb8nvvZW36BImCnQkQ+GxQKBgQCJvY3GZCMC2vZCwFh/feWGGEhkWOCgtvV2a9oq\r\n' +
'NpqIPgQI4RbdbKnm7UfLERzYiD9pnFBAjDnGkvrXGsovvCkx1sSBHnfag5hbulwW\r\n' +
'3j33vy+ssT0moHIsRwStCriv34Ez72QpiLPIVCAvgMYVyp6p+HyFqDueMS7AC3NI\r\n' +
'BI7NnQ==',
p12encmixed:
'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',
p12ecdsa: 'MIIEwQIBAzCCBIcGCSqGSIb3DQEHAaCCBHgEggR0MIIEcDCCAy8GCSqGSIb3DQEHBqCCAyAwggMcAgEAMIIDFQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIxn3OksiScggCAggAgIIC6OB2GSW2p7zaoD4FS5+8kVRF8yTPFpNfV49YCQk49DzPEJoa2tKUE8dMh48jKEh3NRm4kemaN+CKZczTPB5xk21P/+PtLWzfFYFS8/wt/UJ+5NEbRHlVkI2GDj4HYwP+7E0ad0qi54UsuyxIeph7046Jag3keqfoKYinAoiEe3mvbWlICKTWj0PpuDQ2gxb7axwOnqsGfNC3J4HivnbcDPNL+/JReC5SgK/xEQpyBc4Fz49YA9qIGC6gQxNiIC9mQvq7M8hKDumYgkFWH25HXWzj6/pBT+4C8kQxkuLi+KWh9KWj8UXc2YaeqMR6MeJUJ7YMNELVGxU+a3ZY8NFkJf4jLAPy76u4JMEbX6meHtfmOAzqaGG6pnfuqZUWRHrTxYGWIWuTkSFfqCsB08McB6HYqEYm7juHqO7lqnIvRwh++TV7F/DJupOcS8sm4Q0+pI/Ug9lex27d/TVfFL2ICRfCVOvOtv65K+6fqNkPDrctQVl/kqS8tkWZoH+yfS/qDzICk9/fnAnO7bl4yiFGYp6ISbjAnki2NnRVdyGPQIO4B51VqqMeVzN3689ppJQZCajgw7afyq1rDt1dCqiD0OdnKXkARZEp2UeIqmMCMhVPRCeY1N+Z8yF8yWUv77SkGlwtMtyvhGYlrM3Wq/rweW6P20DfeSoLu9pU/ZxXe0X9a4ko/lXjKp/+ksJRZJcxWcRDxFRLtrHIWqrzIEdWilN/ld59HP6JU2+fhBkg+waWXd+lxEmIaVw6YY7WVmQT4riC17GGKjzyrNKQp0q4BDRZKJiJm1LSDBkGYUhWTkiHaZnihuwkidnXGaM6RshPu8c7nA29EoyoZjs4Vtj9dxQzwu6RvA+UvO3v+PMxxa0O/UKjU1XPLdhaxnc5KIUQGechjsgCooHQFOQ8hxEZPUQaBnebTRjq0W7Q+DhKv1EyGFWWRNG2cJRx1EDUO+A02nBvLck5DKOdIcJlsKiHWB0/ntCRqtQ7XzCCATkGCSqGSIb3DQEHAaCCASoEggEmMIIBIjCCAR4GCyqGSIb3DQEMCgECoIG0MIGxMBwGCiqGSIb3DQEMAQMwDgQI3Q+0WbOjf/0CAggABIGQhW8EaZfJhr+MTd4xjkUcubSPjzspoLeLtGLxmKxTBnbwBrKJBJ3bzXvU7we7qvvJGhWQfsRSHXEE841WS8I14veJJLWBJfN5V0AYz2aYkoApDQ61/o7mvgaAIn5rQQh20jp0EFXZM1TRqAT17pjBcBTaZ/s0wpUi2dbYqzhIgEYsQFQfHbW576eht5NlND3tMVgwIwYJKoZIhvcNAQkVMRYEFJ6dpRl6qwj5OZg36y8v5EVowEENMDEGCSqGSIb3DQEJFDEkHiIARQBDAEQAUwBBACAAYwBlAHIAdABpAGYAaQBjAGEAdABlMDEwITAJBgUrDgMCGgUABBSMcup2jX5JqMU5lqH8d/A0/kOu+wQI5FJlbGEnxF4CAggA',
p12ecdsaCert: '-----BEGIN CERTIFICATE-----\r\n' +
'MIICVzCCAf6gAwIBAgIJAO8k1Go1w/58MAkGByqGSM49BAEwgYgxCzAJBgNVBAYT\r\n' +
'AkZSMQ4wDAYDVQQIDAVwYXJpczEMMAoGA1UEBwwDSWxlMQ0wCwYDVQQKDARlcmRm\r\n' +
'MSIwIAYDVQQDDBluaXphci5hYmRlbm5lYmlAZ21haWwuY29tMSgwJgYJKoZIhvcN\r\n' +
'AQkBFhluaXphci5hYmRlbm5lYmlAZ21haWwuY29tMB4XDTE0MDczMDE2MTYyMloX\r\n' +
'DTE1MDczMDE2MTYyMlowgYgxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVwYXJpczEM\r\n' +
'MAoGA1UEBwwDSWxlMQ0wCwYDVQQKDARlcmRmMSIwIAYDVQQDDBluaXphci5hYmRl\r\n' +
'bm5lYmlAZ21haWwuY29tMSgwJgYJKoZIhvcNAQkBFhluaXphci5hYmRlbm5lYmlA\r\n' +
'Z21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELqy3xekJMWlXzq5g\r\n' +
'5ao7Z8PH3iL0I2Tj28SGrDIdZ07f5x/rAbwjbcfp2YsJecEJOoaE3/jgbI8/mc1p\r\n' +
'wWJtm6NQME4wHQYDVR0OBBYEFINzYXPWdpiaoDaLBiObKSezqjYSMB8GA1UdIwQY\r\n' +
'MBaAFINzYXPWdpiaoDaLBiObKSezqjYSMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0E\r\n' +
'AQNIADBFAiEA9Q+TJyUHEn7lhjEkF1OUb0hEwejAWny+mvqQ0XNHup4CIAeOLjEs\r\n' +
'mthwYiI/c1op4Y+H0xLUp2v8iLWHIDqAZA89\r\n' +
'-----END CERTIFICATE-----\r\n'
};
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/forge'
], function(FORGE) {
Tests(
// Global provided by test harness
ASSERT,
FORGE
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/forge'));
}
})();

View File

@@ -0,0 +1,350 @@
(function() {
function Tests(ASSERT, PKCS7, PKI, AES, DES, UTIL) {
var _pem = {
p7: '-----BEGIN PKCS7-----\r\n' +
'MIICTgYJKoZIhvcNAQcDoIICPzCCAjsCAQAxggHGMIIBwgIBADCBqTCBmzELMAkG\r\n' +
'A1UEBhMCREUxEjAQBgNVBAgMCUZyYW5jb25pYTEQMA4GA1UEBwwHQW5zYmFjaDEV\r\n' +
'MBMGA1UECgwMU3RlZmFuIFNpZWdsMRIwEAYDVQQLDAlHZWllcmxlaW4xFjAUBgNV\r\n' +
'BAMMDUdlaWVybGVpbiBERVYxIzAhBgkqhkiG9w0BCQEWFHN0ZXNpZUBicm9rZW5w\r\n' +
'aXBlLmRlAgkA1FQcQNg14vMwDQYJKoZIhvcNAQEBBQAEggEAJhWQz5SniCd1w3A8\r\n' +
'uKVZEfc8Tp21I7FMfFqou+UOVsZCq7kcEa9uv2DIj3o7zD8wbLK1fuyFi4SJxTwx\r\n' +
'kR0a6V4bbonIpXPPJ1f615dc4LydAi2tv5w14LJ1Js5XCgGVnkAmQHDaW3EHXB7X\r\n' +
'T4w9PR3+tcS/5YAnWaM6Es38zCKHd7TnHpuakplIkwSK9rBFAyA1g/IyTPI+ktrE\r\n' +
'EHcVuJcz/7eTlF6wJEa2HL8F1TVWuL0p/0GsJP/8y0MYGdCdtr+TIVo//3YGhoBl\r\n' +
'N4tnheFT/jRAzfCZtflDdgAukW24CekrJ1sG2M42p5cKQ5rGFQtzNy/n8EjtUutO\r\n' +
'HD5YITBsBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBmlpfy3WrYj3uWW7+xNEiH\r\n' +
'gEAm2mfSF5xFPLEqqFkvKTM4w8PfhnF0ehmfQNApvoWQRQanNWLCT+Q9GHx6DCFj\r\n' +
'TUHl+53x88BrCl1E7FhYPs92\r\n' +
'-----END PKCS7-----\r\n',
certificate: '-----BEGIN CERTIFICATE-----\r\n' +
'MIIDtDCCApwCCQDUVBxA2DXi8zANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC\r\n' +
'REUxEjAQBgNVBAgMCUZyYW5jb25pYTEQMA4GA1UEBwwHQW5zYmFjaDEVMBMGA1UE\r\n' +
'CgwMU3RlZmFuIFNpZWdsMRIwEAYDVQQLDAlHZWllcmxlaW4xFjAUBgNVBAMMDUdl\r\n' +
'aWVybGVpbiBERVYxIzAhBgkqhkiG9w0BCQEWFHN0ZXNpZUBicm9rZW5waXBlLmRl\r\n' +
'MB4XDTEyMDMxODIyNTc0M1oXDTEzMDMxODIyNTc0M1owgZsxCzAJBgNVBAYTAkRF\r\n' +
'MRIwEAYDVQQIDAlGcmFuY29uaWExEDAOBgNVBAcMB0Fuc2JhY2gxFTATBgNVBAoM\r\n' +
'DFN0ZWZhbiBTaWVnbDESMBAGA1UECwwJR2VpZXJsZWluMRYwFAYDVQQDDA1HZWll\r\n' +
'cmxlaW4gREVWMSMwIQYJKoZIhvcNAQkBFhRzdGVzaWVAYnJva2VucGlwZS5kZTCC\r\n' +
'ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMsAbQ4fWevHqP1K1y/ewpMS\r\n' +
'3vYovBto7IsKBq0v3NmC2kPf3NhyaSKfjOOS5uAPONLffLck+iGdOLLFia6OSpM6\r\n' +
'0tyQIV9lHoRh7fOEYORab0Z+aBUZcEGT9yotBOraX1YbKc5f9XO+80eG4XYvb5ua\r\n' +
'1NHrxWqe4w2p3zGJCKO+wHpvGkbKz0nfu36jwWz5aihfHi9hp/xs8mfH86mIKiD7\r\n' +
'f2X2KeZ1PK9RvppA0X3lLb2VLOqMt+FHWicyZ/wjhQZ4oW55ln2yYJUQ+adlgaYn\r\n' +
'PrtnsxmbTxM+99oF0F2/HmGrNs8nLZSva1Vy+hmjmWz6/O8ZxhiIj7oBRqYcAocC\r\n' +
'AwEAATANBgkqhkiG9w0BAQUFAAOCAQEAvfvtu31GFBO5+mFjPAoR4BlzKq/H3EPO\r\n' +
'qS8cm/TjHgDRALwSnwKYCFs/bXqE4iOTD6otV4TusX3EPbqL2vzZQEcZn6paU/oZ\r\n' +
'ZVXwQqMqY5tf2teQiNxqxNmSIEPRHOr2QVBVIx2YF4Po89KGUqJ9u/3/10lDqRwp\r\n' +
'sReijr5UKv5aygEcnwcW8+Ne4rTx934UDsutKG20dr5trZfWQRVS9fS9CFwJehEX\r\n' +
'HAMUc/0++80NhfQthmWZWlWM1R3dr4TrIPtWdn5z0MtGeDvqBk7HjGrhcVS6kAsy\r\n' +
'Z9y/lfLPjBuxlQAHztEJCWgI4TW3/RLhgfg2gI1noM2n84Cdmisfkg==\r\n' +
'-----END CERTIFICATE-----\r\n',
privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIIEowIBAAKCAQEAywBtDh9Z68eo/UrXL97CkxLe9ii8G2jsiwoGrS/c2YLaQ9/c\r\n' +
'2HJpIp+M45Lm4A840t98tyT6IZ04ssWJro5KkzrS3JAhX2UehGHt84Rg5FpvRn5o\r\n' +
'FRlwQZP3Ki0E6tpfVhspzl/1c77zR4bhdi9vm5rU0evFap7jDanfMYkIo77Aem8a\r\n' +
'RsrPSd+7fqPBbPlqKF8eL2Gn/GzyZ8fzqYgqIPt/ZfYp5nU8r1G+mkDRfeUtvZUs\r\n' +
'6oy34UdaJzJn/COFBnihbnmWfbJglRD5p2WBpic+u2ezGZtPEz732gXQXb8eYas2\r\n' +
'zyctlK9rVXL6GaOZbPr87xnGGIiPugFGphwChwIDAQABAoIBAAjMA+3QvfzRsikH\r\n' +
'zTtt09C7yJ2yNjSZ32ZHEPMAV/m1CfBXCyL2EkhF0b0q6IZdIoFA3g6xs4UxYvuc\r\n' +
'Q9Mkp2ap7elQ9aFEqIXkGIOtAOXkZV4QrEH90DeHSfax7LygqfD5TF59Gg3iAHjh\r\n' +
'B3Qvqg58LyzJosx0BjLZYaqr3Yv67GkqyflpF/roPGdClHpahAi5PBkHiNhNTAUU\r\n' +
'LJRGvMegXGZkUKgGMAiGCk0N96OZwrinMKO6YKGdtgwVWC2wbJY0trElaiwXozSt\r\n' +
'NmP6KTQp94C7rcVO6v1lZiOfhBe5Kc8QHUU+GYydgdjqm6Rdow/yLHOALAVtXSeb\r\n' +
'U+tPfcECgYEA6Qi+qF+gtPincEDBxRtoKwAlRkALt8kly8bYiGcUmd116k/5bmPw\r\n' +
'd0tBUOQbqRa1obYC88goOVzp9LInAcBSSrexhVaPAF4nrkwYXMOq+76MiH17WUfQ\r\n' +
'MgVM2IB48PBjNk1s3Crj6j1cxxkctqmCnVaI9HlU2PPZ3xjaklfv/NsCgYEA3wH8\r\n' +
'mehUhiAp7vuhd+hfomFw74cqgHC9v0saiYGckpMafh9MJGc4U5GrN1kYeb/CFkSx\r\n' +
'1hOytD3YBKoaKKoYagaMQcjxf6HnEF0f/5OiQkUQpWmgC9lNnE4XTWjnwqaTS5L9\r\n' +
'D+H50SiI3VjHymGXTRJeKpAIwV74AxxrnVofqsUCgYAwmL1B2adm9g/c7fQ6yatg\r\n' +
'hEhBrSuEaTMzmsUfNPfr2m4zrffjWH4WMqBtYRSPn4fDMHTPJ+eThtfXSqutxtCi\r\n' +
'ekpP9ywdNIVr6LyP49Ita6Bc+mYVyU8Wj1pmL+yIumjGM0FHbL5Y4/EMKCV/xjvR\r\n' +
'2fD3orHaCIhf6QvzxtjqTwKBgFm6UemXKlMhI94tTsWRMNGEBU3LA9XUBvSuAkpr\r\n' +
'ZRUwrQssCpXnFinBxbMqXQe3mR8emrM5D8En1P/jdU0BS3t1kP9zG4AwI2lZHuPV\r\n' +
'ggbKBS2Y9zVtRKXsYcHawM13+nIA/WNjmAGJHrB45UJPy/HNvye+9lbfoEiYKdCR\r\n' +
'D4bFAoGBAIm9jcZkIwLa9kLAWH995YYYSGRY4KC29XZr2io2mog+BAjhFt1sqebt\r\n' +
'R8sRHNiIP2mcUECMOcaS+tcayi+8KTHWxIEed9qDmFu6XBbePfe/L6yxPSagcixH\r\n' +
'BK0KuK/fgTPvZCmIs8hUIC+AxhXKnqn4fIWoO54xLsALc0gEjs2d\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
encryptedData: '-----BEGIN PKCS7-----\r\n' +
'MIGHBgkqhkiG9w0BBwagejB4AgEAMHMGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQI\r\n' +
'upMFou5X3DWAUAqObuHSlewM0ZtHzWk9MAmtYb7MSb//OBMKVfLCdbmrS5BpKm9J\r\n' +
'gzwiDR5Od7xgfkqasLS2lOdKAvJ5jZjjTpAyrjBKpShqK9gtXDuO0zH+\r\n' +
'-----END PKCS7-----\r\n',
p7IndefiniteLength: '-----BEGIN PKCS7-----\r\n' +
'MIAGCSqGSIb3DQEHA6CAMIACAQAxggHGMIIBwgIBADCBqTCBmzELMAkGA1UEBhMC\r\n' +
'REUxEjAQBgNVBAgMCUZyYW5jb25pYTEQMA4GA1UEBwwHQW5zYmFjaDEVMBMGA1UE\r\n' +
'CgwMU3RlZmFuIFNpZWdsMRIwEAYDVQQLDAlHZWllcmxlaW4xFjAUBgNVBAMMDUdl\r\n' +
'aWVybGVpbiBERVYxIzAhBgkqhkiG9w0BCQEWFHN0ZXNpZUBicm9rZW5waXBlLmRl\r\n' +
'AgkA1FQcQNg14vMwDQYJKoZIhvcNAQEBBQAEggEAlWCH+E25c4jfff+m0eAxxMmE\r\n' +
'WWaftdsk4ZpAVAr7HsvxJ35bj1mhwTh7rBTg929JBKt6ZaQ4I800jCNxD2O40V6z\r\n' +
'lB7JNRqzgBwfeuU2nV6FB7v1984NBi1jQx6EfxOcusE6RL/63HqJdFbmq3Tl55gF\r\n' +
'dm3JdjmHbCXqwPhuwOXU4yhkpV1RJcrYhPLe3OrLAH7ZfoE0nPJPOX9HPTZ6ReES\r\n' +
'NToS7I9D9k7rCa8fAP7pgjO96GJGBtCHG1VXB9NX4w+xRDbgVPOeHXqqxwZhqpW2\r\n' +
'usBU4+B+MnFLjquOPoySXFfdJFwTP61TPClUdyIne5FFP6EYf98mdtnkjxHo1TCA\r\n' +
'BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECFNtpqBmU3M9oIAESM+yyQLkreETS0Kc\r\n' +
'o01yl6dqqNBczH5FNTK88ypz38/jzjo47+DURlvGzjHJibiDsCz9KyiVmgbRrtvH\r\n' +
'08rfnMbrU+grCkkx9wQI1GnLrYhr87oAAAAAAAAAAAAA\r\n' +
'-----END PKCS7-----\r\n',
p73des: '-----BEGIN PKCS7-----\r\n' +
'MIICTQYJKoZIhvcNAQcDoIICPjCCAjoCAQAxggHGMIIBwgIBADCBqTCBmzELMAkG\r\n' +
'A1UEBhMCREUxEjAQBgNVBAgMCUZyYW5jb25pYTEQMA4GA1UEBwwHQW5zYmFjaDEV\r\n' +
'MBMGA1UECgwMU3RlZmFuIFNpZWdsMRIwEAYDVQQLDAlHZWllcmxlaW4xFjAUBgNV\r\n' +
'BAMMDUdlaWVybGVpbiBERVYxIzAhBgkqhkiG9w0BCQEWFHN0ZXNpZUBicm9rZW5w\r\n' +
'aXBlLmRlAgkA1FQcQNg14vMwDQYJKoZIhvcNAQEBBQAEggEAS6K+sQvdKcK6YafJ\r\n' +
'maDPjBzyjf5jtBgVrFgBXTCRIp/Z2zAXa70skfxhbwTgmilYTacA7jPGRrnLmvBc\r\n' +
'BjhyCKM3dRUyYgh1K1ka0w1prvLmRk6Onf5df1ZQn3AJMIujJZcCOhbV1ByLInve\r\n' +
'xn02KNHstGmdHM/JGyPCp+iYGprhUozVSpNCKS+R33EbsT0sAxamfqdAblT9+5Qj\r\n' +
'4CABvW11a1clPV7STwBbAKbZaLs8mDeoWP0yHvBtJ7qzZdSgJJA2oU7SDv4icwEe\r\n' +
'Ahccbe2HWkLRw8G5YG9XcWx5PnQQhhnXMxkLoSMIYxItyL/cRORbpDohd+otAo66\r\n' +
'WLH1ODBrBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECD5EWJMv1fd7gEj1w3WM1KsM\r\n' +
'L8GDk9JoqA8t9v3oXCT0nAMXoNpHZMnv+0UHHVljlSXBTQxwUP5VMY/ddquJ5O3N\r\n' +
'rDEqqJuHB+KPIsW1kxrdplU=\r\n' +
'-----END PKCS7-----\r\n'
};
describe('pkcs7', function() {
it('should import message from PEM', function() {
var p7 = PKCS7.messageFromPem(_pem.p7);
ASSERT.equal(p7.type, PKI.oids.envelopedData);
ASSERT.equal(p7.version, 0);
ASSERT.equal(p7.recipients.length, 1);
ASSERT.equal(p7.recipients[0].version, 0);
ASSERT.equal(p7.recipients[0].serialNumber, '00d4541c40d835e2f3');
// Test converted RDN, which is constructed of seven parts.
ASSERT.equal(p7.recipients[0].issuer.length, 7);
ASSERT.equal(p7.recipients[0].issuer[0].type, '2.5.4.6');
ASSERT.equal(p7.recipients[0].issuer[0].value, 'DE');
ASSERT.equal(p7.recipients[0].issuer[1].type, '2.5.4.8');
ASSERT.equal(p7.recipients[0].issuer[1].value, 'Franconia');
ASSERT.equal(p7.recipients[0].issuer[2].type, '2.5.4.7');
ASSERT.equal(p7.recipients[0].issuer[2].value, 'Ansbach');
ASSERT.equal(p7.recipients[0].issuer[3].type, '2.5.4.10');
ASSERT.equal(p7.recipients[0].issuer[3].value, 'Stefan Siegl');
ASSERT.equal(p7.recipients[0].issuer[4].type, '2.5.4.11');
ASSERT.equal(p7.recipients[0].issuer[4].value, 'Geierlein');
ASSERT.equal(p7.recipients[0].issuer[5].type, '2.5.4.3');
ASSERT.equal(p7.recipients[0].issuer[5].value, 'Geierlein DEV');
ASSERT.equal(p7.recipients[0].issuer[6].type, '1.2.840.113549.1.9.1');
ASSERT.equal(p7.recipients[0].issuer[6].value, 'stesie@brokenpipe.de');
ASSERT.equal(p7.recipients[0].encryptedContent.algorithm, PKI.oids.rsaEncryption);
ASSERT.equal(p7.recipients[0].encryptedContent.content.length, 256);
ASSERT.equal(p7.encryptedContent.algorithm, PKI.oids['aes256-CBC']);
ASSERT.equal(p7.encryptedContent.parameter.data.length, 16); // IV
});
it('should import indefinite length message from PEM', function() {
ASSERT.doesNotThrow(function() {
var p7 = PKCS7.messageFromPem(_pem.p7IndefiniteLength);
ASSERT.equal(p7.type, PKI.oids.envelopedData);
ASSERT.equal(p7.encryptedContent.parameter.toHex(), '536da6a06653733d');
ASSERT.equal(p7.encryptedContent.content.length(), 80);
});
});
it('should find recipient by serial number', function() {
var p7 = PKCS7.messageFromPem(_pem.p7);
var cert = PKI.certificateFromPem(_pem.certificate);
var ri = p7.findRecipient(cert);
ASSERT.equal(ri.serialNumber, '00d4541c40d835e2f3');
// modify certificate so it doesn't match recipient any more
cert.serialNumber = '1234567890abcdef42';
ri = p7.findRecipient(cert);
ASSERT.equal(ri, null);
});
it('should aes-decrypt message', function() {
var p7 = PKCS7.messageFromPem(_pem.p7);
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
p7.decrypt(p7.recipients[0], privateKey);
// symmetric key must be 32 bytes long (AES 256 key)
ASSERT.equal(p7.encryptedContent.key.data.length, 32);
ASSERT.equal(
p7.content,
'Today is Boomtime, the 9th day of Discord in the YOLD 3178\r\n');
});
it('should 3des-decrypt message', function() {
var p7 = PKCS7.messageFromPem(_pem.p73des);
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
p7.decrypt(p7.recipients[0], privateKey);
// symmetric key must be 24 bytes long (DES3 key)
ASSERT.equal(p7.encryptedContent.key.data.length, 24);
ASSERT.equal(
p7.content,
'Today is Prickle-Prickle, ' +
'the 16th day of Discord in the YOLD 3178\r\n');
});
it('should add a recipient', function() {
var p7 = PKCS7.createEnvelopedData();
// initially there should be no recipients
ASSERT.equal(p7.recipients.length, 0);
var cert = PKI.certificateFromPem(_pem.certificate);
p7.addRecipient(cert);
ASSERT.equal(p7.recipients.length, 1);
ASSERT.deepEqual(p7.recipients[0].serialNumber, cert.serialNumber);
ASSERT.deepEqual(p7.recipients[0].issuer, cert.subject.attributes);
ASSERT.deepEqual(p7.recipients[0].encryptedContent.key, cert.publicKey);
});
it('should aes-encrypt a message', function() {
var p7 = PKCS7.createEnvelopedData();
var cert = PKI.certificateFromPem(_pem.certificate);
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
p7.addRecipient(cert);
p7.content = UTIL.createBuffer('Just a little test');
// pre-condition, PKCS#7 module should default to AES-256-CBC
ASSERT.equal(p7.encryptedContent.algorithm, PKI.oids['aes256-CBC']);
p7.encrypt();
// since we did not provide a key, a random key should have been created
// automatically, AES256 requires 32 bytes of key material
ASSERT.equal(p7.encryptedContent.key.data.length, 32);
// furthermore an IV must be generated, AES256 has 16 byte IV
ASSERT.equal(p7.encryptedContent.parameter.data.length, 16);
// content is 18 bytes long, AES has 16 byte blocksize,
// with padding that makes 32 bytes
ASSERT.equal(p7.encryptedContent.content.data.length, 32);
// RSA encryption should yield 256 bytes
ASSERT.equal(p7.recipients[0].encryptedContent.content.length, 256);
// rewind Key & IV
p7.encryptedContent.key.read = 0;
p7.encryptedContent.parameter.read = 0;
// decryption of the asym. encrypted data should reveal the symmetric key
var decryptedKey = privateKey.decrypt(
p7.recipients[0].encryptedContent.content);
ASSERT.equal(decryptedKey, p7.encryptedContent.key.data);
// decryption of sym. encrypted data should reveal the content
var ciph = AES.createDecryptionCipher(decryptedKey);
ciph.start(p7.encryptedContent.parameter);
ciph.update(p7.encryptedContent.content);
ciph.finish();
ASSERT.equal(ciph.output, 'Just a little test');
});
it('should 3des-ede-encrypt a message', function() {
var p7 = PKCS7.createEnvelopedData();
var cert = PKI.certificateFromPem(_pem.certificate);
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
p7.addRecipient(cert);
p7.content = UTIL.createBuffer('Just a little test');
p7.encryptedContent.algorithm = PKI.oids['des-EDE3-CBC'];
p7.encrypt();
// since we did not provide a key, a random key should have been created
// automatically, 3DES-EDE requires 24 bytes of key material
ASSERT.equal(p7.encryptedContent.key.data.length, 24);
// furthermore an IV must be generated, DES3 has 8 byte IV
ASSERT.equal(p7.encryptedContent.parameter.data.length, 8);
// content is 18 bytes long, DES has 8 byte blocksize,
// with padding that makes 24 bytes
ASSERT.equal(p7.encryptedContent.content.data.length, 24);
// RSA encryption should yield 256 bytes
ASSERT.equal(p7.recipients[0].encryptedContent.content.length, 256);
// rewind Key & IV
p7.encryptedContent.key.read = 0;
p7.encryptedContent.parameter.read = 0;
// decryption of the asym. encrypted data should reveal the symmetric key
var decryptedKey = privateKey.decrypt(
p7.recipients[0].encryptedContent.content);
ASSERT.equal(decryptedKey, p7.encryptedContent.key.data);
// decryption of sym. encrypted data should reveal the content
var ciph = DES.createDecryptionCipher(decryptedKey);
ciph.start(p7.encryptedContent.parameter);
ciph.update(p7.encryptedContent.content);
ciph.finish();
ASSERT.equal(ciph.output, 'Just a little test');
});
it('should export message to PEM', function() {
var p7 = PKCS7.createEnvelopedData();
p7.addRecipient(PKI.certificateFromPem(_pem.certificate));
p7.content = UTIL.createBuffer('Just a little test');
p7.encrypt();
var pem = PKCS7.messageToPem(p7);
// convert back from PEM to new PKCS#7 object, decrypt, and test
p7 = PKCS7.messageFromPem(pem);
p7.decrypt(p7.recipients[0], PKI.privateKeyFromPem(_pem.privateKey));
ASSERT.equal(p7.content, 'Just a little test');
});
it('should decrypt encrypted data from PEM', function() {
var result = '1f8b08000000000000000b2e494d4bcc5308ce4c4dcfd15130b0b430d4b7343732b03437d05170cc2b4e4a4cced051b034343532d25170492d2d294ecec849cc4b0100bf52f02437000000';
var key = 'b96e4a4c0a3555d31e1b295647cc5cfe74081918cb7f797b';
key = UTIL.createBuffer(UTIL.hexToBytes(key));
ASSERT.doesNotThrow(function() {
var p7 = PKCS7.messageFromPem(_pem.encryptedData);
ASSERT.equal(p7.type, PKI.oids.encryptedData);
ASSERT.equal(p7.encryptedContent.algorithm, PKI.oids['des-EDE3-CBC']);
ASSERT.equal(p7.encryptedContent.parameter.toHex(), 'ba9305a2ee57dc35');
ASSERT.equal(p7.encryptedContent.content.length(), 80);
p7.decrypt(key);
ASSERT.equal(p7.content.toHex(), result);
});
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pkcs7',
'forge/pki',
'forge/aes',
'forge/des',
'forge/util'
], function(PKCS7, PKI, AES, DES, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
PKCS7(),
PKI(),
AES(),
DES(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pkcs7')(),
require('../../js/pki')(),
require('../../js/aes')(),
require('../../js/des')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,70 @@
(function() {
function Tests(ASSERT, RANDOM, UTIL) {
var random = RANDOM();
describe('random', function() {
it('should generate 10 random bytes', function() {
random.getBytes(16);
random.getBytes(24);
random.getBytes(32);
var b = random.getBytes(10);
ASSERT.equal(b.length, 10);
});
it('should use a synchronous seed file', function() {
var rand = RANDOM();
rand.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
var b = rand.getBytes(10);
ASSERT.equal(UTIL.bytesToHex(b), '80a7901a239c3e606319');
});
it('should use an asynchronous seed file', function(done) {
var rand = RANDOM();
rand.seedFile = function(needed, callback) {
callback(null, UTIL.fillString('a', needed));
};
rand.getBytes(10, function(err, b) {
ASSERT.equal(err, null);
ASSERT.equal(UTIL.bytesToHex(b), '80a7901a239c3e606319');
done();
});
});
it('should collect some random bytes', function() {
var rand = RANDOM();
rand.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
rand.collect('bbb');
var b = rand.getBytes(10);
ASSERT.equal(UTIL.bytesToHex(b), 'ff8d213516047c94ca46');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/random',
'forge/util'
], function(RANDOM, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
RANDOM,
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/random'),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,109 @@
(function() {
function Tests(ASSERT, RC2, UTIL) {
describe('rc2', function() {
it('should expand a 128-bit key', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var expect = '71ab26462f0b9333609d4476e48ab72438c2194b70a47085d84b6af1dc72119023b94fe80aee2b6b45f27f923d9be1570da3ce8b16ad7f78db166ffbc28a836a4392cf0b748085dae4b69bdc2a4679cdfc09d84317016987e0c5b765c91dc612b1f44d7921b3e2c46447508bd2ac02e119e0f42a89c719675da320cf3e8958cd';
ASSERT.equal(RC2.expandKey(key).toHex(), expect);
});
it('should expand a 40-bit key', function() {
var key = UTIL.hexToBytes('88bca90e90');
var expect = 'af136d2243b94a0878d7a604f8d6d9fd64a698fd6ebc613e641f0d1612055ef6cb55966db8f32bfd9246dae99880be8a91433adf54ea546d9daad62db7a55f6c7790aa87ba67de0e9ea9128dfc7ccdddd7c47c33d2bb7f823729977f083b5dc1f5bb09000b98e12cdaaf22f80dcc88c37d2c2fd80402f8a30a9e41d356669471';
ASSERT.equal(RC2.expandKey(key, 40).toHex(), expect);
});
it('should rc2-ecb encrypt zeros', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var input = new UTIL.createBuffer().fillWithByte(0, 8);
var cipher = RC2.startEncrypting(key, null, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '2269552ab0f85ca6e35b3b2ce4e02191');
});
it('should rc2-ecb encrypt: vegan', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var input = new UTIL.createBuffer('vegan');
var cipher = RC2.startEncrypting(key, null, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '2194adaf4d517e3a');
});
it('should rc2-ecb decrypt: 2194adaf4d517e3a', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var input = new UTIL.createBuffer(UTIL.hexToBytes('2194adaf4d517e3a'));
var cipher = RC2.startDecrypting(key, null, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output.getBytes(), 'vegan');
});
it('should rc2-cbc encrypt: revolution', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var iv = new UTIL.createBuffer(UTIL.hexToBytes('0123456789abcdef'));
var input = new UTIL.createBuffer('revolution');
var cipher = RC2.startEncrypting(key, iv, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '50cfd16e0fd7f20b17a622eb2a469b7e');
});
it('should rc2-cbc decrypt: 50cfd16e0fd7f20b17a622eb2a469b7e', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var iv = new UTIL.createBuffer(UTIL.hexToBytes('0123456789abcdef'));
var input = new UTIL.createBuffer(
UTIL.hexToBytes('50cfd16e0fd7f20b17a622eb2a469b7e'));
var cipher = RC2.startDecrypting(key, iv, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output, 'revolution');
});
it('should rc2-cbc encrypt w/binary string iv: revolution', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var iv = UTIL.hexToBytes('0123456789abcdef');
var input = new UTIL.createBuffer('revolution');
var cipher = RC2.startEncrypting(key, iv, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output.toHex(), '50cfd16e0fd7f20b17a622eb2a469b7e');
});
it('should rc2-cbc decrypt w/binary string iv: 50cfd16e0fd7f20b17a622eb2a469b7e', function() {
var key = UTIL.hexToBytes('88bca90e90875a7f0f79c384627bafb2');
var iv = UTIL.hexToBytes('0123456789abcdef');
var input = new UTIL.createBuffer(
UTIL.hexToBytes('50cfd16e0fd7f20b17a622eb2a469b7e'));
var cipher = RC2.startDecrypting(key, iv, null);
cipher.update(input);
cipher.finish();
ASSERT.equal(cipher.output, 'revolution');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/rc2',
'forge/util'
], function(RC2, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
RC2(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/rc2')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,602 @@
(function() {
function Tests(ASSERT, PKI, RSA, MD, MGF, PSS, RANDOM, UTIL) {
var _pem = {
privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICXQIBAAKBgQDL0EugUiNGMWscLAVM0VoMdhDZEJOqdsUMpx9U0YZI7szokJqQ\r\n' +
'NIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMGTkP3VF29vXBo+dLq5e+8VyAy\r\n' +
'Q3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGtvnM+z0MYDdKo80efzwIDAQAB\r\n' +
'AoGAIzkGONi5G+JifmXlLJdplom486p3upf4Ce2/7mqfaG9MnkyPSairKD/JXvfh\r\n' +
'NNWkkN8DKKDKBcVVElPgORYT0qwrWc7ueLBMUCbRXb1ZyfEulimG0R3kjUh7NYau\r\n' +
'DaIkVgfykXGSQMZx8FoaT6L080zd+0emKDDYRrb+/kgJNJECQQDoUZoiC2K/DWNY\r\n' +
'h3/ppZ0ane2y4SBmJUHJVMPQ2CEgxsrJTxet668ckNCKaOP/3VFPoWC41f17DvKq\r\n' +
'noYINNntAkEA4JbZBZBVUrQFhHlrpXT4jzqtO2RlKZzEq8qmFZfEErxOT1WMyyCi\r\n' +
'lAQ5gUKardo1Kf0omC8Xq/uO9ZYdED55KwJBALs6cJ65UFaq4oLJiQPzLd7yokuE\r\n' +
'dcj8g71PLBTW6jPxIiMFNA89nz3FU9wIVp+xbMNhSoMMKqIPVPC+m0Rn260CQQDA\r\n' +
'I83fWK/mZWUjBM33a68KumRiH238v8XyQxj7+C8i6D8G2GXvkigFAehAkb7LZZd+\r\n' +
'KLuGFyPlWv3fVWHf99KpAkBQFKk3MRMl6IGJZUEFQe4l5whm8LkGU4acSqv9B3xt\r\n' +
'qROkCrsFrMPqjuuzEmyHoQZ64r2PLJg7FOuyhBnQUOt4\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
privateKeyInfo: '-----BEGIN PRIVATE KEY-----\r\n' +
'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMvQS6BSI0Yxaxws\r\n' +
'BUzRWgx2ENkQk6p2xQynH1TRhkjuzOiQmpA0jCiSJDoSic2dZIyUi/LjoCGeVFif\r\n' +
'57N5N5Tt4wZOQ/dUXb29cGj50url77xXIDJDcXMzXAji2ziFEAIXzDqarKBdDuL9\r\n' +
'IO7z+tepEa2+cz7PQxgN0qjzR5/PAgMBAAECgYAjOQY42Lkb4mJ+ZeUsl2mWibjz\r\n' +
'qne6l/gJ7b/uap9ob0yeTI9JqKsoP8le9+E01aSQ3wMooMoFxVUSU+A5FhPSrCtZ\r\n' +
'zu54sExQJtFdvVnJ8S6WKYbRHeSNSHs1hq4NoiRWB/KRcZJAxnHwWhpPovTzTN37\r\n' +
'R6YoMNhGtv7+SAk0kQJBAOhRmiILYr8NY1iHf+mlnRqd7bLhIGYlQclUw9DYISDG\r\n' +
'yslPF63rrxyQ0Ipo4//dUU+hYLjV/XsO8qqehgg02e0CQQDgltkFkFVStAWEeWul\r\n' +
'dPiPOq07ZGUpnMSryqYVl8QSvE5PVYzLIKKUBDmBQpqt2jUp/SiYLxer+471lh0Q\r\n' +
'PnkrAkEAuzpwnrlQVqrigsmJA/Mt3vKiS4R1yPyDvU8sFNbqM/EiIwU0Dz2fPcVT\r\n' +
'3AhWn7Fsw2FKgwwqog9U8L6bRGfbrQJBAMAjzd9Yr+ZlZSMEzfdrrwq6ZGIfbfy/\r\n' +
'xfJDGPv4LyLoPwbYZe+SKAUB6ECRvstll34ou4YXI+Va/d9VYd/30qkCQFAUqTcx\r\n' +
'EyXogYllQQVB7iXnCGbwuQZThpxKq/0HfG2pE6QKuwWsw+qO67MSbIehBnrivY8s\r\n' +
'mDsU67KEGdBQ63g=\r\n' +
'-----END PRIVATE KEY-----\r\n',
publicKey: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL0EugUiNGMWscLAVM0VoMdhDZ\r\n' +
'EJOqdsUMpx9U0YZI7szokJqQNIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMG\r\n' +
'TkP3VF29vXBo+dLq5e+8VyAyQ3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGt\r\n' +
'vnM+z0MYDdKo80efzwIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n'
};
var _signature =
'9200ece65cdaed36bcc20b94c65af852e4f88f0b4fe5b249d54665f815992ac4' +
'3a1399e65d938c6a7f16dd39d971a53ca66523209dbbfbcb67afa579dbb0c220' +
'672813d9e6f4818f29b9becbb29da2032c5e422da97e0c39bfb7a2e7d568615a' +
'5073af0337ff215a8e1b2332d668691f4fb731440055420c24ac451dd3c913f4';
describe('rsa', function() {
it('should generate 512 bit key pair', function() {
var pair = RSA.generateKeyPair(512);
ASSERT.equal(PKI.privateKeyToPem(pair.privateKey).indexOf('-----BEGIN RSA PRIVATE KEY-----'), 0);
ASSERT.equal(PKI.publicKeyToPem(pair.publicKey).indexOf('-----BEGIN PUBLIC KEY-----'), 0);
// sign and verify
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = pair.privateKey.sign(md);
ASSERT.ok(pair.publicKey.verify(md.digest().getBytes(), signature));
});
it('should generate the same 512 bit key pair', function() {
var prng = RANDOM.createInstance();
prng.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
var pair = RSA.generateKeyPair(512, {prng: prng});
var pem = {
privateKey: PKI.privateKeyToPem(pair.privateKey),
publicKey: PKI.publicKeyToPem(pair.publicKey)
};
ASSERT.equal(pem.privateKey.indexOf('-----BEGIN RSA PRIVATE KEY-----'), 0);
ASSERT.equal(pem.publicKey.indexOf('-----BEGIN PUBLIC KEY-----'), 0);
// sign and verify
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = pair.privateKey.sign(md);
ASSERT.ok(pair.publicKey.verify(md.digest().getBytes(), signature));
// create same key pair by using same PRNG
prng = RANDOM.createInstance();
prng.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
var pair2 = RSA.generateKeyPair(512, {prng: prng});
var pem2 = {
privateKey: PKI.privateKeyToPem(pair2.privateKey),
publicKey: PKI.publicKeyToPem(pair2.publicKey)
};
ASSERT.equal(pem.privateKey, pem2.privateKey);
ASSERT.equal(pem.publicKey, pem2.publicKey);
});
it('should convert private key to/from PEM', function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
ASSERT.equal(PKI.privateKeyToPem(privateKey), _pem.privateKey);
});
it('should convert public key to/from PEM', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
ASSERT.equal(PKI.publicKeyToPem(publicKey), _pem.publicKey);
});
it('should convert a PKCS#8 PrivateKeyInfo to/from PEM', function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKeyInfo);
var rsaPrivateKey = PKI.privateKeyToAsn1(privateKey);
var pki = PKI.wrapRsaPrivateKey(rsaPrivateKey);
ASSERT.equal(PKI.privateKeyInfoToPem(pki), _pem.privateKeyInfo);
});
(function() {
var algorithms = ['aes128', 'aes192', 'aes256', '3des', 'des'];
for(var i = 0; i < algorithms.length; ++i) {
var algorithm = algorithms[i];
it('should PKCS#8 encrypt and decrypt private key with ' + algorithm, function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
var encryptedPem = PKI.encryptRsaPrivateKey(
privateKey, 'password', {algorithm: algorithm});
privateKey = PKI.decryptRsaPrivateKey(encryptedPem, 'password');
ASSERT.equal(PKI.privateKeyToPem(privateKey), _pem.privateKey);
});
}
})();
(function() {
var algorithms = ['aes128', 'aes192', 'aes256', '3des', 'des'];
for(var i = 0; i < algorithms.length; ++i) {
var algorithm = algorithms[i];
it('should legacy (OpenSSL style) encrypt and decrypt private key with ' + algorithm, function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
var encryptedPem = PKI.encryptRsaPrivateKey(
privateKey, 'password', {algorithm: algorithm, legacy: true});
privateKey = PKI.decryptRsaPrivateKey(encryptedPem, 'password');
ASSERT.equal(PKI.privateKeyToPem(privateKey), _pem.privateKey);
});
}
})();
it('should verify signature', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = UTIL.hexToBytes(_signature);
ASSERT.ok(publicKey.verify(md.digest().getBytes(), signature));
});
it('should sign and verify', function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = privateKey.sign(md);
ASSERT.ok(publicKey.verify(md.digest().getBytes(), signature));
});
it('should generate missing CRT parameters, sign, and verify', function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
// remove dQ, dP, and qInv
privateKey = RSA.setPrivateKey(
privateKey.n, privateKey.e, privateKey.d,
privateKey.p, privateKey.q);
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = privateKey.sign(md);
ASSERT.ok(publicKey.verify(md.digest().getBytes(), signature));
});
it('should sign and verify with a private key containing only e, n, and d parameters', function() {
var privateKey = PKI.privateKeyFromPem(_pem.privateKey);
// remove all CRT parameters from private key, so that it consists
// only of e, n and d (which make a perfectly valid private key, but its
// operations are slower)
privateKey = RSA.setPrivateKey(
privateKey.n, privateKey.e, privateKey.d);
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var md = MD.sha1.create();
md.update('0123456789abcdef');
var signature = privateKey.sign(md);
ASSERT.ok(publicKey.verify(md.digest().getBytes(), signature));
});
(function() {
var tests = [{
keySize: 1024,
privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICWwIBAAKBgQDCjvkkLWNTeYXqEsqGiVCW/pDt3/qAodNMHcU9gOU2rxeWwiRu\r\n' +
'OhhLqmMxXHLi0oP5Xmg0m7zdOiLMEyzzyRzdp21aqp3k5qtuSDkZcf1prsp1jpYm\r\n' +
'6z9EGpaSHb64BCuUsQGmUPKutd5RERKHGZXtiRuvvIyue7ETq6VjXrOUHQIDAQAB\r\n' +
'AoGAOKeBjTNaVRhyEnNeXkbmHNIMSfiK7aIx8VxJ71r1ZDMgX1oxWZe5M29uaxVM\r\n' +
'rxg2Lgt7tLYVDSa8s0hyMptBuBdy3TJUWruDx85uwCrWnMerCt/iKVBS22fv5vm0\r\n' +
'LEq/4gjgIVTZwgqbVxGsBlKcY2VzxAfYqYzU8EOZBeNhZdECQQDy+PJAPcUN2xOs\r\n' +
'6qy66S91x6y3vMjs900OeX4+bgT4VSVKmLpqRTPizzcL07tT4+Y+pAAOX6VstZvZ\r\n' +
'6iFDL5rPAkEAzP1+gaRczboKoJWKJt0uEMUmztcY9NXJFDmjVLqzKwKjcAoGgIal\r\n' +
'h+uBFT9VJ16QajC7KxTRLlarzmMvspItUwJAeUMNhEpPwm6ID1DADDi82wdgiALM\r\n' +
'NJfn+UVhYD8Ac//qsKQwxUDseFH6owh1AZVIIBMxg/rwUKUCt2tGVoW3uQJAIt6M\r\n' +
'Aml/D8+xtxc45NuC1n9y1oRoTl1/Ut1rFyKbD5nnS0upR3uf9LruvjqDtaq0Thvz\r\n' +
'+qQT4RoFJ5pfprSO2QJAdMkfNWRqECfAhZyQuUrapeWU3eQ0wjvktIynCIwiBDd2\r\n' +
'MfjmVXzBJhMk6dtINt+vBEITVQEOdtyTgDt0y3n2Lw==\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKeyPem: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCjvkkLWNTeYXqEsqGiVCW/pDt\r\n' +
'3/qAodNMHcU9gOU2rxeWwiRuOhhLqmMxXHLi0oP5Xmg0m7zdOiLMEyzzyRzdp21a\r\n' +
'qp3k5qtuSDkZcf1prsp1jpYm6z9EGpaSHb64BCuUsQGmUPKutd5RERKHGZXtiRuv\r\n' +
'vIyue7ETq6VjXrOUHQIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n',
encrypted: 'jsej3OoacmJ1VjWrlw68F+drnQORAuKAqVu6RMbz1xSXjzA355vctrJZXolRU0mvzuu/6VuNynkKGGyRJ6DHt85CvwTMChw4tOMV4Dy6bgnUt3j+DZA2sWTwFhOlpzvNQMK70QpuqrXtOZmAO59EwoDeJkW/iH6t4YzNOVYo9Jg=',
signature: 'GT0/3EV2zrXxPd1ydijJq3R7lkI4c0GtcprgpG04dSECv/xyXtikuzivxv7XzUdHpu6QiYmM0xE4D4i7LK3Mzy+f7aB4o/dg8XXO3htLiBzVI+ZJCRh06RdYctPtclAWmyZikZ8Etw3NnA/ldKuG4jApbwRb21UFm5gYLrJ4SP4=',
signaturePss: 'F4xffaANDBjhFxeSJx8ANuBbdhaWZjUHRQh4ueYQMPPCaR2mpwdqxE04sbgNgIiZzBuLIAI4HpTMMoDk3Rruhjefx3+9UhzTxgB0hRI+KzRChRs+ToltWWDZdYzt9T8hfTlELeqT4V8HgjDuteO/IAvIVlRIBwMNv53Iebu1FY4=',
signatureWithAbcSalt: 'GYA/Zp8G+jqG2Fu7Um+XP7Cr/yaVdzJN8lyt57Lw6gFflia2CPbOVMLyqLzD7fKoE8UD0Rc6DF8k04xhEu60sudw2nxGHeDvpL4M9du0uYra/WSr9kv7xNjAW62NyNerDngHD2J7O8gQ07TZiTXkrfS724vQab5xZL/+FhvisMY=',
signatureWithCustomPrng: 'LzWcUpUYK+URDp72hJbz1GVEp0rG0LHjd+Pdh2w5rfQFbUThbmXDl3X6DUT5UZr5RjUSHtc2usvH+w49XskyIJJO929sUk9EkMJMK/6QAnYYEp5BA+48pdGNNMZyjIbhyl9Y4lInzFPX8XYMM8o+tdSK+hj+dW5OPdnwWbDtR7U='
}, {
keySize: 1025,
privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICXgIBAAKBgQGIkej4PDlAigUh5fbbHp1WXuTHhOdQfAke+LoH0TM4uzn0QmgK\r\n' +
'SJqxzB1COJ5o0DwZw/NR+CNy7NUrly+vmh2YPwsaqN+AsYBF9qsF93oN8/TBtaL/\r\n' +
'GRoRGpDcCglkj1kZnDaWR79NsG8mC0TrvQCkcCLOP0c2Ux1hRbntOetGXwIDAQAB\r\n' +
'AoGBAIaJWsoX+ZcAthmT8jHOICXFh6pJBe0zVPzkSPz82Q0MPSRUzcsYbsuYJD7Z\r\n' +
'oJBTLQW3feANpjhwqe2ydok7y//ONm3Th53Bcu8jLfoatg4KYxNFIwXEO10mPOld\r\n' +
'VuDIGrBkTABe6q2P5PeUKGCKLT6i/u/2OTXTrQiJbQ0gU8thAkEBjqcFivWMXo34\r\n' +
'Cb9/EgfWCCtv9edRMexgvcFMysRsbHJHDK9JjRLobZltwtAv3cY7F3a/Cu1afg+g\r\n' +
'jAzm5E3gowJBAPwYFHTLzaZToxFKNQztWrPsXF6YfqHpPUUIpT4UzL6DhGG0M00U\r\n' +
'qMyhkYRRqmGOSrSovjg2hjM2643MUUWxUxUCQDPkk/khu5L3YglKzyy2rmrD1MAq\r\n' +
'y0v3XCR3TBq89Ows+AizrJxbkLvrk/kfBowU6M5GG9o9SWFNgXWZnFittocCQQDT\r\n' +
'e1P1419DUFi1UX6NuLTlybx3sxBQvf0jY6xUF1jn3ib5XBXJbTJqcIRF78iyjI9J\r\n' +
'XWIugDc20bTsQOJRSAA9AkEBU8kpueHBaiXTikqqlK9wvc2Lp476hgyKVmVyBGye\r\n' +
'9TLTWkTCzDPtManLy47YtXkXnmyazS+DlKFU61XAGEnZfg==\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKeyPem: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQGIkej4PDlAigUh5fbbHp1WXuTH\r\n' +
'hOdQfAke+LoH0TM4uzn0QmgKSJqxzB1COJ5o0DwZw/NR+CNy7NUrly+vmh2YPwsa\r\n' +
'qN+AsYBF9qsF93oN8/TBtaL/GRoRGpDcCglkj1kZnDaWR79NsG8mC0TrvQCkcCLO\r\n' +
'P0c2Ux1hRbntOetGXwIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n',
encrypted: 'AOVeCUN8BOVkZvt4mxyNn/yCYE1MZ40A3e/osh6EvCBcJ09hyYbx7bzKSrdkhRnDyW0pGtgP352CollasllQZ9HlfI2Wy9zKM0aYZZn8OHBA+60Tc3xHHDGznLZqggUKuhoNpj+faVZ1uzb285eTpQQa+4mLUue2svJD4ViM8+ng',
signature: 'AFSx0axDYXlF2rO3ofgUhYSI8ZlIWtJUUZ62PhgdBp9O5zFqMX3DXoiov1e7NenSOz1khvTSMctFWzKP3GU3F0yewe+Yd3UAZE0dM8vAxigSSfAchUkBDmp9OFuszUie63zwWwpG+gXtvyfueZs1RniBvW1ZmXJvS+HFgX4ouzwd',
signaturePss: 'AQvBdhAXDpu+7RpcybMgwuTUk6w+qa08Lcq3G1xHY4kC7ZUzauZd/Jn9e0ePKApDqs7eDNAOV+dQkU2wiH/uBg6VGelzb0hFwcpSLyBW92Vw0q3GlzY7myWn8qnNzasrt110zFflWQa1GiuzH/C8f+Z82/MzlWDxloJIYbq2PRC8',
signatureWithAbcSalt: 'AW4bKnG/0TGvAZgqX5Dk+fXpUNgX7INFelE46d3m+spaMTG5XalY0xP1sxWfaE/+Zl3FmZcfTNtfOCo0eNRO1h1+GZZfp32ZQZmZvkdUG+dUQp318LNzgygrVf/5iIX+QKV5/soSDuAHBzS7yDfMgzJfnXNpFE/zPLOgZIoOIuLq',
signatureWithCustomPrng: 'AVxfCyGC/7Y3kz//eYFEuWQijjR7eR05AM36CwDlLsVkDRtXoeVzz2yTFBdP+i+QgQ73C/I3lLtvXTwfleorvIX9YncVBeGDQXssmULxzqsM3izaLfJXCRAGx9ErL1Az10+fAqPZpq954OVSDqrR/61Q7CsMY7CiQO3nfIIaxgVL'
}, {
keySize: 1031,
privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICXwIBAAKBgWyeKqA2oA4klYrKT9hjjutYQksJNN0cxwaQwIm9AYiLxOsYtT/C\r\n' +
'ovJx5Oy1EvkbYQbfvYsGISUx9bW8yasZkTHR55IbW3+UptvQjTDtdxBQTgQOpsAh\r\n' +
'BJtZYY3OmyH9Sj3F3oB//oyriNoj0QYyfsvlO8UsMmLzpnf6qfZBDHA/9QIDAQAB\r\n' +
'AoGBBj/3ne5muUmbnTfU7lOUNrCGaADonMx6G0ObAJHyk6PPOePbEgcmDyNEk+Y7\r\n' +
'aEAODjIzmttIbvZ39/Qb+o9nDmCSZC9VxiYPP+rjOzPglCDT5ks2Xcjwzd3If6Ya\r\n' +
'Uw6P31Y760OCYeTb4Ib+8zz5q51CkjkdX5Hq/Yu+lZn0Vx7BAkENo83VfL+bwxTm\r\n' +
'V7vR6gXqTD5IuuIGHL3uTmMNNURAP6FQDHu//duipys83iMChcOeXtboE16qYrO0\r\n' +
'9KC0cqL4JQJBB/aYo/auVUGZA6f50YBp0b2slGMk9TBQG0iQefuuSyH4kzKnt2e3\r\n' +
'Q40SBmprcM+DfttWJ11bouec++goXjz+95ECQQyiTWYRxulgKVuyqCYnvpLnTEnR\r\n' +
'0MoYlVTHBriVPkLErYaYCYgse+SNM1+N4p/Thv6KmkUcq/Lmuc5DSRfbl1iBAkEE\r\n' +
'7GKtJQvd7EO1bfpXnARQx+tWhwHHkgpFBBVHReMZ0rQEFhJ5o2c8HZEiZFNvGO2c\r\n' +
'1fErP14zlu2JFZ03vpCI8QJBCQz9HL28VNjafSAF2mon/SNjKablRjoGGKSoSdyA\r\n' +
'DHDZ/LeRsTp2dg8+bSiG1R+vPqw0f/BT+ux295Sy9ocGEM8=\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKeyPem: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgWyeKqA2oA4klYrKT9hjjutYQksJ\r\n' +
'NN0cxwaQwIm9AYiLxOsYtT/CovJx5Oy1EvkbYQbfvYsGISUx9bW8yasZkTHR55Ib\r\n' +
'W3+UptvQjTDtdxBQTgQOpsAhBJtZYY3OmyH9Sj3F3oB//oyriNoj0QYyfsvlO8Us\r\n' +
'MmLzpnf6qfZBDHA/9QIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n',
encrypted: 'ShSS4/fEAkuS6XiQakhOpWp82IXaaCaDNtsndU4uokvriqgCGZyqc+IkIk3eVmZ8bn4vVIRR43ydFuvGgsptVjizOdLGZudph3TJ1clcYEMcCXk4z5HaEu0bx5SW9jmzHhE/z+WV8PB48q7y7C2qtmPmfttG2NMsNLBvkiaDopRO',
signature: 'Z3vYgRdezrWmdA3NC1Uz2CcHRTcE+/C2idGZA1FjUGqFztAHQ31k0QW/F5zuJdKvg8LQU45S3KxW+OQpbGPL98QbzJLhml88mFGe6OinLXJbi7UQWrtXwamc2jMdiXwovSLbXaXy6PX2QW089iC8XuAZftVi3T/IKV0458FQQprg',
signaturePss: 'R6QsK6b3QinIPZPamm/dP0Zndqti1TzAkFTRSZJaRSa1u2zuvZC5QHF4flDjEtHosWeDyxrBE7PHGQZ0b1bHv9qgHGsJCMwaQPj3AWj9fjYmx7b86KM2vHr8q/vqDaa9pTvVRSSwvD6fwoZPc9twQEfdjdDBAiy23yLDzk/zZiwM',
signatureWithAbcSalt: 'Ep9qx4/FPNcWTixWhvL2IAyJR69o5I4MIJi3cMAhDmpuTvAaL/ThQwFWkBPPOPT4Jbumnu6ELjPNjo72wa00e5k64qnZgy1pauBPMlXRlKehRc9UJZ6+xot642z8Qs+rt89OgbYTsvlyr8lzXooUHz/lPpfawYCqd7maRMs8YlYM',
signatureWithCustomPrng: 'NHAwyn2MdM5ez/WbDNbu2A2JNS+cRiWk/zBoh0lg3aq/RsBS0nrYr4AGiC5jt6KWVcN4AIVOomYtX2k+MhLoemN2t2rDj/+LXOeU7kgCAz0q0ED2NFQz7919JU+PuYXMy03qTMfl5jbvStdi/00eQHjJKGEH+xAgrDcED2lrhtCu'
}, {
keySize: 1032,
privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICYQIBAAKBggDPhzn5I3GecxWt5DKbP+VhM2AFNSOL0+VbYEOR1hnlZdLbxGK4\r\n' +
'cPQzMr2qT6dyttJcsgWr3xKobPkz7vsTZzQATSiekm5Js5dGpaj5lrq/x2+WTZvn\r\n' +
'55x9M5Y5dlpusDMKcC3KaIX/axc+MbvPFzo6Eli7JLCWdBg01eKo30knil0CAwEA\r\n' +
'AQKBggCNl/sjFF7SOD1jbt5kdL0hi7cI9o+xOLs1lEGmAEmc7dNnZN/ibhb/06/6\r\n' +
'wuxB5aEz47bg5IvLZMbG+1hNjc26D0J6Y3Ltwrg8f4ZMdDrh4v0DZ8hy/HbEpMrJ\r\n' +
'Td5dk3mtw9FLow10MB5udPLTDKhfDpTcWiObKm2STtFeBk3xeEECQQ6Cx6bZxQJ1\r\n' +
'zCxflV5Xi8BgAQaUKMqygugte+HpOLflL0j1fuZ0rPosUyDOEFkTzOsPxBYYOU8i\r\n' +
'Gzan1GvW3WwRAkEOTTRt849wpgC9xx2pF0IrYEVmv5gEMy3IiRfCNgEoBwpTWVf4\r\n' +
'QFpN3V/9GFz0WQEEYo6OTmkNcC3Of5zbHhu1jQJBBGxXAYQ2KnbP4uLL/DMBdYWO\r\n' +
'Knw1JvxdLPrYXVejI2MoE7xJj2QXajbirAhEMXL4rtpicj22EmoaE4H7HVgkrJEC\r\n' +
'QQq2V5w4AGwvW4TLHXNnYX/eB33z6ujScOuxjGNDUlBqHZja5iKkCUAjnl+UnSPF\r\n' +
'exaOwBrlrpiLOzRer94MylKNAkEBmI58bqfkI5OCGDArAsJ0Ih58V0l1UW35C1SX\r\n' +
'4yDoXSM5A/xQu2BJbXO4jPe3PnDvCVCEyKpbCK6bWbe26Y7zuw==\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKeyPem: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGgMA0GCSqGSIb3DQEBAQUAA4GOADCBigKBggDPhzn5I3GecxWt5DKbP+VhM2AF\r\n' +
'NSOL0+VbYEOR1hnlZdLbxGK4cPQzMr2qT6dyttJcsgWr3xKobPkz7vsTZzQATSie\r\n' +
'km5Js5dGpaj5lrq/x2+WTZvn55x9M5Y5dlpusDMKcC3KaIX/axc+MbvPFzo6Eli7\r\n' +
'JLCWdBg01eKo30knil0CAwEAAQ==\r\n' +
'-----END PUBLIC KEY-----\r\n',
encrypted: 'pKTbv+xgXPDc+wbjsANFu1/WTcmy4aZFKXKnxddHbU5S0Dpdj2OqCACiBwu1oENPMgPAJ27XRbFtKG+eS8tX47mKP2Fo0Bi+BPFtzuQ1bj3zUzTwzjemT+PU+a4Tho/eKjPhm6xrwGAoQH2VEDEpvcYf+SRmGFJpJ/zPUrSxgffj',
signature: 'R9WBFprCfcIC4zY9SmBpEM0E+cr5j4gMn3Ido5mktoR9VBoJqC6eR6lubIPvZZUz9e4yUSYX0squ56Q9Y0yZFQjTHgsrlmhB2YW8kpv4h8P32Oz2TLcMJK9R2tIh9vvyxwBkd/Ml1qG60GnOFUFzxUad9VIlzaF1PFR6EfnkgBUW',
signaturePss: 'v9UBd4XzBxSRz8yhWKjUkFpBX4Fr2G+ImjqbePL4sAZvYw1tWL+aUQpzG8eOyMxxE703VDh9nIZULYI/uIb9HYHQoGYQ3WoUaWqtZg1x8pZP+Ad7ilUWk5ImRl57fTznNQiVdwlkS5Wgheh1yJCES570a4eujiK9OyB0ba4rKIcM',
signatureWithAbcSalt: 'HCm0FI1jE6wQgwwi0ZwPTkGjssxAPtRh6tWXhNd2J2IoJYj9oQMMjCEElnvQFBa/l00sIsw2YV1tKyoTABaSTGV4vlJcDF+K0g/wiAf30TRUZo72DZKDNdyffDlH0wBDkNVW+F6uqdciJqBC6zz+unNh7x+FRwYaY8xhudIPXdyP',
signatureWithCustomPrng: 'AGyN8xu+0yfCR1tyB9mCXcTGb2vdLnsX9ro2Qy5KV6Hw5YMVNltAt65dKR4Y8pfu6D4WUyyJRUtJ8td2ZHYzIVtWY6bG1xFt5rkjTVg4v1tzQgUQq8AHvRE2qLzwDXhazJ1e6Id2Nuxb1uInFyRC6/gLmiPga1WRDEVvFenuIA48'
}];
for(var i = 0; i < tests.length; ++i) {
createTests(tests[i]);
}
it('should ensure maximum message length for a 1024-bit key is exceeded', function() {
/* For PKCS#1 v1.5, the message must be padded with at least eight bytes,
two zero bytes and one byte telling what the block type is. This is 11
extra bytes are added to the message. The test uses a message of 118
bytes.Together with the 11 extra bytes the encryption block needs to be
at least 129 bytes long. This requires a key of 1025-bits. */
var key = PKI.publicKeyFromPem(tests[0].publicKeyPem);
var message = UTIL.createBuffer().fillWithByte(0, 118);
ASSERT.throws(function() {
key.encrypt(message.getBytes());
});
});
it('should ensure maximum message length for a 1025-bit key is not exceeded', function() {
var key = PKI.publicKeyFromPem(tests[1].publicKeyPem);
var message = UTIL.createBuffer().fillWithByte(0, 118);
ASSERT.doesNotThrow(function() {
key.encrypt(message.getBytes());
});
});
/**
* Creates RSA encryption & decryption tests.
*
* Uses different key sizes (1024, 1025, 1031, 1032). The test functions are
* generated from "templates" below, one for each key size to provide sensible
* output.
*
* Key material in was created with OpenSSL using these commands:
*
* openssl genrsa -out rsa_1024_private.pem 1024
* openssl rsa -in rsa_1024_private.pem -out rsa_1024_public.pem \
* -outform PEM -pubout
* echo 'too many secrets' | openssl rsautl -encrypt \
* -inkey rsa_1024_public.pem -pubin -out rsa_1024_encrypted.bin
*
* echo -n 'just testing' | openssl dgst -sha1 -binary > tosign.sha1
* openssl pkeyutl -sign -in tosign.sha1 -inkey rsa_1024_private.pem \
* -out rsa_1024_sig.bin -pkeyopt digest:sha1
* openssl pkeyutl -sign -in tosign.sha1 -inkey rsa_1024_private.pem \
* -out rsa_1024_sigpss.bin -pkeyopt digest:sha1 \
* -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:20
*
* OpenSSL commands for signature verification:
*
* openssl pkeyutl -verify -in tosign.sha1 -sigfile rsa_1024_sig.bin \
* -pubin -inkey rsa_1024_public.pem -pkeyopt digest:sha1
* openssl pkeyutl -verify -in tosign.sha1 -sigfile rsa_1025_sigpss.bin \
* -pubin -inkey rsa_1025_public.pem -pkeyopt digest:sha1 \
* -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:20
*/
function createTests(params) {
var keySize = params.keySize;
it('should rsa encrypt using a ' + keySize + '-bit key', function() {
var message = "it need's to be about 20% cooler"; // it need's better grammar too
/* First step, do public key encryption */
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var data = key.encrypt(message);
/* Second step, use private key decryption to verify successful
encryption. The encrypted message differs every time, since it is
padded with random data. Therefore just rely on the decryption
routine to work, which is tested seperately against an externally
provided encrypted message. */
key = PKI.privateKeyFromPem(params.privateKeyPem);
ASSERT.equal(key.decrypt(data), message);
});
it('should rsa decrypt using a ' + keySize + '-bit key', function() {
var data = UTIL.decode64(params.encrypted);
var key = PKI.privateKeyFromPem(params.privateKeyPem);
ASSERT.equal(key.decrypt(data), 'too many secrets\n');
});
it('should rsa sign using a ' + keySize + '-bit key and PKCS#1 v1.5 padding', function() {
var key = PKI.privateKeyFromPem(params.privateKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
var signature = UTIL.decode64(params.signature);
ASSERT.equal(key.sign(md), signature);
});
it('should verify an rsa signature using a ' + keySize + '-bit key and PKCS#1 v1.5 padding', function() {
var signature = UTIL.decode64(params.signature);
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
ASSERT.equal(key.verify(md.digest().getBytes(), signature), true);
});
/* Note: signatures are *not* deterministic (the point of RSASSA-PSS),
so they can't be compared easily -- instead they are just verified
using the verify() function which is tested against OpenSSL-generated
signatures. */
it('should rsa sign using a ' + keySize + '-bit key and PSS padding', function() {
var privateKey = PKI.privateKeyFromPem(params.privateKeyPem);
var publicKey = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
// create signature
var pss = PSS.create(
MD.sha1.create(), MGF.mgf1.create(MD.sha1.create()), 20);
var signature = privateKey.sign(md, pss);
// verify signature
md.start();
md.update('just testing');
ASSERT.equal(
publicKey.verify(md.digest().getBytes(), signature, pss), true);
});
it('should verify an rsa signature using a ' + keySize + '-bit key and PSS padding', function() {
var signature = UTIL.decode64(params.signaturePss);
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
var pss = PSS.create(
MD.sha1.create(), MGF.mgf1.create(MD.sha1.create()), 20);
ASSERT.equal(
key.verify(md.digest().getBytes(), signature, pss), true);
});
it('should rsa sign using a ' + keySize + '-bit key and PSS padding using pss named-param API', function() {
var privateKey = PKI.privateKeyFromPem(params.privateKeyPem);
var publicKey = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
// create signature
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
saltLength: 20
});
var signature = privateKey.sign(md, pss);
// verify signature
md.start();
md.update('just testing');
ASSERT.equal(
publicKey.verify(md.digest().getBytes(), signature, pss), true);
});
it('should verify an rsa signature using a ' + keySize + '-bit key and PSS padding using pss named-param API', function() {
var signature = UTIL.decode64(params.signaturePss);
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
saltLength: 20
});
ASSERT.equal(
key.verify(md.digest().getBytes(), signature, pss), true);
});
it('should rsa sign using a ' + keySize + '-bit key and PSS padding using salt "abc"', function() {
var privateKey = PKI.privateKeyFromPem(params.privateKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
// create signature
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
salt: UTIL.createBuffer('abc')
});
var signature = privateKey.sign(md, pss);
var b64 = UTIL.encode64(signature);
ASSERT.equal(b64, params.signatureWithAbcSalt);
});
it('should verify an rsa signature using a ' + keySize + '-bit key and PSS padding using salt "abc"', function() {
var signature = UTIL.decode64(params.signatureWithAbcSalt);
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
saltLength: 3
});
ASSERT.equal(
key.verify(md.digest().getBytes(), signature, pss), true);
});
it('should rsa sign using a ' + keySize + '-bit key and PSS padding using custom PRNG', function() {
var prng = RANDOM.createInstance();
prng.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
var privateKey = PKI.privateKeyFromPem(params.privateKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
// create signature
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
saltLength: 20,
prng: prng
});
var signature = privateKey.sign(md, pss);
var b64 = UTIL.encode64(signature);
ASSERT.equal(b64, params.signatureWithCustomPrng);
});
it('should verify an rsa signature using a ' + keySize + '-bit key and PSS padding using custom PRNG', function() {
var prng = RANDOM.createInstance();
prng.seedFileSync = function(needed) {
return UTIL.fillString('a', needed);
};
var signature = UTIL.decode64(params.signatureWithCustomPrng);
var key = PKI.publicKeyFromPem(params.publicKeyPem);
var md = MD.sha1.create();
md.start();
md.update('just testing');
var pss = PSS.create({
md: MD.sha1.create(),
mgf: MGF.mgf1.create(MD.sha1.create()),
saltLength: 20,
prng: prng
});
ASSERT.equal(
key.verify(md.digest().getBytes(), signature, pss), true);
});
}
})();
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pki',
'forge/rsa',
'forge/md',
'forge/mgf',
'forge/pss',
'forge/random',
'forge/util'
], function(PKI, RSA, MD, MGF, PSS, RANDOM, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
PKI(),
RSA(),
MD(),
MGF(),
PSS(),
RANDOM(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pki')(),
require('../../js/rsa')(),
require('../../js/md')(),
require('../../js/mgf')(),
require('../../js/pss')(),
require('../../js/random')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,75 @@
(function() {
function Tests(ASSERT, SHA1, UTIL) {
describe('sha1', function() {
it('should digest the empty string', function() {
var md = SHA1.create();
ASSERT.equal(
md.digest().toHex(), 'da39a3ee5e6b4b0d3255bfef95601890afd80709');
});
it('should digest "abc"', function() {
var md = SHA1.create();
md.update('abc');
ASSERT.equal(
md.digest().toHex(), 'a9993e364706816aba3e25717850c26c9cd0d89d');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA1.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12');
});
it('should digest "c\'\u00e8"', function() {
var md = SHA1.create();
md.update("c\'\u00e8", 'utf8');
ASSERT.equal(
md.digest().toHex(), '98c9a3f804daa73b68a5660d032499a447350c0d');
});
it('should digest "THIS IS A MESSAGE"', function() {
var md = SHA1.create();
md.start();
md.update('THIS IS ');
md.update('A MESSAGE');
// do twice to check continuing digest
ASSERT.equal(
md.digest().toHex(), '5f24f4d6499fd2d44df6c6e94be8b14a796c071d');
ASSERT.equal(
md.digest().toHex(), '5f24f4d6499fd2d44df6c6e94be8b14a796c071d');
});
it('should digest a long message', function() {
// Note: might be too slow on old browsers
var md = SHA1.create();
md.update(UTIL.fillString('a', 1000000));
ASSERT.equal(
md.digest().toHex(), '34aa973cd4c4daa4f61eeb2bdbad27316534016f');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/sha1',
'forge/util'
], function(SHA1, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
SHA1(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/sha1')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,81 @@
(function() {
function Tests(ASSERT, SHA256, UTIL) {
describe('sha256', function() {
it('should digest the empty string', function() {
var md = SHA256.create();
ASSERT.equal(
md.digest().toHex(),
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
});
it('should digest "abc"', function() {
var md = SHA256.create();
md.update('abc');
ASSERT.equal(
md.digest().toHex(),
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA256.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(),
'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592');
});
it('should digest "c\'\u00e8"', function() {
var md = SHA256.create();
md.update("c\'\u00e8", 'utf8');
ASSERT.equal(
md.digest().toHex(),
'1aa15c717afffd312acce2217ce1c2e5dabca53c92165999132ec9ca5decdaca');
});
it('should digest "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"', function() {
var md = SHA256.create();
md.start();
md.update('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');
// do twice to check continuing digest
ASSERT.equal(
md.digest().toHex(),
'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1');
ASSERT.equal(
md.digest().toHex(),
'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1');
});
it('should digest a long message', function() {
// Note: might be too slow on old browsers
var md = SHA256.create();
md.update(UTIL.fillString('a', 1000000));
ASSERT.equal(
md.digest().toHex(),
'cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/sha256',
'forge/util'
], function(SHA256, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
SHA256(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/sha256')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,174 @@
(function() {
function Tests(ASSERT, SHA512, UTIL) {
describe('sha512', function() {
it('should digest the empty string', function() {
var md = SHA512.create();
ASSERT.equal(
md.digest().toHex(),
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e');
});
it('should digest "abc"', function() {
var md = SHA512.create();
md.update('abc');
ASSERT.equal(
md.digest().toHex(),
'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f');
});
it('should digest "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"', function() {
var md = SHA512.create();
md.update('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu');
ASSERT.equal(
md.digest().toHex(),
'8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA512.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(),
'07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6');
});
it('should digest "c\'\u00e8"', function() {
var md = SHA512.create();
md.update("c\'\u00e8", 'utf8');
ASSERT.equal(
md.digest().toHex(),
'9afdc0390dd91e81c63f858d1c6fcd9f949f3fc89dbdaed9e4211505bad63d8e8787797e2e9ea651285eb6954e51c4f0299837c3108cb40f1420bca1d237355c');
});
it('should digest "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"', function() {
var md = SHA512.create();
md.start();
md.update('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');
// do twice to check continuing digest
ASSERT.equal(
md.digest().toHex(),
'204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445');
ASSERT.equal(
md.digest().toHex(),
'204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445');
});
});
SHA384 = SHA512.sha384;
describe('sha384', function() {
it('should digest the empty string', function() {
var md = SHA384.create();
ASSERT.equal(
md.digest().toHex(),
'38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b');
});
it('should digest "abc"', function() {
var md = SHA384.create();
md.update('abc');
ASSERT.equal(
md.digest().toHex(),
'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7');
});
it('should digest "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"', function() {
var md = SHA384.create();
md.update('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu');
ASSERT.equal(
md.digest().toHex(),
'09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA384.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(),
'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1');
});
it('should digest "c\'\u00e8"', function() {
var md = SHA384.create();
md.update("c\'\u00e8", 'utf8');
ASSERT.equal(
md.digest().toHex(),
'382ec8a92d50abf57f7d0f934ff3969d6d354d30c96f1616678a920677867aba49521d2d535c0f285a3c2961c2034ea3');
});
it('should digest "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"', function() {
var md = SHA384.create();
md.start();
md.update('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');
// do twice to check continuing digest
ASSERT.equal(
md.digest().toHex(),
'3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b');
ASSERT.equal(
md.digest().toHex(),
'3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b');
});
});
SHA256 = SHA512.sha256;
describe('sha512/256', function() {
it('should digest the empty string', function() {
var md = SHA256.create();
ASSERT.equal(
md.digest().toHex(),
'c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA256.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(),
'dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d');
});
});
SHA224 = SHA512.sha224;
describe('sha512/224', function() {
it('should digest the empty string', function() {
var md = SHA224.create();
ASSERT.equal(
md.digest().toHex(),
'6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4');
});
it('should digest "The quick brown fox jumps over the lazy dog"', function() {
var md = SHA224.create();
md.update('The quick brown fox jumps over the lazy dog');
ASSERT.equal(
md.digest().toHex(),
'944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/sha512',
'forge/util'
], function(SHA512, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
SHA512(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/sha512')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,193 @@
(function() {
function Tests(ASSERT, forge) {
// Original RSA key generated by openssh
var keystr =
'-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIIEogIBAAKCAQEA301O+LBnd6ngw9i0Pb5iTwlQ1s37ay3DNpisjh+jPDDvaIZq\r\n' +
'PC+44YV7RaR1ib2wEoQfg4DwqVw5wlA2x97Txngb+sJe0yUfmM9vMTxhXWuURVR6\r\n' +
'6DGd8t2eOBN8qDoYlpvdVf8Go5Btrb6NCexUbZtFS1AmumK2zQKxIizgVLK8dx4G\r\n' +
'NYbqxibUxgYHbwRpu8ROrogVrZbMW1cOb4JE+DzG1FvfHSdzkxb9e5ARcsuLxCdP\r\n' +
'ItUMVY8jjgER6b5lK+Nzr57hFdr08RjWGBldNGrCFqDdm+1WkGAHTRrg/i/MD8BU\r\n' +
'8NCFUBpQTSrhALkGqBdGZPN/PrXonXjhcd11awIDAQABAoIBAHGMESUaJnLN2jIc\r\n' +
'RoLDBaBk/0tLEJaOfZ6Mgen/InUf+Q0wlGKobZ2Xz3g5SV9SKm8v6gpnjXjBIcmy\r\n' +
'GjkGEK/yMWAQaEF7thZxHHxv1J65bnrWm2zolgWCNcsT9aZhbFFhTmpFNO4FKhBY\r\n' +
'PcWW+9OESfci+Z57RbL3tHTJVwUZrthtagpFEgVceq18GLSS9N4TWJ8HX1CDxf9R\r\n' +
'4gzEy3+8oC0QONx+bgsWUmzNk9QNNW6yPV5NYZ3SwNLVgw3+6m8WDaqo5FWK7y2f\r\n' +
'pa63DUzXlg5uSYnk4OFVxI6TLpmNQcjigpXnsd1PwcynW0AM83jzIYu0F31ppU61\r\n' +
'8flrqfECgYEA8j/joUve1F4lTt2U34RF+59giZ1r0ME4LafNEgN/ZLMB8ghToSqr\r\n' +
'qzNnJnSppkAKTa2NVZGgJkvqn+qysM1HNm/3ksdUcE5yijgc3E17PNdBJwwNLZfP\r\n' +
'p9jB/ZPaNMduGqltYamOVkbg/qS7O4rcUHstrGGGtJ9fveH+cu87emMCgYEA6/oX\r\n' +
'6A2fW88hw4hZwV2pCk6gumi89vXbKbhnD6j907TW583xIqXYsQBb7x/KGyPf65+k\r\n' +
'Sou9MRyLhRu7qcc8INpSnFsra8ZQosP+ao8tUTq7p7N0H27qG5liTeAAksvk/xnq\r\n' +
'2VdL1YDRpo4tmRD7TAj8uc1sgXqdsBCPrqq4Q1kCgYAHcNjwEmGEymOA+aNh/jEc\r\n' +
'Gngfofs2zUiJdncBD6RxFmJ/6auP7ryZJJoNf1XaqmrmmecWcsOliX1qbg4RCi0e\r\n' +
'ye+jzYWVcYNpJXIVfjfD1aTFq0QYW2pgcHL88/am2l1SalPWxRt/IOw2Rh8OJCTC\r\n' +
'QBZWDiTSFXceYPus0hZUmwKBgCc2FYbfzJ0q3Adrvs5cy9wEmLyg7tVyoQpbs/Rs\r\n' +
'NlFZeWRnWixRtqIi1yPy+lhsK6cxjdE9SyDAB4cExrg9fQZQgO2uUJbGC1wgiUQX\r\n' +
'qoYW5lvFfARFH+2aHTWnhTDfZJvnKJkY4mcF0tCES5tlsPw/eg89zUvunglFlzqE\r\n' +
'771xAoGAdYRG1PIkAzjuh785rc35885dsaXChZx1+7rfZ+AclyisRsmES9UfqL6M\r\n' +
'+SuluaBSWJQUBS7iaHazUeXmy5t+HBjSSLuAOHoZUckwDWD3EM7GHjFlWJOCArI3\r\n' +
'hOYlsXSyl07rApzg/t+HxXcNpLZGJTgRwrRGF2OipUL0VPlTdRc=\r\n' +
'-----END RSA PRIVATE KEY-----\r\n';
var key = forge.pki.privateKeyFromPem(keystr);
describe('ssh', function() {
it('should convert keys to openssh public keys', function() {
var expect =
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfTU74sGd3qeDD2LQ9vmJPCVD' +
'WzftrLcM2mKyOH6M8MO9ohmo8L7jhhXtFpHWJvbAShB+DgPCpXDnCUDbH3tPGeB' +
'v6wl7TJR+Yz28xPGFda5RFVHroMZ3y3Z44E3yoOhiWm91V/wajkG2tvo0J7FRtm' +
'0VLUCa6YrbNArEiLOBUsrx3HgY1hurGJtTGBgdvBGm7xE6uiBWtlsxbVw5vgkT4' +
'PMbUW98dJ3OTFv17kBFyy4vEJ08i1QxVjyOOARHpvmUr43OvnuEV2vTxGNYYGV0' +
'0asIWoN2b7VaQYAdNGuD+L8wPwFTw0IVQGlBNKuEAuQaoF0Zk838+teideOFx3X' +
'Vr A comment';
ASSERT.equal(forge.ssh.publicKeyToOpenSSH(key, 'A comment'), expect);
});
it('should convert keys to putty unencrypted keys', function() {
var expect =
'PuTTY-User-Key-File-2: ssh-rsa\r\n' +
'Encryption: none\r\n' +
'Comment: imported-openssh-key\r\n' +
'Public-Lines: 6\r\n' +
'AAAAB3NzaC1yc2EAAAADAQABAAABAQDfTU74sGd3qeDD2LQ9vmJPCVDWzftrLcM2\r\n' +
'mKyOH6M8MO9ohmo8L7jhhXtFpHWJvbAShB+DgPCpXDnCUDbH3tPGeBv6wl7TJR+Y\r\n' +
'z28xPGFda5RFVHroMZ3y3Z44E3yoOhiWm91V/wajkG2tvo0J7FRtm0VLUCa6YrbN\r\n' +
'ArEiLOBUsrx3HgY1hurGJtTGBgdvBGm7xE6uiBWtlsxbVw5vgkT4PMbUW98dJ3OT\r\n' +
'Fv17kBFyy4vEJ08i1QxVjyOOARHpvmUr43OvnuEV2vTxGNYYGV00asIWoN2b7VaQ\r\n' +
'YAdNGuD+L8wPwFTw0IVQGlBNKuEAuQaoF0Zk838+teideOFx3XVr\r\n' +
'Private-Lines: 14\r\n' +
'AAABAHGMESUaJnLN2jIcRoLDBaBk/0tLEJaOfZ6Mgen/InUf+Q0wlGKobZ2Xz3g5\r\n' +
'SV9SKm8v6gpnjXjBIcmyGjkGEK/yMWAQaEF7thZxHHxv1J65bnrWm2zolgWCNcsT\r\n' +
'9aZhbFFhTmpFNO4FKhBYPcWW+9OESfci+Z57RbL3tHTJVwUZrthtagpFEgVceq18\r\n' +
'GLSS9N4TWJ8HX1CDxf9R4gzEy3+8oC0QONx+bgsWUmzNk9QNNW6yPV5NYZ3SwNLV\r\n' +
'gw3+6m8WDaqo5FWK7y2fpa63DUzXlg5uSYnk4OFVxI6TLpmNQcjigpXnsd1Pwcyn\r\n' +
'W0AM83jzIYu0F31ppU618flrqfEAAACBAPI/46FL3tReJU7dlN+ERfufYImda9DB\r\n' +
'OC2nzRIDf2SzAfIIU6Eqq6szZyZ0qaZACk2tjVWRoCZL6p/qsrDNRzZv95LHVHBO\r\n' +
'coo4HNxNezzXQScMDS2Xz6fYwf2T2jTHbhqpbWGpjlZG4P6kuzuK3FB7LaxhhrSf\r\n' +
'X73h/nLvO3pjAAAAgQDr+hfoDZ9bzyHDiFnBXakKTqC6aLz29dspuGcPqP3TtNbn\r\n' +
'zfEipdixAFvvH8obI9/rn6RKi70xHIuFG7upxzwg2lKcWytrxlCiw/5qjy1ROrun\r\n' +
's3QfbuobmWJN4ACSy+T/GerZV0vVgNGmji2ZEPtMCPy5zWyBep2wEI+uqrhDWQAA\r\n' +
'AIB1hEbU8iQDOO6Hvzmtzfnzzl2xpcKFnHX7ut9n4ByXKKxGyYRL1R+ovoz5K6W5\r\n' +
'oFJYlBQFLuJodrNR5ebLm34cGNJIu4A4ehlRyTANYPcQzsYeMWVYk4ICsjeE5iWx\r\n' +
'dLKXTusCnOD+34fFdw2ktkYlOBHCtEYXY6KlQvRU+VN1Fw==\r\n' +
'Private-MAC: 87fa1011848453317d8e41b00c927e9d17dc334e\r\n';
ASSERT.equal(forge.ssh.privateKeyToPutty(key, '', 'imported-openssh-key'), expect);
});
it('should convert keys to putty encrypted keys', function() {
var expect =
'PuTTY-User-Key-File-2: ssh-rsa\r\n' +
'Encryption: aes256-cbc\r\n' +
'Comment: imported-openssh-key\r\n' +
'Public-Lines: 6\r\n' +
'AAAAB3NzaC1yc2EAAAADAQABAAABAQDfTU74sGd3qeDD2LQ9vmJPCVDWzftrLcM2\r\n' +
'mKyOH6M8MO9ohmo8L7jhhXtFpHWJvbAShB+DgPCpXDnCUDbH3tPGeBv6wl7TJR+Y\r\n' +
'z28xPGFda5RFVHroMZ3y3Z44E3yoOhiWm91V/wajkG2tvo0J7FRtm0VLUCa6YrbN\r\n' +
'ArEiLOBUsrx3HgY1hurGJtTGBgdvBGm7xE6uiBWtlsxbVw5vgkT4PMbUW98dJ3OT\r\n' +
'Fv17kBFyy4vEJ08i1QxVjyOOARHpvmUr43OvnuEV2vTxGNYYGV00asIWoN2b7VaQ\r\n' +
'YAdNGuD+L8wPwFTw0IVQGlBNKuEAuQaoF0Zk838+teideOFx3XVr\r\n' +
'Private-Lines: 14\r\n' +
'EiVwpacmA7mhmGBTPXeIZZPkeRDtb4LOWzI+68cA5oM7UJTpBxh9zsnpAdWg2knP\r\n' +
'snA5gpTSq0CJV9HWb8yAY3R5izflQ493fCbJzuPFTW6RJ2y/D5dUmDWccfMczPNT\r\n' +
'GEDOfslCPe+Yz1h0y0y5NI5WwJowxv3nL9FTlQ9KDVrdoSizkVbTh4CJTrvqIc7c\r\n' +
'sI/HU25OHS8kcIZPiPL8m40ot254rkbPCWrskm9H4n+EC+BwJNtEic9ZQfGPWOVl\r\n' +
't8JxY35mHqGIlfhyVkdts/Rx7kwOHY+GPXDVRnHQZQOkFtVqCFGx8mL83CspIEq0\r\n' +
'V8LaHuvxiadA4OEeR0azuDhfVJXvrUpHd4CPjAzJu4doHm98GJAyrz3mtCyxIguH\r\n' +
'k8zKVJzbNawy5T43l5x9cR6VKzcl6d4V14vphiovxc8DG/J7RHBd4d1y6wxo5ZMY\r\n' +
'qqQ0E6VHtq6auBZjnGzx0P/1lGjpZdxUf4OVTaZ+stCxX5wAH9exF+gdZAlk20Gp\r\n' +
'Atg60boQuolHBiH66dQynyHp+6yuLPLKXy74EO+AEB3HvNK7aIQV8rCD7I7HEa12\r\n' +
'xxqIH4l0FWQKHXNIrK45uo6Hdg1siYp9zU4FFgDcNGOZJsT6+etPp1sgAeBuBR4F\r\n' +
'pnuX1KZzRTbG1kcRrTOjsMh0bKfZAn0+uwyuPBtwEnLziGoCXU+9+XO85zcPF2j1\r\n' +
'Ip5AWAOBI82SKMLu51Dpdz1rwSZOPFWnHxRxfnUiQa9Kc7qBGrMxy1UNECAwMGzp\r\n' +
'ljKesqZvoANo0voiodALXGs7kSpmXjcbHnUUt0SI/QHyajXabIiLHGf6lfvStYLP\r\n' +
'L5bLfswsMqG/2lonYWrPl9YC0WzvfRpbHgpI9G1eLjFFRlaqJ3EpZf5Dy26Z0eh0\r\n' +
'Private-MAC: 23aa5b6e2a411107c59e1e6c3bca06247e3c9627\r\n';
ASSERT.equal(forge.ssh.privateKeyToPutty(key, 'passphrase', 'imported-openssh-key'), expect);
});
it('should convert keys to openssh encrypted private keys', function() {
var expect =
'-----BEGIN RSA PRIVATE KEY-----\n' +
'Proc-Type: 4,ENCRYPTED\n' +
'DEK-Info: AES-128-CBC,2616162F269429AA628E42C3BD5A0027\n' +
'\n' +
'p8+mGWeQxZrRg6OeeFqgEX8sXGGUqWJuK4XhtgRpxAQaSg8bK6m/ahArEonjzgrO\n' +
'XMLow7N0aXqGJzL+n4c4EzL7e4SquzeYZLq0UCs8vbWE5GdTT6BxisWIJqzOaQW3\n' +
'd3OqS2lM5o47cuADMIMp015b0dJn5nwJall20GSI1XnpTUHIJ1oFv7fW/s5g39VD\n' +
'DSVmPzJEMhcTa8BskHrKITV6l+TuivGqrHH0LCYCfQ3IBLiRZrPINQLLkaHR6kis\n' +
'4qvFEMhQGAz0GrifwEob9+FPzDAHHnYTS0kG1jhZ3p92vaUi8sPxyv5ndRXOSZZg\n' +
'vh6Cdrk62myG/rHbsBRrrpa+Ka+BX4ofedwP3SBHPwqBpksYhEF7MxsWKhmHY+d0\n' +
'YINHrj0w+yfw4H3n1+0w4wajlHVUncp7RP8KKMtG3vvvfF1loWpLbyF0s6fgq7p4\n' +
'7kt1LcnRKB3U2IZYfMHuv94+5q0BKfGF6NmRpmgdJojyS2IXZyFaJRqrCa0mKcP9\n' +
'PtDZFPTEy0VeNTL8KqjweEmjK3/JtZPVgXXkPWlFMw3Hc/dtP/l6VssGLk8P/DHD\n' +
'yknagPsfa70iydTvDO+nrtS57DkoUqhMsU3BhCjMzZg+/bo1JgmxQUWT//PoQLSB\n' +
'Z7/F59AfHzZIkWgqfvGRzX3y+G1M1l11dX658iWmN0kZ5MyHU0qwU9hVI6P/fcfk\n' +
'6MQKc/MzPnkjw/knREtYMtHrVsKrDVDizfguGFKFC8FVhhrDOFZUnza0nh6nt1HZ\n' +
'Xk156MhATenWdHBW4Rn3ec1aMOD16k2SRIHd+nyJzx51H3PUdTtXBWqFNGggzoJG\n' +
'99ax3jD6pTLQY3BG146QKQ0csItMTIdwZPAidkzv8VVXC7HaqXk1K1pgfJT6mD4P\n' +
'LaNbuA9r7mNiNoPzwzk0h3BomBTMXZpAyL9Jlre9jTu6lpyN/TkOzHhs/I1/lvKQ\n' +
'Uki7BXv65Jq6RqkTbNc5plxBYggdzLGurr0ZIBDsoN6uXkzaM+fCMlJU8+MgAcBb\n' +
'x88bj8h3t4akPd/WaSsWKeOzB3Uaw3ztYCpwSVv1F+N0u6C6zGo+9VFAQZh1uKvC\n' +
'G9U5hvAG7WEoQ801/fvKj93lqLDhOarPJC8CcfMLwoIqj7zah7TtBYq8VsuF7Fsx\n' +
'dEWNFiXhtFqUhgBMt1tcOXGiXA79NucSVzUBNzrRZKlLDYm2TKKyOqEbG9vF/YxL\n' +
'ZG3TwmcFj0sko2K61ya7FGpKmfPQCJJoi0tIfnW4eIVcyeRpXYi5B2xqvSXcTdUx\n' +
'5y5Vpuu1CzrMZr50b3sSOFjcOXE5211RS8SHpOMWY+JDDB4vF4Dv94fqEIgnFtrR\n' +
'oQgk3DueWb1x09NcJtEZsW6lT3Jw19ursb++XSejFZ9Xu5ED8fbewgGo2w/N5j1H\n' +
'vQEnFkGcL1jLlLqp9PlvPIE4a///wy1y0XbnKMJs+dKxiesKVx1zZ1WDcK2Qgv4r\n' +
'G+RsZzHZuCjUyty1+SMVOYM6+3zW6bjXN58xI3XeSxgE/JaJKjLWBZWx5+eU7b6a\n' +
'04mJDMhnpdLHG97m9p90L1yuudiJfq6ngha41xxv9xLmNatfrtStCrq/DR0KHm0K\n' +
'-----END RSA PRIVATE KEY-----\n';
// Unable to test -- uses a random IV that I can't control
//ASSERT.equal(forge.ssh.rsaPrivateKeyAsOpenSSH(key, 'passphrase'), expect);
});
it('should convert keys to openssh unencrypted private keys', function() {
var expect = keystr;
ASSERT.equal(forge.ssh.privateKeyToOpenSSH(key, ''), expect);
});
it('should get an MD5 SSH fingerprint', function() {
var fp = forge.ssh.getPublicKeyFingerprint(key);
ASSERT.equal(fp.toHex(), '46549abeb89422a0955d4041ae7322ec');
});
it('should get a hex MD5 SSH fingerprint', function() {
var fp = forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex'});
ASSERT.equal(fp, '46549abeb89422a0955d4041ae7322ec');
});
it('should get a hex, colon-delimited MD5 SSH fingerprint', function() {
var fp = forge.ssh.getPublicKeyFingerprint(
key, {encoding: 'hex', delimiter: ':'});
ASSERT.equal(fp, '46:54:9a:be:b8:94:22:a0:95:5d:40:41:ae:73:22:ec');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/forge'
], function(forge) {
Tests(
// Global provided by test harness
ASSERT,
forge
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/forge'));
}
})();

View File

@@ -0,0 +1,191 @@
(function() {
function Tests(ASSERT, forge) {
describe('tls', function() {
it('should test TLS 1.0 PRF', function() {
// Note: This test vector is originally from:
// http://www.imc.org/ietf-tls/mail-archive/msg01589.html
// But that link is now dead.
var secret = forge.util.createBuffer().fillWithByte(0xAB, 48).getBytes();
var seed = forge.util.createBuffer().fillWithByte(0xCD, 64).getBytes();
var bytes = forge.tls.prf_tls1(secret, 'PRF Testvector', seed, 104);
var expect =
'd3d4d1e349b5d515044666d51de32bab258cb521' +
'b6b053463e354832fd976754443bcf9a296519bc' +
'289abcbc1187e4ebd31e602353776c408aafb74c' +
'bc85eff69255f9788faa184cbb957a9819d84a5d' +
'7eb006eb459d3ae8de9810454b8b2d8f1afbc655' +
'a8c9a013';
ASSERT.equal(bytes.toHex(), expect);
});
it('should establish a TLS connection and transfer data', function(done) {
var end = {};
var data = {};
createCertificate('server', data);
createCertificate('client', data);
data.client.connection = {};
data.server.connection = {};
end.client = forge.tls.createConnection({
server: false,
caStore: [data.server.cert],
sessionCache: {},
cipherSuites: [
forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
virtualHost: 'server',
verify: function(c, verified, depth, certs) {
data.client.connection.commonName =
certs[0].subject.getField('CN').value;
data.client.connection.certVerified = verified;
return true;
},
connected: function(c) {
c.prepare('Hello Server');
},
getCertificate: function(c, hint) {
return data.client.cert;
},
getPrivateKey: function(c, cert) {
return data.client.privateKey;
},
tlsDataReady: function(c) {
end.server.process(c.tlsData.getBytes());
},
dataReady: function(c) {
data.client.connection.data = c.data.getBytes();
c.close();
},
closed: function(c) {
ASSERT.equal(data.client.connection.commonName, 'server');
ASSERT.equal(data.client.connection.certVerified, true);
ASSERT.equal(data.client.connection.data, 'Hello Client');
done();
},
error: function(c, error) {
ASSERT.equal(error.message, undefined);
}
});
end.server = forge.tls.createConnection({
server: true,
caStore: [data.client.cert],
sessionCache: {},
cipherSuites: [
forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
connected: function(c) {
},
verifyClient: true,
verify: function(c, verified, depth, certs) {
data.server.connection.commonName =
certs[0].subject.getField('CN').value;
data.server.connection.certVerified = verified;
return true;
},
getCertificate: function(c, hint) {
data.server.connection.certHint = hint[0];
return data.server.cert;
},
getPrivateKey: function(c, cert) {
return data.server.privateKey;
},
tlsDataReady: function(c) {
end.client.process(c.tlsData.getBytes());
},
dataReady: function(c) {
data.server.connection.data = c.data.getBytes();
c.prepare('Hello Client');
c.close();
},
closed: function(c) {
ASSERT.equal(data.server.connection.certHint, 'server');
ASSERT.equal(data.server.connection.commonName, 'client');
ASSERT.equal(data.server.connection.certVerified, true);
ASSERT.equal(data.server.connection.data, 'Hello Server');
},
error: function(c, error) {
ASSERT.equal(error.message, undefined);
}
});
end.client.handshake();
function createCertificate(cn, data) {
var keys = forge.pki.rsa.generateKeyPair(512);
var cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(
cert.validity.notBefore.getFullYear() + 1);
var attrs = [{
name: 'commonName',
value: cn
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([{
name: 'basicConstraints',
cA: true
}, {
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}, {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'https://myuri.com/webid#me'
}]
}]);
cert.sign(keys.privateKey);
data[cn] = {
cert: forge.pki.certificateToPem(cert),
privateKey: forge.pki.privateKeyToPem(keys.privateKey)
};
}
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/forge'
], function(forge) {
Tests(
// Global provided by test harness
ASSERT,
forge
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/forge'));
}
})();

View File

@@ -0,0 +1,406 @@
(function() {
function Tests(ASSERT, UTIL) {
// custom assertion to test array-like objects
function assertArrayEqual(actual, expected) {
ASSERT.equal(actual.length, expected.length);
for (var idx = 0; idx < expected.length; idx++) {
ASSERT.equal(actual[idx], expected[idx]);
}
}
describe('util', function() {
it('should put bytes into a buffer', function() {
var b = UTIL.createBuffer();
b.putByte(1);
b.putByte(2);
b.putByte(3);
b.putByte(4);
b.putInt32(4);
b.putByte(1);
b.putByte(2);
b.putByte(3);
b.putInt32(4294967295);
var hex = b.toHex();
ASSERT.equal(hex, '0102030400000004010203ffffffff');
var bytes = [];
while(b.length() > 0) {
bytes.push(b.getByte());
}
ASSERT.deepEqual(
bytes, [1, 2, 3, 4, 0, 0, 0, 4, 1, 2, 3, 255, 255, 255, 255]);
});
it('should put bytes from an Uint8Array into a buffer', function() {
if(typeof Uint8Array === 'undefined') {
return;
}
var data = [1, 2, 3, 4, 0, 0, 0, 4, 1, 2, 3, 255, 255, 255, 255];
var ab = new Uint8Array(data);
var b = UTIL.createBuffer(ab);
var hex = b.toHex();
ASSERT.equal(hex, '0102030400000004010203ffffffff');
var bytes = [];
while(b.length() > 0) {
bytes.push(b.getByte());
}
ASSERT.deepEqual(bytes, data);
});
it('should convert bytes from hex', function() {
var hex = '0102030400000004010203ffffffff';
var b = UTIL.createBuffer();
b.putBytes(UTIL.hexToBytes(hex));
ASSERT.equal(b.toHex(), hex);
});
it('should put 0 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(0, 8);
ASSERT.equal(b.toHex(), '00');
});
it('should put 0 into a buffer using two\'s complement w/2 bytes', function() {
var b = UTIL.createBuffer();
b.putSignedInt(0, 16);
ASSERT.equal(b.toHex(), '0000');
});
it('should put 127 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(127, 8);
ASSERT.equal(b.toHex(), '7f');
});
it('should put 127 into a buffer using two\'s complement w/2 bytes', function() {
var b = UTIL.createBuffer();
b.putSignedInt(127, 16);
ASSERT.equal(b.toHex(), '007f');
});
it('should put 128 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(128, 16);
ASSERT.equal(b.toHex(), '0080');
});
it('should put 256 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(256, 16);
ASSERT.equal(b.toHex(), '0100');
});
it('should put -128 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(-128, 8);
ASSERT.equal(b.toHex(), '80');
});
it('should put -129 into a buffer using two\'s complement', function() {
var b = UTIL.createBuffer();
b.putSignedInt(-129, 16);
ASSERT.equal(b.toHex(), 'ff7f');
});
it('should get 0 from a buffer using two\'s complement', function() {
var x = 0;
var n = 8;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(x, n), x);
});
it('should get 127 from a buffer using two\'s complement', function() {
var x = 127;
var n = 8;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(n), x);
});
it('should get 128 from a buffer using two\'s complement', function() {
var x = 128;
var n = 16;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(n), x);
});
it('should get 256 from a buffer using two\'s complement', function() {
var x = 256;
var n = 16;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(n), x);
});
it('should get -128 from a buffer using two\'s complement', function() {
var x = -128;
var n = 8;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(n), x);
});
it('should get -129 from a buffer using two\'s complement', function() {
var x = -129;
var n = 16;
var b = UTIL.createBuffer();
b.putSignedInt(x, n);
ASSERT.equal(b.getSignedInt(n), x);
});
it('should base64 encode some bytes', function() {
var s1 = '00010203050607080A0B0C0D0F1011121415161719';
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5';
ASSERT.equal(UTIL.encode64(s1), s2);
});
it('should base64 decode some bytes', function() {
var s1 = '00010203050607080A0B0C0D0F1011121415161719';
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5';
ASSERT.equal(UTIL.decode64(s2), s1);
});
it('should base64 encode some bytes using util.binary.base64', function() {
var s1 = new Uint8Array([
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30,
0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x41,
0x30, 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x46, 0x31,
0x30, 0x31, 0x31, 0x31, 0x32, 0x31, 0x34, 0x31, 0x35,
0x31, 0x36, 0x31, 0x37, 0x31, 0x39]);
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5';
ASSERT.equal(UTIL.binary.base64.encode(s1), s2);
});
it('should base64 encode some odd-length bytes using util.binary.base64', function() {
var s1 = new Uint8Array([
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30,
0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x41,
0x30, 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x46, 0x31,
0x30, 0x31, 0x31, 0x31, 0x32, 0x31, 0x34, 0x31, 0x35,
0x31, 0x36, 0x31, 0x37, 0x31, 0x39, 0x31, 0x41, 0x31,
0x42]);
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5MUExQg==';
ASSERT.equal(UTIL.binary.base64.encode(s1), s2);
});
it('should base64 decode some bytes using util.binary.base64', function() {
var s1 = new Uint8Array([
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30,
0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x41,
0x30, 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x46, 0x31,
0x30, 0x31, 0x31, 0x31, 0x32, 0x31, 0x34, 0x31, 0x35,
0x31, 0x36, 0x31, 0x37, 0x31, 0x39]);
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5';
ASSERT.deepEqual(UTIL.binary.base64.decode(s2), s1);
});
it('should base64 decode some odd-length bytes using util.binary.base64', function() {
var s1 = new Uint8Array([
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30,
0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x41,
0x30, 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x46, 0x31,
0x30, 0x31, 0x31, 0x31, 0x32, 0x31, 0x34, 0x31, 0x35,
0x31, 0x36, 0x31, 0x37, 0x31, 0x39, 0x31, 0x41, 0x31,
0x42]);
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5MUExQg==';
assertArrayEqual(UTIL.binary.base64.decode(s2), s1);
});
it('should convert IPv4 0.0.0.0 textual address to 4-byte address', function() {
var bytes = UTIL.bytesFromIP('0.0.0.0');
var b = UTIL.createBuffer().fillWithByte(0, 4);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv4 127.0.0.1 textual address to 4-byte address', function() {
var bytes = UTIL.bytesFromIP('127.0.0.1');
var b = UTIL.createBuffer();
b.putByte(127);
b.putByte(0);
b.putByte(0);
b.putByte(1);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 :: textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('::');
var b = UTIL.createBuffer().fillWithByte(0, 16);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 ::0 textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('::0');
var b = UTIL.createBuffer().fillWithByte(0, 16);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 0:: textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('0::');
var b = UTIL.createBuffer().fillWithByte(0, 16);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 ::1 textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('::1');
var b = UTIL.createBuffer().fillWithByte(0, 14);
b.putBytes(UTIL.hexToBytes('0001'));
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 1:: textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('1::');
var b = UTIL.createBuffer();
b.putBytes(UTIL.hexToBytes('0001'));
b.fillWithByte(0, 14);
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 1::1 textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('1::1');
var b = UTIL.createBuffer();
b.putBytes(UTIL.hexToBytes('0001'));
b.fillWithByte(0, 12);
b.putBytes(UTIL.hexToBytes('0001'));
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 1::1:0 textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('1::1:0');
var b = UTIL.createBuffer();
b.putBytes(UTIL.hexToBytes('0001'));
b.fillWithByte(0, 10);
b.putBytes(UTIL.hexToBytes('0001'));
b.putBytes(UTIL.hexToBytes('0000'));
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv6 2001:db8:0:1:1:1:1:1 textual address to 16-byte address', function() {
var bytes = UTIL.bytesFromIP('2001:db8:0:1:1:1:1:1');
var b = UTIL.createBuffer();
b.putBytes(UTIL.hexToBytes('2001'));
b.putBytes(UTIL.hexToBytes('0db8'));
b.putBytes(UTIL.hexToBytes('0000'));
b.putBytes(UTIL.hexToBytes('0001'));
b.putBytes(UTIL.hexToBytes('0001'));
b.putBytes(UTIL.hexToBytes('0001'));
b.putBytes(UTIL.hexToBytes('0001'));
b.putBytes(UTIL.hexToBytes('0001'));
ASSERT.equal(bytes, b.getBytes());
});
it('should convert IPv4 0.0.0.0 byte address to textual representation', function() {
var addr = '0.0.0.0';
var bytes = UTIL.createBuffer().fillWithByte(0, 4).getBytes();
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '0.0.0.0');
});
it('should convert IPv4 0.0.0.0 byte address to textual representation', function() {
var addr = '127.0.0.1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '127.0.0.1');
});
it('should convert IPv6 :: byte address to canonical textual representation (RFC 5952)', function() {
var addr = '::';
var bytes = UTIL.createBuffer().fillWithByte(0, 16).getBytes();
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '::');
});
it('should convert IPv6 ::1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '::1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '::1');
});
it('should convert IPv6 1:: byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1::';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::');
});
it('should convert IPv6 0:0:0:0:0:0:0:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '0:0:0:0:0:0:0:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '::1');
});
it('should convert IPv6 1:0:0:0:0:0:0:0 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1:0:0:0:0:0:0:0';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::');
});
it('should convert IPv6 1::1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1::1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::1');
});
it('should convert IPv6 1:0:0:0:0:0:0:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1:0:0:0:0:0:0:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::1');
});
it('should convert IPv6 1:0000:0000:0000:0000:0000:0000:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1:0000:0000:0000:0000:0000:0000:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::1');
});
it('should convert IPv6 1:0:0:1:1:1:0:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1:0:0:1:1:1:0:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1::1:1:1:0:1');
});
it('should convert IPv6 1:0:1:1:1:0:0:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '1:0:1:1:1:0:0:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '1:0:1:1:1::1');
});
it('should convert IPv6 2001:db8:0:1:1:1:1:1 byte address to canonical textual representation (RFC 5952)', function() {
var addr = '2001:db8:0:1:1:1:1:1';
var bytes = UTIL.bytesFromIP(addr);
var addr = UTIL.bytesToIP(bytes);
ASSERT.equal(addr, '2001:db8:0:1:1:1:1:1');
});
});
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/util'
], function(UTIL) {
Tests(
// Global provided by test harness
ASSERT,
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,734 @@
(function() {
function Tests(ASSERT, PKI, MD, UTIL) {
var _pem = {
privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
'MIICXQIBAAKBgQDL0EugUiNGMWscLAVM0VoMdhDZEJOqdsUMpx9U0YZI7szokJqQ\r\n' +
'NIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMGTkP3VF29vXBo+dLq5e+8VyAy\r\n' +
'Q3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGtvnM+z0MYDdKo80efzwIDAQAB\r\n' +
'AoGAIzkGONi5G+JifmXlLJdplom486p3upf4Ce2/7mqfaG9MnkyPSairKD/JXvfh\r\n' +
'NNWkkN8DKKDKBcVVElPgORYT0qwrWc7ueLBMUCbRXb1ZyfEulimG0R3kjUh7NYau\r\n' +
'DaIkVgfykXGSQMZx8FoaT6L080zd+0emKDDYRrb+/kgJNJECQQDoUZoiC2K/DWNY\r\n' +
'h3/ppZ0ane2y4SBmJUHJVMPQ2CEgxsrJTxet668ckNCKaOP/3VFPoWC41f17DvKq\r\n' +
'noYINNntAkEA4JbZBZBVUrQFhHlrpXT4jzqtO2RlKZzEq8qmFZfEErxOT1WMyyCi\r\n' +
'lAQ5gUKardo1Kf0omC8Xq/uO9ZYdED55KwJBALs6cJ65UFaq4oLJiQPzLd7yokuE\r\n' +
'dcj8g71PLBTW6jPxIiMFNA89nz3FU9wIVp+xbMNhSoMMKqIPVPC+m0Rn260CQQDA\r\n' +
'I83fWK/mZWUjBM33a68KumRiH238v8XyQxj7+C8i6D8G2GXvkigFAehAkb7LZZd+\r\n' +
'KLuGFyPlWv3fVWHf99KpAkBQFKk3MRMl6IGJZUEFQe4l5whm8LkGU4acSqv9B3xt\r\n' +
'qROkCrsFrMPqjuuzEmyHoQZ64r2PLJg7FOuyhBnQUOt4\r\n' +
'-----END RSA PRIVATE KEY-----\r\n',
publicKey: '-----BEGIN PUBLIC KEY-----\r\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL0EugUiNGMWscLAVM0VoMdhDZ\r\n' +
'EJOqdsUMpx9U0YZI7szokJqQNIwokiQ6EonNnWSMlIvy46AhnlRYn+ezeTeU7eMG\r\n' +
'TkP3VF29vXBo+dLq5e+8VyAyQ3FzM1wI4ts4hRACF8w6mqygXQ7i/SDu8/rXqRGt\r\n' +
'vnM+z0MYDdKo80efzwIDAQAB\r\n' +
'-----END PUBLIC KEY-----\r\n',
certificate: '-----BEGIN CERTIFICATE-----\r\n' +
'MIIDIjCCAougAwIBAgIJANE2aHSbwpaRMA0GCSqGSIb3DQEBBQUAMGoxCzAJBgNV\r\n' +
'BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEN\r\n' +
'MAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDEVMBMGA1UEAxMMbXlzZXJ2ZXIu\r\n' +
'Y29tMB4XDTEwMDYxOTE3MzYyOFoXDTExMDYxOTE3MzYyOFowajELMAkGA1UEBhMC\r\n' +
'VVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYDVQQHEwpCbGFja3NidXJnMQ0wCwYD\r\n' +
'VQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MRUwEwYDVQQDEwxteXNlcnZlci5jb20w\r\n' +
'gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMvQS6BSI0YxaxwsBUzRWgx2ENkQ\r\n' +
'k6p2xQynH1TRhkjuzOiQmpA0jCiSJDoSic2dZIyUi/LjoCGeVFif57N5N5Tt4wZO\r\n' +
'Q/dUXb29cGj50url77xXIDJDcXMzXAji2ziFEAIXzDqarKBdDuL9IO7z+tepEa2+\r\n' +
'cz7PQxgN0qjzR5/PAgMBAAGjgc8wgcwwHQYDVR0OBBYEFPV1Y+DHXW6bA/r9sv1y\r\n' +
'NJ8jAwMAMIGcBgNVHSMEgZQwgZGAFPV1Y+DHXW6bA/r9sv1yNJ8jAwMAoW6kbDBq\r\n' +
'MQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExEzARBgNVBAcTCkJsYWNr\r\n' +
'c2J1cmcxDTALBgNVBAoTBFRlc3QxDTALBgNVBAsTBFRlc3QxFTATBgNVBAMTDG15\r\n' +
'c2VydmVyLmNvbYIJANE2aHSbwpaRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF\r\n' +
'BQADgYEARdH2KOlJWTC1CS2y/PAvg4uiM31PXMC1hqSdJlnLM1MY4hRfuf9VyTeX\r\n' +
'Y6FdybcyDLSxKn9id+g9229ci9/s9PI+QmD5vXd8yZyScLc2JkYB4GC6+9D1+/+x\r\n' +
's2hzMxuK6kzZlP+0l9LGcraMQPGRydjCARZZm4Uegln9rh85XFQ=\r\n' +
'-----END CERTIFICATE-----\r\n'
};
describe('x509', function() {
it('should convert certificate to/from PEM', function() {
var certificate = PKI.certificateFromPem(_pem.certificate);
ASSERT.equal(PKI.certificateToPem(certificate), _pem.certificate);
});
it('should verify self-signed certificate', function() {
var certificate = PKI.certificateFromPem(_pem.certificate);
ASSERT.ok(certificate.verify(certificate));
});
it('should generate and verify a self-signed certificate', function() {
var keys = {
privateKey: PKI.privateKeyFromPem(_pem.privateKey),
publicKey: PKI.publicKeyFromPem(_pem.publicKey)
};
var attrs = [{
name: 'commonName',
value: 'example.org'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var cert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: attrs,
issuer: attrs,
isCA: true
});
var pem = PKI.certificateToPem(cert);
cert = PKI.certificateFromPem(pem);
// verify certificate chain
var caStore = PKI.createCaStore();
caStore.addCertificate(cert);
PKI.verifyCertificateChain(caStore, [cert], function(vfd, depth, chain) {
ASSERT.equal(vfd, true);
ASSERT.ok(cert.verifySubjectKeyIdentifier());
return true;
});
});
it('should generate and fail to verify a self-signed certificate that is not in the CA store', function() {
var keys = {
privateKey: PKI.privateKeyFromPem(_pem.privateKey),
publicKey: PKI.publicKeyFromPem(_pem.publicKey)
};
var attrs = [{
name: 'commonName',
value: 'example.org'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var cert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: attrs,
issuer: attrs,
isCA: true
});
var pem = PKI.certificateToPem(cert);
cert = PKI.certificateFromPem(pem);
// verify certificate chain
var caStore = PKI.createCaStore();
PKI.verifyCertificateChain(caStore, [cert], function(vfd, depth, chain) {
ASSERT.equal(vfd, PKI.certificateError.unknown_ca);
return true;
});
});
it('should verify certificate chain ending with intermediate certificate from CA store', function() {
var keys = {
privateKey: PKI.privateKeyFromPem(_pem.privateKey),
publicKey: PKI.publicKeyFromPem(_pem.publicKey)
};
var entity = [{
name: 'commonName',
value: 'example.org'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var intermediate = [{
name: 'commonName',
value: 'intermediate'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var root = [{
name: 'commonName',
value: 'root'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var intermediateCert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: intermediate,
issuer: root,
isCA: true
});
var entityCert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: entity,
issuer: intermediate,
isCA: false
});
// verify certificate chain
var caStore = PKI.createCaStore();
caStore.addCertificate(intermediateCert);
var chain = [entityCert, intermediateCert];
PKI.verifyCertificateChain(caStore, chain, function(vfd, depth, chain) {
ASSERT.equal(vfd, true);
return true;
});
});
it('should fail to verify certificate chain ending with non-CA intermediate certificate from CA store', function() {
var keys = {
privateKey: PKI.privateKeyFromPem(_pem.privateKey),
publicKey: PKI.publicKeyFromPem(_pem.publicKey)
};
var entity = [{
name: 'commonName',
value: 'example.org'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var intermediate = [{
name: 'commonName',
value: 'intermediate'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var root = [{
name: 'commonName',
value: 'root'
}, {
name: 'countryName',
value: 'US'
}, {
shortName: 'ST',
value: 'Virginia'
}, {
name: 'localityName',
value: 'Blacksburg'
}, {
name: 'organizationName',
value: 'Test'
}, {
shortName: 'OU',
value: 'Test'
}];
var intermediateCert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: intermediate,
issuer: root,
isCA: false
});
var entityCert = createCertificate({
publicKey: keys.publicKey,
signingKey: keys.privateKey,
serialNumber: '01',
subject: entity,
issuer: intermediate,
isCA: false
});
// verify certificate chain
var caStore = PKI.createCaStore();
caStore.addCertificate(intermediateCert);
var chain = [entityCert, intermediateCert];
PKI.verifyCertificateChain(caStore, chain, function(vfd, depth, chain) {
if(depth === 0) {
ASSERT.equal(vfd, true);
} else {
ASSERT.equal(vfd, PKI.certificateError.bad_certificate);
}
return true;
});
});
it('should verify certificate with sha1WithRSAEncryption signature', function() {
var certPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIDZDCCAs2gAwIBAgIKQ8fjjgAAAABh3jANBgkqhkiG9w0BAQUFADBGMQswCQYD\r\n' +
'VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu\r\n' +
'dGVybmV0IEF1dGhvcml0eTAeFw0xMjA2MjcxMzU5MTZaFw0xMzA2MDcxOTQzMjda\r\n' +
'MGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N\r\n' +
'b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRYwFAYDVQQDEw13d3cu\r\n' +
'Z29vZ2xlLmRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw2Hw3vNy5QMSd\r\n' +
'0/iMCS8lwZk9lnEk2NmrJt6vGJfRGlBprtHp5lpMFMoi+x8m8EwGVxXHGp7hLyN/\r\n' +
'gXuUjL7/DY9fxxx9l77D+sDZz7jfUfWmhS03Ra1FbT6myF8miVZFChJ8XgWzioJY\r\n' +
'gyNdRUC9149yrXdPWrSmSVaT0+tUCwIDAQABo4IBNjCCATIwHQYDVR0lBBYwFAYI\r\n' +
'KwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTiQGhrO3785rMPIKZ/zQEl5RyS\r\n' +
'0TAfBgNVHSMEGDAWgBS/wDDr9UMRPme6npH7/Gra42sSJDBbBgNVHR8EVDBSMFCg\r\n' +
'TqBMhkpodHRwOi8vd3d3LmdzdGF0aWMuY29tL0dvb2dsZUludGVybmV0QXV0aG9y\r\n' +
'aXR5L0dvb2dsZUludGVybmV0QXV0aG9yaXR5LmNybDBmBggrBgEFBQcBAQRaMFgw\r\n' +
'VgYIKwYBBQUHMAKGSmh0dHA6Ly93d3cuZ3N0YXRpYy5jb20vR29vZ2xlSW50ZXJu\r\n' +
'ZXRBdXRob3JpdHkvR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkuY3J0MAwGA1UdEwEB\r\n' +
'/wQCMAAwDQYJKoZIhvcNAQEFBQADgYEAVJ0qt/MBvHEPuWHeH51756qy+lBNygLA\r\n' +
'Xp5Gq+xHUTOzRty61BR05zv142hYAGWvpvnEOJ/DI7V3QlXK8a6dQ+du97obQJJx\r\n' +
'7ekqtfxVzmlSb23halYSoXmWgP8Tq0VUDsgsSLE7fS8JuO1soXUVKj1/6w189HL6\r\n' +
'LsngXwZSuL0=\r\n' +
'-----END CERTIFICATE-----\r\n';
var issuerPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIICsDCCAhmgAwIBAgIDC2dxMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\r\n' +
'MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\r\n' +
'aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwNjA4MjA0MzI3WhcNMTMwNjA3MTk0MzI3\r\n' +
'WjBGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZ\r\n' +
'R29vZ2xlIEludGVybmV0IEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\r\n' +
'gYkCgYEAye23pIucV+eEPkB9hPSP0XFjU5nneXQUr0SZMyCSjXvlKAy6rWxJfoNf\r\n' +
'NFlOCnowzdDXxFdF7dWq1nMmzq0yE7jXDx07393cCDaob1FEm8rWIFJztyaHNWrb\r\n' +
'qeXUWaUr/GcZOfqTGBhs3t0lig4zFEfC7wFQeeT9adGnwKziV28CAwEAAaOBozCB\r\n' +
'oDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFL/AMOv1QxE+Z7qekfv8atrjaxIk\r\n' +
'MB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYB\r\n' +
'Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v\r\n' +
'Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde\r\n' +
'BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN\r\n' +
'0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml\r\n' +
'UUIuOss4jHg7y/j7lYe8vJD5UDI=\r\n' +
'-----END CERTIFICATE-----\r\n';
var cert = PKI.certificateFromPem(certPem, true);
var issuer = PKI.certificateFromPem(issuerPem);
ASSERT.ok(issuer.verify(cert));
});
it('should verify certificate with sha256WithRSAEncryption signature', function() {
var certPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIDuzCCAqOgAwIBAgIEO5vZjDANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJE\r\n' +
'RTEPMA0GA1UEChMGRWxzdGVyMQswCQYDVQQLEwJDQTEZMBcGA1UEAxMQRWxzdGVy\r\n' +
'U29mdFRlc3RDQTAeFw0xMDA5MTUwNTM4MjRaFw0xMzA5MTUwNTM4MjRaMCsxFDAS\r\n' +
'BgNVBAUTCzEwMDIzMTQ5OTRDMRMwEQYDVQQDEwoxMDAyMzE0OTk0MIGfMA0GCSqG\r\n' +
'SIb3DQEBAQUAA4GNADCBiQKBgQCLPqjbwjsugzw6+qwwm/pdzDwk7ASIsBYJ17GT\r\n' +
'qyT0zCnYmdDDGWsYc+xxFVVIi8xBt6Mlq8Rwj+02UJhY9qm6zRA9MqFZC3ih+HoW\r\n' +
'xq7H8N2d10N0rX6h5PSjkF5fU5ugncZmppsRGJ9DNXgwjpf/CsH2rqThUzK4xfrq\r\n' +
'jpDS/wIDAQABo4IBTjCCAUowDgYDVR0PAQH/BAQDAgUgMAwGA1UdEwEB/wQCMAAw\r\n' +
'HQYDVR0OBBYEFF1h7H37OQivS57GD8+nK6VsgMPTMIGXBgNVHR8EgY8wgYwwgYmg\r\n' +
'gYaggYOGgYBsZGFwOi8vMTkyLjE2OC42LjI0OjM4OS9sJTNkQ0ElMjBaZXJ0aWZp\r\n' +
'a2F0ZSxvdSUzZENBLGNuJTNkRWxzdGVyU29mdFRlc3RDQSxkYyUzZHdpZXNlbCxk\r\n' +
'YyUzZGVsc3RlcixkYyUzZGRlPz9iYXNlPyhvYmplY3RDbGFzcz0qKTBxBgNVHSME\r\n' +
'ajBogBRBILMYmlZu//pj3wjDe2UPkq7jk6FKpEgwRjELMAkGA1UEBhMCREUxDzAN\r\n' +
'BgNVBAoTBkVsc3RlcjEPMA0GA1UECxMGUm9vdENBMRUwEwYDVQQDEwxFbHN0ZXJS\r\n' +
'b290Q0GCBDuayikwDQYJKoZIhvcNAQELBQADggEBAK8Z1+/VNyU5w/EiyhFH5aRE\r\n' +
'Mzxo0DahqKEm4pW5haBgKubJwZGs+CrBZR70TPbZGgJd36eyMgeXb/06lBnxewii\r\n' +
'I/aY6wMTviQTpqFnz5m0Le8UhH+hY1bqNG/vf6J+1gbOSrZyhAUV+MDJbL/OkzX4\r\n' +
'voVAfUBqSODod0f5wCW2RhvBmB9E62baP6qizdxyPA4iV16H4C0etd/7coLX6NZC\r\n' +
'oz3Yu0IRTQCH+YrpfIbxGb0grNhtCTfFpa287fuzu8mIEvLNr8GibhBXmQg7iJ+y\r\n' +
'q0VIyZLY8k6jEPrUB5Iv5ouSR19Dda/2+xJPlT/bosuNcErEuk/yKAHWAzwm1wQ=\r\n' +
'-----END CERTIFICATE-----\r\n';
var issuerPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIESjCCAzKgAwIBAgIEO5rKKTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJE\r\n' +
'RTEPMA0GA1UEChMGRWxzdGVyMQ8wDQYDVQQLEwZSb290Q0ExFTATBgNVBAMTDEVs\r\n' +
'c3RlclJvb3RDQTAeFw0wOTA3MjgwODE5MTFaFw0xNDA3MjgwODE5MTFaMEYxCzAJ\r\n' +
'BgNVBAYTAkRFMQ8wDQYDVQQKEwZFbHN0ZXIxCzAJBgNVBAsTAkNBMRkwFwYDVQQD\r\n' +
'ExBFbHN0ZXJTb2Z0VGVzdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\r\n' +
'AQEAv5uoKLnxXQe75iqwqgyt3H6MDAx/wvUVs26+2+yHpEUb/2gA3L8E+NChSb9E\r\n' +
'aNgxxoac3Yhvxzq2mPpih3vkY7Xw512Tm8l/OPbT8kbmBJmYZneFALXHytAIZiEf\r\n' +
'e0ZYNKAlClFIgNP5bE9UjTqVEEoSiUhpTubM6c5xEYVznnwPBoYQ0ari7RTDYnME\r\n' +
'HK4vMfoeBeWHYPiEygNHnGUG8d3merRC/lQASUtL6ikmLWKCKHfyit5ACzPNKAtw\r\n' +
'IzHAzD5ek0BpcUTci8hUsKz2ZvmoZcjPyj63veQuMYS5cTMgr3bfz9uz1xuoEDsb\r\n' +
'Sv9rQX9Iw3N7yMpxTDJTqGKhYwIDAQABo4IBPjCCATowDgYDVR0PAQH/BAQDAgEG\r\n' +
'MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFEEgsxiaVm7/+mPfCMN7ZQ+S\r\n' +
'ruOTMIGXBgNVHR8EgY8wgYwwgYmggYaggYOGgYBsZGFwOi8vMTkyLjE2OC42LjI0\r\n' +
'OjM4OS9sJTNkQ0ElMjBaZXJ0aWZpa2F0ZSxvdSUzZFJvb3RDQSxjbiUzZEVsc3Rl\r\n' +
'clJvb3RDQSxkYyUzZHdpZXNlbCxkYyUzZGVsc3RlcixkYyUzZGRlPz9iYXNlPyhv\r\n' +
'YmplY3RDbGFzcz0qKTBbBgNVHSMEVDBSoUqkSDBGMQswCQYDVQQGEwJERTEPMA0G\r\n' +
'A1UEChMGRWxzdGVyMQ8wDQYDVQQLEwZSb290Q0ExFTATBgNVBAMTDEVsc3RlclJv\r\n' +
'b3RDQYIEO5rKADANBgkqhkiG9w0BAQsFAAOCAQEAFauDnfHSbgRmbFkpQUXM5wKi\r\n' +
'K5STAaVps201iAjacX5EsOs5L37VUMoT9G2DAE8Z6B1pIiR3zcd3UpiHnFlUTC0f\r\n' +
'ZdOCXzDkOfziKY/RzuUsLNFUhBizCIA0+XcKgm3dSA5ex8fChLJddSYheSLuPua7\r\n' +
'iNMuzaU2YnevbMwpdEsl55Qr/uzcc0YM/mCuM4vsNFyFml91SQyPPmdR3VvGOoGl\r\n' +
'qS1R0HSoPJUvr0N0kARwD7kO3ikcJ6FxBCsgVLZHGJC+q8PQNZmVMbfgjH4nAyP8\r\n' +
'u7Qe03v2WLW0UgKu2g0UcQXWXbovktpZoK0fUOwv3bqsZ0K1IjVvMKG8OysUvA==\r\n' +
'-----END CERTIFICATE-----\r\n';
var cert = PKI.certificateFromPem(certPem, true);
var issuer = PKI.certificateFromPem(issuerPem);
ASSERT.ok(issuer.verify(cert));
});
it('should import certificate with sha256 RSASSA-PSS signature', function() {
var certPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIERzCCAvugAwIBAgIEO50CcjBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQC\r\n' +
'AQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwRjELMAkGA1UE\r\n' +
'BhMCREUxDzANBgNVBAoTBkVsc3RlcjELMAkGA1UECxMCQ0ExGTAXBgNVBAMTEEVs\r\n' +
'c3RlclNvZnRUZXN0Q0EwHhcNMTEwNzI4MTIxMzU3WhcNMTQwNzI4MTIxMzU3WjAr\r\n' +
'MRQwEgYDVQQFEwsxMDAyNzUzMzI1QzETMBEGA1UEAxMKMTAwMjc1MzMyNTCCASIw\r\n' +
'DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALHCogo7LVUkxWsMIc/0jgH2PCLt\r\n' +
'ukbATPehxWBG1XUPrz53lWgFJzlZaKLlLVVnXrfULaifuOKlZP6SM1JQlL1JuYgY\r\n' +
'AdgZyHjderNIk5NsSTmefwonSn/ukri5IRTH420oHtSjxk6+/DXlWnQy5OzTN6Bq\r\n' +
'jVJo8L+TTmf2jWuEam5cWa+YVP2k3tIqX5yMUDFjKO4znHdtIkHnBE0Kx03rWQRB\r\n' +
'TSYWDgDm2gttdOs9JVeuW0nnwQj27uo9gOR0iyaUjVrKLZ95p6zpXhM4uMSVRNeo\r\n' +
'LqkdqP2n+4pDXZVqLNgjkHQUS/xq9Q/kYgT2J7wkGfYxP9to7TG7vra1eOECAwEA\r\n' +
'AaOB7zCB7DAOBgNVHQ8BAf8EBAMCBSAwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\r\n' +
'NDJ2BZIk6ukLqkdmttH12bu2leswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2Ny\r\n' +
'bC5lbHN0ZXIuZGUvRWxzdGVyU29mdFRlc3RDQS5jcmwwcQYDVR0jBGowaIAU1R9A\r\n' +
'HmpdzaxK3v+ihQsEpAFgzOKhSqRIMEYxCzAJBgNVBAYTAkRFMQ8wDQYDVQQKEwZF\r\n' +
'bHN0ZXIxDzANBgNVBAsTBlJvb3RDQTEVMBMGA1UEAxMMRWxzdGVyUm9vdENBggQ7\r\n' +
'msqPMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0B\r\n' +
'AQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAQEAJBYNRZpe+z3yPPLV539Yci6OfjVg\r\n' +
'vs1e3rvSvcpFaqRJ8vZ8WNx3uuRQZ6B4Z3YEc00UJAOl3wU6KhamyryK2YvCrPg+\r\n' +
'TS5QDXNaO2z/rAnY1wWSlwBPlhqpMRrNv9cRXBcgK5YxprjytCVYN0UHdintgYxG\r\n' +
'fg7QYiFb00UXxAza1AFrpG+RqySFfO1scmu4kgpeb6A3USnQ0r6rZz6dt6NqgZZ6\r\n' +
'oUpDOCvnS9XSOWuvJirV8hIU0KAagguTbwfTqt9nt0wDlwZpemsJZ4Vvnvy8d9Jf\r\n' +
'zA68EWHbZLr2QP9hb3sHCWJgplMsTJnUwRfi2hf5KNtP8Xg5DSLMfTEbhw==\r\n' +
'-----END CERTIFICATE-----\r\n';
var cert = PKI.certificateFromPem(certPem, true);
ASSERT.equal(cert.signatureOid, PKI.oids['RSASSA-PSS']);
ASSERT.equal(cert.signatureParameters.hash.algorithmOid, PKI.oids['sha256']);
ASSERT.equal(cert.signatureParameters.mgf.algorithmOid, PKI.oids['mgf1']);
ASSERT.equal(cert.signatureParameters.mgf.hash.algorithmOid, PKI.oids['sha256']);
ASSERT.equal(cert.siginfo.algorithmOid, PKI.oids['RSASSA-PSS']);
ASSERT.equal(cert.siginfo.parameters.hash.algorithmOid, PKI.oids['sha256']);
ASSERT.equal(cert.siginfo.parameters.mgf.algorithmOid, PKI.oids['mgf1']);
ASSERT.equal(cert.siginfo.parameters.mgf.hash.algorithmOid, PKI.oids['sha256']);
});
it('should export certificate with sha256 RSASSA-PSS signature', function() {
var certPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIERzCCAvugAwIBAgIEO50CcjBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQC\r\n' +
'AQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwRjELMAkGA1UE\r\n' +
'BhMCREUxDzANBgNVBAoTBkVsc3RlcjELMAkGA1UECxMCQ0ExGTAXBgNVBAMTEEVs\r\n' +
'c3RlclNvZnRUZXN0Q0EwHhcNMTEwNzI4MTIxMzU3WhcNMTQwNzI4MTIxMzU3WjAr\r\n' +
'MRQwEgYDVQQFEwsxMDAyNzUzMzI1QzETMBEGA1UEAxMKMTAwMjc1MzMyNTCCASIw\r\n' +
'DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALHCogo7LVUkxWsMIc/0jgH2PCLt\r\n' +
'ukbATPehxWBG1XUPrz53lWgFJzlZaKLlLVVnXrfULaifuOKlZP6SM1JQlL1JuYgY\r\n' +
'AdgZyHjderNIk5NsSTmefwonSn/ukri5IRTH420oHtSjxk6+/DXlWnQy5OzTN6Bq\r\n' +
'jVJo8L+TTmf2jWuEam5cWa+YVP2k3tIqX5yMUDFjKO4znHdtIkHnBE0Kx03rWQRB\r\n' +
'TSYWDgDm2gttdOs9JVeuW0nnwQj27uo9gOR0iyaUjVrKLZ95p6zpXhM4uMSVRNeo\r\n' +
'LqkdqP2n+4pDXZVqLNgjkHQUS/xq9Q/kYgT2J7wkGfYxP9to7TG7vra1eOECAwEA\r\n' +
'AaOB7zCB7DAOBgNVHQ8BAf8EBAMCBSAwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\r\n' +
'NDJ2BZIk6ukLqkdmttH12bu2leswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2Ny\r\n' +
'bC5lbHN0ZXIuZGUvRWxzdGVyU29mdFRlc3RDQS5jcmwwcQYDVR0jBGowaIAU1R9A\r\n' +
'HmpdzaxK3v+ihQsEpAFgzOKhSqRIMEYxCzAJBgNVBAYTAkRFMQ8wDQYDVQQKEwZF\r\n' +
'bHN0ZXIxDzANBgNVBAsTBlJvb3RDQTEVMBMGA1UEAxMMRWxzdGVyUm9vdENBggQ7\r\n' +
'msqPMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0B\r\n' +
'AQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAQEAJBYNRZpe+z3yPPLV539Yci6OfjVg\r\n' +
'vs1e3rvSvcpFaqRJ8vZ8WNx3uuRQZ6B4Z3YEc00UJAOl3wU6KhamyryK2YvCrPg+\r\n' +
'TS5QDXNaO2z/rAnY1wWSlwBPlhqpMRrNv9cRXBcgK5YxprjytCVYN0UHdintgYxG\r\n' +
'fg7QYiFb00UXxAza1AFrpG+RqySFfO1scmu4kgpeb6A3USnQ0r6rZz6dt6NqgZZ6\r\n' +
'oUpDOCvnS9XSOWuvJirV8hIU0KAagguTbwfTqt9nt0wDlwZpemsJZ4Vvnvy8d9Jf\r\n' +
'zA68EWHbZLr2QP9hb3sHCWJgplMsTJnUwRfi2hf5KNtP8Xg5DSLMfTEbhw==\r\n' +
'-----END CERTIFICATE-----\r\n';
var cert = PKI.certificateFromPem(certPem, true);
ASSERT.equal(PKI.certificateToPem(cert), certPem);
});
it('should verify certificate with sha256 RSASSA-PSS signature', function() {
var certPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIERzCCAvugAwIBAgIEO50CcjBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQC\r\n' +
'AQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwRjELMAkGA1UE\r\n' +
'BhMCREUxDzANBgNVBAoTBkVsc3RlcjELMAkGA1UECxMCQ0ExGTAXBgNVBAMTEEVs\r\n' +
'c3RlclNvZnRUZXN0Q0EwHhcNMTEwNzI4MTIxMzU3WhcNMTQwNzI4MTIxMzU3WjAr\r\n' +
'MRQwEgYDVQQFEwsxMDAyNzUzMzI1QzETMBEGA1UEAxMKMTAwMjc1MzMyNTCCASIw\r\n' +
'DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALHCogo7LVUkxWsMIc/0jgH2PCLt\r\n' +
'ukbATPehxWBG1XUPrz53lWgFJzlZaKLlLVVnXrfULaifuOKlZP6SM1JQlL1JuYgY\r\n' +
'AdgZyHjderNIk5NsSTmefwonSn/ukri5IRTH420oHtSjxk6+/DXlWnQy5OzTN6Bq\r\n' +
'jVJo8L+TTmf2jWuEam5cWa+YVP2k3tIqX5yMUDFjKO4znHdtIkHnBE0Kx03rWQRB\r\n' +
'TSYWDgDm2gttdOs9JVeuW0nnwQj27uo9gOR0iyaUjVrKLZ95p6zpXhM4uMSVRNeo\r\n' +
'LqkdqP2n+4pDXZVqLNgjkHQUS/xq9Q/kYgT2J7wkGfYxP9to7TG7vra1eOECAwEA\r\n' +
'AaOB7zCB7DAOBgNVHQ8BAf8EBAMCBSAwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\r\n' +
'NDJ2BZIk6ukLqkdmttH12bu2leswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2Ny\r\n' +
'bC5lbHN0ZXIuZGUvRWxzdGVyU29mdFRlc3RDQS5jcmwwcQYDVR0jBGowaIAU1R9A\r\n' +
'HmpdzaxK3v+ihQsEpAFgzOKhSqRIMEYxCzAJBgNVBAYTAkRFMQ8wDQYDVQQKEwZF\r\n' +
'bHN0ZXIxDzANBgNVBAsTBlJvb3RDQTEVMBMGA1UEAxMMRWxzdGVyUm9vdENBggQ7\r\n' +
'msqPMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0B\r\n' +
'AQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAQEAJBYNRZpe+z3yPPLV539Yci6OfjVg\r\n' +
'vs1e3rvSvcpFaqRJ8vZ8WNx3uuRQZ6B4Z3YEc00UJAOl3wU6KhamyryK2YvCrPg+\r\n' +
'TS5QDXNaO2z/rAnY1wWSlwBPlhqpMRrNv9cRXBcgK5YxprjytCVYN0UHdintgYxG\r\n' +
'fg7QYiFb00UXxAza1AFrpG+RqySFfO1scmu4kgpeb6A3USnQ0r6rZz6dt6NqgZZ6\r\n' +
'oUpDOCvnS9XSOWuvJirV8hIU0KAagguTbwfTqt9nt0wDlwZpemsJZ4Vvnvy8d9Jf\r\n' +
'zA68EWHbZLr2QP9hb3sHCWJgplMsTJnUwRfi2hf5KNtP8Xg5DSLMfTEbhw==\r\n' +
'-----END CERTIFICATE-----\r\n';
var issuerPem = '-----BEGIN CERTIFICATE-----\r\n' +
'MIIEZDCCAxigAwIBAgIEO5rKjzBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQC\r\n' +
'AQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwRjELMAkGA1UE\r\n' +
'BhMCREUxDzANBgNVBAoTBkVsc3RlcjEPMA0GA1UECxMGUm9vdENBMRUwEwYDVQQD\r\n' +
'EwxFbHN0ZXJSb290Q0EwHhcNMTEwNzI4MTExNzI4WhcNMTYwNzI4MTExNzI4WjBG\r\n' +
'MQswCQYDVQQGEwJERTEPMA0GA1UEChMGRWxzdGVyMQswCQYDVQQLEwJDQTEZMBcG\r\n' +
'A1UEAxMQRWxzdGVyU29mdFRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\r\n' +
'AQoCggEBAMFpz3sXnXq4ZUBdYdpG5DJVfITLXYwXPfEJzr1pLRfJ2eMPn7k3B/2g\r\n' +
'bvuH30zKmDRjlfV51sFw4l1l+cQugzy5FEOrfE6g7IvhpBUf9SQujVWtE3BoSRR5\r\n' +
'pSGbIWC7sm2SG0drpoCRpL0xmWZlAUS5mz7hBecJC/kKkKeOxUg5h492XQgWd0ow\r\n' +
'6GlyQBxJCmxgQBMnLS0stecs234hR5gvTHic50Ey+gRMPsTyco2Fm0FqvXtBuOsj\r\n' +
'zAW7Nk2hnM6awFHVMDBLm+ClE1ww0dLW0ujkdoGsTEbvmM/w8MBI6WAiWaanjK/x\r\n' +
'lStmQeUVXKd+AfuzT/FIPrwANcC1qGUCAwEAAaOB8TCB7jAOBgNVHQ8BAf8EBAMC\r\n' +
'AQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU1R9AHmpdzaxK3v+ihQsE\r\n' +
'pAFgzOIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5lbHN0ZXIuZGUvRWxz\r\n' +
'dGVyUm9vdENBLmNybDBxBgNVHSMEajBogBS3zfTokckL2H/fTojW02K+metEcaFK\r\n' +
'pEgwRjELMAkGA1UEBhMCREUxDzANBgNVBAoTBkVsc3RlcjEPMA0GA1UECxMGUm9v\r\n' +
'dENBMRUwEwYDVQQDEwxFbHN0ZXJSb290Q0GCBDuaylowQQYJKoZIhvcNAQEKMDSg\r\n' +
'DzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKID\r\n' +
'AgEgA4IBAQBjT107fBmSfQNUYCpXIlaS/pogPoCahuC1g8QDtq6IEVXoEgXCzfVN\r\n' +
'JYHyYOQOraP4O2LEcXpo/oc0MMpVF06QLKG/KieUE0mrZnsCJ3GLSJkM8tI8bRHj\r\n' +
'8tAhlViMacUqnKKufCs/rIN25JB57+sCyFqjtRbSt88e+xqFJ5I79Btp/bNtoj2G\r\n' +
'OJGl997EPua9/yJuvdA9W67WO/KwEh+FqylB1pAapccOHqttwu4QJIc/XJfG5rrf\r\n' +
'8QZz8HIuOcroA4zIrprQ1nJRCuMII04ueDtBVz1eIEmqNEUkr09JdK8M0LKH0lMK\r\n' +
'Ysgjai/P2mPVVwhVw6dHzUVRLXh3xIQr\r\n' +
'-----END CERTIFICATE-----\r\n';
var cert = PKI.certificateFromPem(certPem, true);
var issuer = PKI.certificateFromPem(issuerPem);
ASSERT.ok(issuer.verify(cert));
});
});
describe('public key fingerprints', function() {
it('should get a SHA-1 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(publicKey, {type: 'RSAPublicKey'});
ASSERT.equal(fp.toHex(), 'f57563e0c75d6e9b03fafdb2fd72349f23030300');
});
it('should get a SHA-1 SubjectPublicKeyInfo fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {type: 'SubjectPublicKeyInfo'});
ASSERT.equal(fp.toHex(), '984724bc548bbc2c8acbac044bd8d518abd26dd8');
});
it('should get a hex SHA-1 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {type: 'RSAPublicKey', encoding: 'hex'});
ASSERT.equal(fp, 'f57563e0c75d6e9b03fafdb2fd72349f23030300');
});
it('should get a hex, colon-delimited SHA-1 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {type: 'RSAPublicKey', encoding: 'hex', delimiter: ':'});
ASSERT.equal(
fp, 'f5:75:63:e0:c7:5d:6e:9b:03:fa:fd:b2:fd:72:34:9f:23:03:03:00');
});
it('should get a hex, colon-delimited SHA-1 SubjectPublicKeyInfo fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {
type: 'SubjectPublicKeyInfo',
encoding: 'hex',
delimiter: ':'
});
ASSERT.equal(
fp, '98:47:24:bc:54:8b:bc:2c:8a:cb:ac:04:4b:d8:d5:18:ab:d2:6d:d8');
});
it('should get an MD5 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {md: MD.md5.create(), type: 'RSAPublicKey'});
ASSERT.equal(fp.toHex(), 'c7da180cc48d31a071d31a78bc43d9d7');
});
it('should get an MD5 SubjectPublicKeyInfo fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {md: MD.md5.create(), type: 'SubjectPublicKeyInfo'});
ASSERT.equal(fp.toHex(), 'e5c5ba577fe24fb8a678d8d58f539cd7');
});
it('should get a hex MD5 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey,
{md: MD.md5.create(), type: 'RSAPublicKey', encoding: 'hex'});
ASSERT.equal(fp, 'c7da180cc48d31a071d31a78bc43d9d7');
});
it('should get a hex, colon-delimited MD5 RSAPublicKey fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {
md: MD.md5.create(),
type: 'RSAPublicKey',
encoding: 'hex',
delimiter: ':'
});
ASSERT.equal(fp, 'c7:da:18:0c:c4:8d:31:a0:71:d3:1a:78:bc:43:d9:d7');
});
it('should get a hex, colon-delimited MD5 SubjectPublicKeyInfo fingerprint', function() {
var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
var fp = PKI.getPublicKeyFingerprint(
publicKey, {
md: MD.md5.create(),
type: 'SubjectPublicKeyInfo',
encoding: 'hex',
delimiter: ':'
});
ASSERT.equal(fp, 'e5:c5:ba:57:7f:e2:4f:b8:a6:78:d8:d5:8f:53:9c:d7');
});
});
function createCertificate(options) {
var publicKey = options.publicKey;
var signingKey = options.signingKey;
var subject = options.subject;
var issuer = options.issuer;
var isCA = options.isCA;
var serialNumber = options.serialNumber || '01';
var cert = PKI.createCertificate();
cert.publicKey = publicKey;
cert.serialNumber = serialNumber;
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(
cert.validity.notBefore.getFullYear() + 1);
cert.setSubject(subject);
cert.setIssuer(issuer);
var extensions = [];
if(isCA) {
extensions.push({
name: 'basicConstraints',
cA: true
});
}
extensions.push({
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}, {
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
codeSigning: true,
emailProtection: true,
timeStamping: true
}, {
name: 'nsCertType',
client: true,
server: true,
email: true,
objsign: true,
sslCA: true,
emailCA: true,
objCA: true
}, {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'http://example.org/webid#me'
}]
}, {
name: 'subjectKeyIdentifier'
});
// FIXME: add authorityKeyIdentifier extension
cert.setExtensions(extensions);
cert.sign(signingKey);
return cert;
}
}
// check for AMD
if(typeof define === 'function') {
define([
'forge/pki',
'forge/md',
'forge/util'
], function(PKI, MD, UTIL) {
Tests(
// Global provided by test harness
ASSERT,
PKI(),
MD(),
UTIL()
);
});
} else if(typeof module === 'object' && module.exports) {
// assume NodeJS
Tests(
require('assert'),
require('../../js/pki')(),
require('../../js/md')(),
require('../../js/util')());
}
})();

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="mocha/mocha.css">
<script src="mocha/mocha.js" type="text/javascript" charset="utf-8"></script>
<script src="chai/chai.js" type="text/javascript" charset="utf-8"></script>
<script src="require.js" data-main="test" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="mocha"></div>
</body>
</html>

View File

@@ -0,0 +1,35 @@
/*
RequireJS 2.1.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(aa){function I(b){return"[object Function]"===L.call(b)}function J(b){return"[object Array]"===L.call(b)}function y(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function m(b,c){return s(b,c)&&b[c]}function G(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function R(b,c,d,m){c&&G(c,function(c,j){if(d||!s(b,j))m&&"string"!==typeof c?(b[j]||(b[j]={}),R(b[j],
c,d,m)):b[j]=c});return b}function u(b,c){return function(){return c.apply(b,arguments)}}function ba(b){if(!b)return b;var c=aa;y(b.split("."),function(b){c=c[b]});return c}function B(b,c,d,m){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=m;d&&(c.originalError=d);return c}function ha(b){function c(a,f,b){var e,n,c,g,d,S,i,h=f&&f.split("/");e=h;var j=k.map,l=j&&j["*"];if(a&&"."===a.charAt(0))if(f){e=m(k.pkgs,f)?h=[f]:h.slice(0,h.length-1);f=a=e.concat(a.split("/"));
for(e=0;f[e];e+=1)if(n=f[e],"."===n)f.splice(e,1),e-=1;else if(".."===n)if(1===e&&(".."===f[2]||".."===f[0]))break;else 0<e&&(f.splice(e-1,2),e-=2);e=m(k.pkgs,f=a[0]);a=a.join("/");e&&a===f+"/"+e.main&&(a=f)}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&j&&(h||l)){f=a.split("/");for(e=f.length;0<e;e-=1){c=f.slice(0,e).join("/");if(h)for(n=h.length;0<n;n-=1)if(b=m(j,h.slice(0,n).join("/")))if(b=m(b,c)){g=b;d=e;break}if(g)break;!S&&(l&&m(l,c))&&(S=m(l,c),i=e)}!g&&S&&(g=S,d=i);g&&(f.splice(0,d,
g),a=f.join("/"))}return a}function d(a){A&&y(document.getElementsByTagName("script"),function(f){if(f.getAttribute("data-requiremodule")===a&&f.getAttribute("data-requirecontext")===i.contextName)return f.parentNode.removeChild(f),!0})}function z(a){var f=m(k.paths,a);if(f&&J(f)&&1<f.length)return d(a),f.shift(),i.require.undef(a),i.require([a]),!0}function h(a){var f,b=a?a.indexOf("!"):-1;-1<b&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function j(a,f,b,e){var n,C,g=null,d=f?f.name:
null,j=a,l=!0,k="";a||(l=!1,a="_@r"+(M+=1));a=h(a);g=a[0];a=a[1];g&&(g=c(g,d,e),C=m(q,g));a&&(g?k=C&&C.normalize?C.normalize(a,function(a){return c(a,d,e)}):c(a,d,e):(k=c(a,d,e),a=h(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!C&&!b?"_unnormalized"+(Q+=1):"";return{prefix:g,name:k,parentMap:f,unnormalized:!!b,url:n,originalName:j,isDefine:l,id:(g?g+"!"+k:k)+b}}function r(a){var f=a.id,b=m(p,f);b||(b=p[f]=new i.Module(a));return b}function t(a,f,b){var e=a.id,n=m(p,e);if(s(q,e)&&(!n||n.defineEmitComplete))"defined"===
f&&b(q[e]);else r(a).on(f,b)}function v(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(y(b,function(f){if(f=m(p,f))f.error=a,f.events.error&&(e=!0,f.emit("error",a))}),!e)l.onError(a)}function w(){T.length&&(ia.apply(H,[H.length-1,0].concat(T)),T=[])}function x(a){delete p[a];delete V[a]}function F(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!0,y(a.depMaps,function(e,c){var g=e.id,d=m(p,g);d&&(!a.depMatched[c]&&!b[g])&&(m(f,g)?(a.defineDep(c,q[g]),a.check()):F(d,f,b))}),b[e]=!0)}
function D(){var a,f,b,e,n=(b=1E3*k.waitSeconds)&&i.startTime+b<(new Date).getTime(),c=[],g=[],h=!1,j=!0;if(!W){W=!0;G(V,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&n)z(f)?h=e=!0:(c.push(f),d(f));else if(!b.inited&&(b.fetched&&a.isDefine)&&(h=!0,!a.prefix))return j=!1});if(n&&c.length)return b=B("timeout","Load timeout for modules: "+c,null,c),b.contextName=i.contextName,v(b);j&&y(g,function(a){F(a,{},{})});if((!n||e)&&h)if((A||da)&&!X)X=setTimeout(function(){X=
0;D()},50);W=!1}}function E(a){s(q,a[0])||r(j(a[0],null,!0)).init(a[1],a[2])}function K(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!Y?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=i.onScriptError;(!a.detachEvent||Y)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function L(){var a;for(w();H.length;){a=H.shift();if(null===a[0])return v(B("mismatch","Mismatched anonymous define() module: "+a[a.length-
1]));E(a)}}var W,Z,i,N,X,k={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},shim:{},config:{}},p={},V={},$={},H=[],q={},U={},M=1,Q=1;N={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=q[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return k.config&&m(k.config,a.map.id)||{}},exports:q[a.map.id]}}};Z=function(a){this.events=
m($,a.id)||{};this.map=a;this.shim=m(k.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};Z.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=u(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=
!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],u(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;U[a]||(U[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;
var e=this.exports,n=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(I(n)){if(this.events.error)try{e=i.execCb(c,n,b,e)}catch(d){a=d}else e=i.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",v(this.error=
a)}else e=n;this.exports=e;if(this.map.isDefine&&!this.ignore&&(q[c]=e,l.onResourceLoad))l.onResourceLoad(i,this.map,this.depMaps);x(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=j(a.prefix);this.depMaps.push(d);t(d,"defined",u(this,function(e){var n,d;d=this.map.name;var g=this.map.parentMap?this.map.parentMap.name:null,h=
i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,g,!0)})||""),e=j(a.prefix+"!"+d,this.map.parentMap),t(e,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=m(p,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else n=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=u(this,
function(a){this.inited=!0;this.error=a;a.requireModules=[b];G(p,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&x(a.map.id)});v(a)}),n.fromText=u(this,function(e,c){var d=a.name,g=j(d),C=O;c&&(e=c);C&&(O=!1);r(g);s(k.config,b)&&(k.config[d]=k.config[b]);try{l.exec(e)}catch(ca){return v(B("fromtexteval","fromText eval for "+b+" failed: "+ca,ca,[b]))}C&&(O=!0);this.depMaps.push(g);i.completeLoad(d);h([d],n)}),e.load(a.name,h,n,k)}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=
this;this.enabling=this.enabled=!0;y(this.depMaps,u(this,function(a,b){var c,e;if("string"===typeof a){a=j(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=m(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;t(a,"defined",u(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&t(a,"error",this.errback)}c=a.id;e=p[c];!s(N,c)&&(e&&!e.enabled)&&i.enable(a,this)}));G(this.pluginMaps,u(this,function(a){var b=m(p,a.id);b&&!b.enabled&&i.enable(a,
this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:k,contextName:b,registry:p,defined:q,urlFetched:U,defQueue:H,Module:Z,makeModuleMap:j,nextTick:l.nextTick,onError:v,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};G(a,function(a,b){e[b]?
"map"===b?(k.map||(k.map={}),R(k[b],a,!0,!0)):R(k[b],a,!0):k[b]=a});a.shim&&(G(a.shim,function(a,b){J(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);c[b]=a}),k.shim=c);a.packages&&(y(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ja,"").replace(ea,"")}}),k.pkgs=b);G(p,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=j(b))});if(a.deps||a.callback)i.require(a.deps||[],
a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(aa,arguments));return b||a.exports&&ba(a.exports)}},makeRequire:function(a,f){function d(e,c,h){var g,k;f.enableBuildCallback&&(c&&I(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(I(c))return v(B("requireargs","Invalid require call"),h);if(a&&s(N,e))return N[e](p[a.id]);if(l.get)return l.get(i,e,a,d);g=j(e,a,!1,!0);g=g.id;return!s(q,g)?v(B("notloaded",'Module name "'+g+'" has not been loaded yet for context: '+
b+(a?"":". Use require([])"))):q[g]}L();i.nextTick(function(){L();k=r(j(null,a));k.skipMap=f.skipMap;k.init(e,c,h,{enabled:!0});D()});return d}f=f||{};R(d,{isBrowser:A,toUrl:function(b){var d,f=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==f&&(!("."===g||".."===g)||1<f))d=b.substring(f,b.length),b=b.substring(0,f);return i.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return s(q,j(b,a,!1,!0).id)},specified:function(b){b=j(b,a,!1,!0).id;return s(q,b)||s(p,b)}});a||(d.undef=function(b){w();var c=
j(b,a,!0),d=m(p,b);delete q[b];delete U[c.url];delete $[b];d&&(d.events.defined&&($[b]=d.events),x(b))});return d},enable:function(a){m(p,a.id)&&r(a).enable()},completeLoad:function(a){var b,c,e=m(k.shim,a)||{},d=e.exports;for(w();H.length;){c=H.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=m(p,a);if(!b&&!s(q,a)&&c&&!c.inited){if(k.enforceDefine&&(!d||!ba(d)))return z(a)?void 0:v(B("nodefine","No define call for "+a,null,[a]));E([a,e.deps||[],e.exportsFn])}D()},nameToUrl:function(a,
b,c){var e,d,h,g,j,i;if(l.jsExtRegExp.test(a))g=a+(b||"");else{e=k.paths;d=k.pkgs;g=a.split("/");for(j=g.length;0<j;j-=1)if(i=g.slice(0,j).join("/"),h=m(d,i),i=m(e,i)){J(i)&&(i=i[0]);g.splice(0,j,i);break}else if(h){a=a===h.name?h.location+"/"+h.main:h.location;g.splice(0,j,a);break}g=g.join("/");g+=b||(/\?/.test(g)||c?"":".js");g=("/"===g.charAt(0)||g.match(/^[\w\+\.\-]+:/)?"":k.baseUrl)+g}return k.urlArgs?g+((-1===g.indexOf("?")?"?":"&")+k.urlArgs):g},load:function(a,b){l.load(i,a,b)},execCb:function(a,
b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=K(a),i.completeLoad(a.id)},onScriptError:function(a){var b=K(a);if(!z(b.id))return v(B("scripterror","Script error",a,[b.id]))}};i.require=i.makeRequire();return i}var l,w,x,D,t,E,P,K,Q,fa,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,ea=/\.js$/,ja=/^\.\//;w=Object.prototype;var L=w.toString,ga=w.hasOwnProperty,ia=
Array.prototype.splice,A=!!("undefined"!==typeof window&&navigator&&document),da=!A&&"undefined"!==typeof importScripts,ka=A&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,Y="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},r={},T=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(I(requirejs))return;r=requirejs;requirejs=void 0}"undefined"!==typeof require&&!I(require)&&(r=require,require=void 0);l=requirejs=function(b,c,d,z){var h,
j="_";!J(b)&&"string"!==typeof b&&(h=b,J(c)?(b=c,c=d,d=z):b=[]);h&&h.context&&(j=h.context);(z=m(F,j))||(z=F[j]=l.s.newContext(j));h&&z.configure(h);return z.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version="2.1.5";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=A;w=l.s={contexts:F,newContext:ha};l({});y(["toUrl","undef","defined","specified"],function(b){l[b]=function(){var c=F._;return c.require[b].apply(c,
arguments)}});if(A&&(x=w.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))x=w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var l=b&&b.config||{},h;if(A)return h=l.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),h.type=l.scriptType||"text/javascript",h.charset="utf-8",h.async=!0,h.setAttribute("data-requirecontext",b.contextName),h.setAttribute("data-requiremodule",c),
h.attachEvent&&!(h.attachEvent.toString&&0>h.attachEvent.toString().indexOf("[native code"))&&!Y?(O=!0,h.attachEvent("onreadystatechange",b.onScriptLoad)):(h.addEventListener("load",b.onScriptLoad,!1),h.addEventListener("error",b.onScriptError,!1)),h.src=d,K=h,D?x.insertBefore(h,D):x.appendChild(h),K=null,h;if(da)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(B("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};A&&M(document.getElementsByTagName("script"),function(b){x||(x=
b.parentNode);if(t=b.getAttribute("data-main"))return r.baseUrl||(E=t.split("/"),Q=E.pop(),fa=E.length?E.join("/")+"/":"./",r.baseUrl=fa,t=Q),t=t.replace(ea,""),r.deps=r.deps?r.deps.concat(t):[t],!0});define=function(b,c,d){var l,h;"string"!==typeof b&&(d=c,c=b,b=null);J(c)||(d=c,c=[]);!c.length&&I(d)&&d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(l=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),
function(b){if("interactive"===b.readyState)return P=b}),l=P;l&&(b||(b=l.getAttribute("data-requiremodule")),h=F[l.getAttribute("data-requirecontext")])}(h?h.defQueue:T).push([b,c,d])};define.amd={jQuery:!0};l.exec=function(b){return eval(b)};l(r)}})(this);

View File

@@ -0,0 +1,36 @@
var ASSERT = chai.assert;
mocha.setup({
ui: 'bdd',
timeout: 30000
});
requirejs.config({
paths: {
forge: 'forge',
test: 'test'
}
});
requirejs([
'test/util',
'test/md5',
'test/sha1',
'test/sha256',
'test/hmac',
'test/pbkdf2',
'test/mgf1',
'test/random',
'test/asn1',
'test/pem',
'test/rsa',
'test/kem',
'test/pkcs1',
'test/x509',
'test/csr',
'test/aes',
'test/rc2',
'test/des',
'test/pkcs7',
'test/pkcs12',
'test/tls'
], function() {
mocha.run();
});

File diff suppressed because one or more lines are too long