Skip to content

Commit

Permalink
Remove dependency to ursa (#928)
Browse files Browse the repository at this point in the history
  • Loading branch information
mfred488 authored and herom committed Jun 2, 2017
1 parent d3f9875 commit 431c73b
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 33 deletions.
4 changes: 1 addition & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,12 +532,10 @@ WS-Security X509 Certificate support.
var privateKey = fs.readFileSync(privateKeyPath);
var publicKey = fs.readFileSync(publicKeyPath);
var password = ''; // optional password
var wsSecurity = new soap.WSSecurityCert(privateKey, publicKey, password, 'utf8');
var wsSecurity = new soap.WSSecurityCert(privateKey, publicKey, password);
client.setSecurity(wsSecurity);
```

_Note_: Optional dependency 'ursa' is required to be installed successfully when WSSecurityCert is used.

## Handling XML Attributes, Value and XML (wsdlOptions).
Sometimes it is necessary to override the default behaviour of `node-soap` in order to deal with the special requirements
of your code base or a third library you use. Therefore you can use the `wsdlOptions` Object, which is passed in the
Expand Down
13 changes: 5 additions & 8 deletions lib/security/WSSecurityCert.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"use strict";

var optional = require("optional");
var ursa = optional('ursa');
var fs = require('fs');
var path = require('path');
var ejs = require('ejs');
Expand Down Expand Up @@ -36,15 +34,14 @@ function generateId() {
return uuid.v4().replace(/-/gm, '');
}

function WSSecurityCert(privatePEM, publicP12PEM, password, encoding) {
if (!ursa) {
throw new Error('Module ursa must be installed to use WSSecurityCert');
}
this.privateKey = ursa.createPrivateKey(privatePEM, password, encoding);
function WSSecurityCert(privatePEM, publicP12PEM, password) {
this.publicP12PEM = publicP12PEM.toString().replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace(/(\r\n|\n|\r)/gm, '');

this.signer = new SignedXml();
this.signer.signingKey = this.privateKey.toPrivatePem();
this.signer.signingKey = {
key: privatePEM,
passphrase: password
};
this.x509Id = "x509-" + generateId();

var _this = this;
Expand Down
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"ejs": "~2.5.5",
"finalhandler": "^0.5.0",
"lodash": "^3.10.1",
"optional": "^0.1.3",
"request": ">=2.9.0",
"sax": ">=0.6",
"selectn": "^0.9.6",
Expand All @@ -22,9 +21,6 @@
"uuid": "^3.0.1",
"xml-crypto": "~0.8.0"
},
"optionalDependencies": {
"ursa": "0.8.5 || >=0.9.4"
},
"repository": {
"type": "git",
"url": "https://github.com/milewise/node-soap.git"
Expand Down
11 changes: 11 additions & 0 deletions test/certs/agent2-key-with-password.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBgTAbBgkqhkiG9w0BBQMwDgQICq+TjRaVRpYCAggABIIBYIW7b0BY6bWa1tcl
kW9xqSNyMI6C051rPqMzbN8jTrKneHSaegCCDd6fDDyH3vXJaxxzmgnGuRBHEv/6
8tTTbQERI1VnjYAH3dgYIdi3k1YYCKHatPK7El1B3ffWhiW8t1jNOWRC6p00VbIN
SYKrTs8s1JGoMkeKp6N1jATbnPcuqPut3MdQjV/7cHMJJC2t8dDfiKspRB2x/bDY
6S665JLXUpAhTvSVehtBIoXA9BBGVanbhgT4vyx9T4PJKmsiylrz4cTDeoeXPkE/
eWx0IDJr7uyllCkzY4nftEKRZdjUZa4dzvLlZpbW1bppPi0j8yjvt0YE5qEf+LNZ
8QvE3We5eOE76tYBfA44yUwUJJ8coTg4/mOomaZnW+LRdH9jxQdDIYesZkR4dosO
f3lqR5GTZGpr/qaI//Pf1r6nRCDw9Oqi+knPJUNqAJh13Y7jvFedIdAL6vJXFZxq
PsZxAOE=
-----END ENCRYPTED PRIVATE KEY-----
49 changes: 31 additions & 18 deletions test/security/WSSecurityCert.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,60 @@ describe('WSSecurityCert', function() {
var WSSecurityCert = require('../../').WSSecurityCert;
var cert = fs.readFileSync(join(__dirname, '..', 'certs', 'agent2-cert.pem'));
var key = fs.readFileSync(join(__dirname, '..', 'certs', 'agent2-key.pem'));
var keyWithPassword = fs.readFileSync(join(__dirname, '..', 'certs', 'agent2-key-with-password.pem')); // The passphrase protecting the private key is "soap"

it('is a function', function() {
WSSecurityCert.should.be.type('function');
});

it('should accept valid constructor variables', function() {
var instance = new WSSecurityCert(key, cert, '', 'utf8');
instance.should.have.property('privateKey');
var instance = new WSSecurityCert(key, cert, '');
instance.should.have.property('publicP12PEM');
instance.should.have.property('signer');
instance.should.have.property('x509Id');
});

it('should not accept invalid constructor variables', function() {
it('should fail at computing signature when the private key is invalid', function() {
var passed = true;

try {
new WSSecurityCert('*****', cert, '', 'utf8');
var instance = new WSSecurityCert('*****', cert, '');
instance.postProcess('<soap:Header></soap:Header><soap:Body></soap:Body>', 'soap');
} catch(e) {
passed = false;
}

if (passed) {
throw new Error('bad private key');
}
});

passed = true;

try {
new WSSecurityCert(key, cert, '', 'bob');
} catch(e) {
passed = false;
}
it('should insert a WSSecurity signing block when postProcess is called (private key is raw)', function() {
var instance = new WSSecurityCert(key, cert, '');
var xml = instance.postProcess('<soap:Header></soap:Header><soap:Body></soap:Body>', 'soap');

if (passed) {
throw new Error('bad encoding');
}
xml.should.containEql('<wsse:Security');
xml.should.containEql('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');
xml.should.containEql('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd');
xml.should.containEql('soap:mustUnderstand="1"');
xml.should.containEql('<wsse:BinarySecurityToken');
xml.should.containEql('EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
xml.should.containEql('ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"');
xml.should.containEql('wsu:Id="' + instance.x509Id);
xml.should.containEql('</wsse:BinarySecurityToken>');
xml.should.containEql('<Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="_1">');
xml.should.containEql('<Created>' + instance.created);
xml.should.containEql('<Expires>' + instance.expires);
xml.should.containEql('<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">');
xml.should.containEql('<wsse:SecurityTokenReference>');
xml.should.containEql('<wsse:Reference URI="#' + instance.x509Id);
xml.should.containEql('ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>');
xml.should.containEql(instance.publicP12PEM);
xml.should.containEql(instance.signer.getSignatureXml());
});

it('should insert a WSSecurity signing block when postProcess is called', function() {
var instance = new WSSecurityCert(key, cert, '', 'utf8');
it('should insert a WSSecurity signing block when postProcess is called (private key is protected by a passphrase)', function() {
var instance = new WSSecurityCert(keyWithPassword, cert, 'soap');
var xml = instance.postProcess('<soap:Header></soap:Header><soap:Body></soap:Body>', 'soap');

xml.should.containEql('<wsse:Security');
Expand All @@ -71,7 +84,7 @@ describe('WSSecurityCert', function() {
});

it('should only add two Reference elements, for Soap Body and Timestamp inside wsse:Security element', function() {
var instance = new WSSecurityCert(key, cert, '', 'utf8');
var instance = new WSSecurityCert(key, cert, '');
var xml = instance.postProcess('<soap:Header></soap:Header><soap:Body><Body></Body><Timestamp></Timestamp></soap:Body>', 'soap');

xml.match(/<Reference URI="#/g).should.have.length(2);
Expand Down

0 comments on commit 431c73b

Please sign in to comment.