Skip to content

Commit

Permalink
Imrpove URDNA2015 support.
Browse files Browse the repository at this point in the history
- Add docs.
- Add Algorithm Support docs.
- Add URDNA2015 Migration docs.
- Add migration tools:
  - Undocumented "rejectURDNA2015" API option to not allow URDNA2015.
    - Allows concerned code to explicitly fail in potential edge cases.
  - Global "RDF_CANONIZE_TRACE_URDNA2015" to trace URDNA2015 use.
    - Allows developers to find deep usage of URDNA2015 more easily.
  - These may exist as long as the URDNA2015 alias support exists. Both
    are not expected to have security implications.
  • Loading branch information
davidlehn committed Jun 23, 2023
1 parent 7197435 commit 1938b42
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 33 deletions.
45 changes: 42 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
[![Build status](https://img.shields.io/github/actions/workflow/status/digitalbazaar/rdf-canonize/main.yml)](https://github.com/digitalbazaar/rdf-canonize/actions/workflows/main.yml)
[![Coverage status](https://img.shields.io/codecov/c/github/digitalbazaar/rdf-canonize)](https://codecov.io/gh/digitalbazaar/rdf-canonize)

An implementation of the [RDF Dataset Canonicalization Algorithm][] in JavaScript.
An implementation of the [RDF Dataset Canonicalization][] specification in
JavaScript.

Introduction
------------

...
See the [RDF Dataset Canonicalization][] specification for details on the
specification and algorithm this library implements.

Installation
------------
Expand Down Expand Up @@ -70,6 +72,40 @@ const canonical = await canonize.canonize(dataset, {
});
```

Algorithm Support
-----------------

* "[RDFC-1.0][]": Supported.
* Primary algorithm in the [RDF Dataset Canonicalization][] specification.
* "[URDNA2015][]": Deprecated and supported as an alias for "RDFC-1.0".
* Former algorithm name that evolved into "RDFC-1.0".
* **NOTE**: There are minor differences in the [canonical N-Quads
form](https://w3c.github.io/rdf-canon/spec/#canonical-quads) that *could*
cause canonical output differences in some cases. See the 4.0.0 changelog
or code for details. If strict "URDNA2015" support is required, use a 3.x
version of this library.
* See the migration section below if you have code that uses the "URDNA2015"
algorithm name.
* "[URGNA2012][]": No longer supported.
* Older algorithm with significant differences from newer algorithms.
* Use older versions versions of this library if support is needed.

URDNA2015 Migration
-------------------

* The deprecated "URDNA2015" algorithm name is currently supported as an alias
for "RDFC-1.0".
* There is a minor difference that could cause compatibilty issues. It is
considered an edge case that will not be an issue in practice. See above for
details.
* Two tools are currently provided to help transition to "RDFC-1.0":
* If the "undocumented" API option `rejectURDNA2015` is truthy, it will cause
an error to be thrown if "URDNA2015" is used.
* If the global "RDF\_CANONIZE\_TRACE\_URDNA2015" is truthy, it will cause
`console.trace()` to be called when "URDNA2015" is used. This is designed
for *development use only* to find where "URDNA2015" is being used. It
could be *very* verbose.

Related Modules
---------------

Expand Down Expand Up @@ -127,6 +163,9 @@ Commercial support for this library is available upon request from

[Digital Bazaar]: https://digitalbazaar.com/
[JSON-LD]: https://json-ld.org/
[RDF Dataset Canonicalization Algorithm]: https://w3c.github.io/rdf-canon/spec/
[RDF Dataset Canonicalization]: https://w3c.github.io/rdf-canon/spec/
[RDFC-1.0]: https://w3c.github.io/rdf-canon/spec/
[URDNA2015]: https://w3c.github.io/rdf-canon/spec/#urdna2015
[URGNA2012]: https://w3c.github.io/rdf-canon/spec/#urgna2012
[jsonld.js]: https://github.com/digitalbazaar/jsonld.js
[rdf-canonize-native]: https://github.com/digitalbazaar/rdf-canonize-native
37 changes: 24 additions & 13 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

const URDNA2015 = require('./URDNA2015');
const URDNA2015Sync = require('./URDNA2015Sync');
const {warning} = require('./platform');

// optional native support
let rdfCanonizeNative;
Expand All @@ -60,6 +59,13 @@ function _inputToDataset(input, options) {
return input;
}

// helper to trace URDNA2015 usage
function _traceURDNA2015() {
if(!!globalThis.RDF_CANONIZE_TRACE_URDNA2015) {
console.trace('[rdf-canonize] URDNA2015 is deprecated, use RDFC-1.0');
}
}

// expose helpers
exports.NQuads = require('./NQuads');
exports.IdentifierIssuer = require('./IdentifierIssuer');
Expand Down Expand Up @@ -123,15 +129,18 @@ exports.canonize = async function(input, options) {
err ? reject(err) : resolve(canonical)));
}

if(['RDFC-1.0', 'URDNA2015'].includes(options.algorithm)) {
if(options.algorithm === 'URDNA2015') {
warning('"URDNA2015" algorithm is deprecated in favor of "RDFC-1.0"');
}
return new URDNA2015(options).main(dataset);
}
if(!('algorithm' in options)) {
throw new Error('No RDF Dataset Canonicalization algorithm specified.');
}
if(options.algorithm === 'RDFC-1.0') {
_traceURDNA2015();
return new URDNA2015(options).main(dataset);
}
// URDNA2015 deprecated, handled as alias for RDFC-1.0 if allowed
if(options.algorithm === 'URDNA2015' && !options.rejectURDNA2015) {
_traceURDNA2015();
return new URDNA2015(options).main(dataset);
}
throw new Error(
'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
};
Expand Down Expand Up @@ -177,15 +186,17 @@ exports._canonizeSync = function(input, options) {
}
return rdfCanonizeNative.canonizeSync(dataset, options);
}
if(['RDFC-1.0', 'URDNA2015'].includes(options.algorithm)) {
if(options.algorithm === 'URDNA2015') {
warning('"URDNA2015" algorithm is deprecated in favor of "RDFC-1.0"');
}
return new URDNA2015Sync(options).main(dataset);
}
if(!('algorithm' in options)) {
throw new Error('No RDF Dataset Canonicalization algorithm specified.');
}
if(options.algorithm === 'RDFC-1.0') {
return new URDNA2015Sync(options).main(dataset);
}
// URDNA2015 deprecated, handled as alias for RDFC-1.0 if allowed
if(options.algorithm === 'URDNA2015' && !options.rejectURDNA2015) {
_traceURDNA2015();
return new URDNA2015Sync(options).main(dataset);
}
throw new Error(
'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
};
8 changes: 0 additions & 8 deletions lib/platform-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,3 @@ exports.bufferToHex = function bufferToHex(buffer) {
}
return hex;
};

const seen = new Set();
exports.warning = function warning(msg) {
if(!seen.has(msg)) {
seen.add(msg);
console.warn(`WARNING[rdf-canonize]: ${msg}.`);
}
};
8 changes: 0 additions & 8 deletions lib/platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,3 @@ exports.crypto = crypto.webcrypto;
exports.bufferToHex = function bufferToHex(buffer) {
return Buffer.from(buffer).toString('hex');
};

const seen = new Set();
exports.warning = function warning(msg) {
if(!seen.has(msg)) {
seen.add(msg);
console.warn(`WARNING[rdf-canonize]: ${msg}.`);
}
};
16 changes: 15 additions & 1 deletion test/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,24 @@ _:c14n1 <urn:p1> "v1" .
assert.deepStrictEqual(canonicalIdMap, expectIdMap);
});

it('should warn when using URDNA2015', async () => {
it('should allow URDNA2015 by default', async () => {
await rdfCanonize.canonize({}, {
algorithm: 'URDNA2015',
format: 'application/n-quads'
});
});

it('should handle undocumented rejectURDNA2015 option', async () => {
let error;
try {
await rdfCanonize.canonize({}, {
algorithm: 'URDNA2015',
format: 'application/n-quads',
rejectURDNA2015: true
});
} catch(e) {
error = e;
}
assert(error);
});
});

0 comments on commit 1938b42

Please sign in to comment.