Skip to content

Commit

Permalink
Add RsaSignature2017 support.
Browse files Browse the repository at this point in the history
- Use jws lib.
- Use specific header params.
- Use JWS Compact Serialization with Detached Content.
  • Loading branch information
davidlehn committed Sep 27, 2017
1 parent 4814f02 commit e3ca544
Show file tree
Hide file tree
Showing 3 changed files with 329 additions and 4 deletions.
85 changes: 83 additions & 2 deletions lib/jsonld-signatures.js
Expand Up @@ -69,7 +69,8 @@ api.SECURITY_CONTEXT_URL = 'https://w3id.org/security/v1';
api.SUPPORTED_ALGORITHMS = [
'EcdsaKoblitzSignature2016',
'GraphSignature2012',
'LinkedDataSignature2015'
'LinkedDataSignature2015',
'RsaSignature2017'
];

/* Core API */
Expand Down Expand Up @@ -107,8 +108,9 @@ api.use = function(name, injectable) {
// api not set yet, load default
if(!libs[name]) {
var requireAliases = {
'bitcoreMessage': 'bitcore-message',
'forge': 'node-forge',
'bitcoreMessage': 'bitcore-message'
'jws': 'jws'
};
var requireName = requireAliases[name] || name;
libs[name] = global[name] || (_nodejs && require(requireName));
Expand Down Expand Up @@ -797,6 +799,25 @@ var _createSignature = function(input, options) {
return Promise.resolve(signature);
}

if(options.algorithm === 'RsaSignature2017') {
// works same in any environment
var jws = api.use('jws');
var fullSignature = jws.sign({
header: {
alg: 'RS256',
b64: false,
crit: ['b64']
},
privateKey: options.privateKeyPem,
payload: _getDataToHash(input, options)
});
// detached content signature
var parts = fullSignature.split('.');
parts[1] = '';
var detachedSignature = parts.join('.');
return Promise.resolve(detachedSignature);
}

if(_nodejs) {
// optimize using node libraries
var crypto = api.use('crypto');
Expand Down Expand Up @@ -842,6 +863,17 @@ var _verifySignature = function(input, signature, options) {
return Promise.resolve(verified);
}

if(options.algorithm === 'RsaSignature2017') {
// works same in any environment
var jws = api.use('jws');
// rebuild detached content signature
var parts = signature.split('.');
parts[1] = _encodeBase64Url(_getDataToHash(input, options));
var fullSignature = parts.join('.');
var verified = jws.verify(fullSignature, 'RS256', options.publicKeyPem);
return Promise.resolve(verified);
}

if(_nodejs) {
// optimize using node libraries
var crypto = api.use('crypto');
Expand Down Expand Up @@ -965,6 +997,55 @@ function _zeroFill(num) {
return (num < 10) ? '0' + num : '' + num;
}

/**
* Encodes input according to the "Base64url Encoding" format as specified
* in JSON Web Signature (JWS) RFC7517. A URL safe character set is used and
* trailing '=', line breaks, whitespace, and other characters are omitted.
*
* @param input the data to encode.
*
* @return the encoded value.
*/
function _encodeBase64Url(input) {
var forge = api.use('forge');
var enc = forge.util.encode64(input);
return enc
.replace(/=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
// expose for testing
api._encodeBase64Url = _encodeBase64Url;

/**
* Decodes input according to the "Base64url Encoding" format as specified
* in JSON Web Signature (JWS) RFC7517. A URL safe character set is used and
* trailing '=', line breaks, whitespace, and other characters are omitted.
*
* @param input the data to decode.
*
* @return the decoded value.
*/
function _decodeBase64Url(input) {
var forge = api.use('forge');
var normalInput = input
.replace(/-/g, '+')
.replace(/_/g, '/');
var mod4 = normalInput.length % 4;
if(mod4 === 0) {
// pass
} else if(mod4 === 2) {
normalInput = normalInput + '==';
} else if(mod4 === 3) {
normalInput = normalInput + '=';
} else {
throw new Error('Illegal base64 string.');
}
return forge.util.decode64(normalInput);
}
// expose for testing
api._decodeBase64Url = _decodeBase64Url;

/* Promises API */

/**
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -38,6 +38,7 @@
"commander": "~2.9.0",
"es6-promise": "^4.0.5",
"jsonld": "^0.5.10",
"jws": "^3.1.4",
"node-forge": "~0.7.1"
},
"devDependencies": {
Expand Down

0 comments on commit e3ca544

Please sign in to comment.