fiftyone.pipeline.did 4.5.37 → 4.5.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/owid/README.md +12 -0
- package/node_modules/owid/owid.crypto.test.js +58 -5
- package/node_modules/owid/owid.interop.test.js +20 -3
- package/node_modules/owid/owid.published-key.test.js +253 -0
- package/node_modules/owid/owid.test.js +6 -1
- package/node_modules/owid/testdata/51did-identifier.json +6 -0
- package/node_modules/owid/testdata/51did-public-keys.json +182 -0
- package/node_modules/owid/v1.js +19 -3
- package/package.json +2 -2
- package/readme.md +1 -1
|
@@ -22,6 +22,12 @@ public key from their well known end point and verifies the ECDSA signature
|
|
|
22
22
|
locally. When `crypto.subtle` is not available it falls back to the creator's
|
|
23
23
|
remote verify end point.
|
|
24
24
|
|
|
25
|
+
Both end points are versioned, `/owid/api/v<version>/creator` and
|
|
26
|
+
`/owid/api/v<version>/verify`, and the version in the path is the version
|
|
27
|
+
byte of the OWID being verified rather than a fixed number, because a
|
|
28
|
+
creator serves each version of the format at its own path and returns 404
|
|
29
|
+
for the others.
|
|
30
|
+
|
|
25
31
|
The public key is requested for the OWID's own creation date
|
|
26
32
|
(`?date=<minutes>`), so OWIDs signed before a signing-key rotation still
|
|
27
33
|
verify. A creator that does not support the `date` parameter ignores it and
|
|
@@ -38,6 +44,12 @@ The headers are sent to every creator domain that a verification touches,
|
|
|
38
44
|
so only set a credential that all the creators in the tree are meant to
|
|
39
45
|
see.
|
|
40
46
|
|
|
47
|
+
A custom header makes the key request a non simple cross origin request, so
|
|
48
|
+
the browser sends a `OPTIONS` preflight first and the creator has to answer
|
|
49
|
+
it with `Access-Control-Allow-Headers` naming that header. A creator that
|
|
50
|
+
does not answer the preflight cannot be given a credential this way, and
|
|
51
|
+
the request never leaves the browser.
|
|
52
|
+
|
|
41
53
|
## Reading answers instead of throwing
|
|
42
54
|
|
|
43
55
|
An OWID is read from whatever a caller was handed, which on a public end
|
|
@@ -45,6 +45,25 @@ const otherKeyPair = nodeCrypto.generateKeyPairSync('ec', {
|
|
|
45
45
|
// 2021-04-06 12:59 UTC expressed as minutes since 2020-01-01 00:00 UTC.
|
|
46
46
|
const testDateInMinutes = 664619;
|
|
47
47
|
|
|
48
|
+
// The version byte every OWID built here is written with. The mocked
|
|
49
|
+
// creator only answers the path for this version, and the expected URL is
|
|
50
|
+
// built from the version the library read back out of the OWID, so the test
|
|
51
|
+
// and the library take the version from the same place and a wrong version
|
|
52
|
+
// in either one fails rather than passing quietly.
|
|
53
|
+
const testVersion = 3;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The creator key URL the library must request for an OWID. The version
|
|
57
|
+
* segment comes from the OWID's own version byte, which is the value the
|
|
58
|
+
* library uses, so this expectation cannot drift away from the code.
|
|
59
|
+
* @param {Object} o - the OWID that was read.
|
|
60
|
+
* @returns {string} the expected URL.
|
|
61
|
+
*/
|
|
62
|
+
function expectedCreatorUrl(o) {
|
|
63
|
+
return "//" + o.domain + "/owid/api/v" + o.version +
|
|
64
|
+
"/creator?date=" + o.date;
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
/**
|
|
49
68
|
* Reads an OWID that the test expects to be valid, asserting the three facts
|
|
50
69
|
* a read always reports before handing back the OWID itself.
|
|
@@ -64,8 +83,9 @@ const wrongKeyDomain = "wrong-key.swan-demo.uk";
|
|
|
64
83
|
const emptyKeyDomain = "empty-key.swan-demo.uk";
|
|
65
84
|
|
|
66
85
|
/**
|
|
67
|
-
* Builds the unsigned portion of
|
|
68
|
-
* same form the library serializes for
|
|
86
|
+
* Builds the unsigned portion of an OWID, at the version named by
|
|
87
|
+
* testVersion, as a byte array in the same form the library serializes for
|
|
88
|
+
* verification.
|
|
69
89
|
* @param {string} domain - the creator domain.
|
|
70
90
|
* @param {number} dateInMinutes - minutes since the OWID base date.
|
|
71
91
|
* @param {Buffer} payload - the payload bytes.
|
|
@@ -77,7 +97,7 @@ function buildUnsignedOWID(domain, dateInMinutes, payload) {
|
|
|
77
97
|
var length = Buffer.alloc(4);
|
|
78
98
|
length.writeUInt32LE(payload.length);
|
|
79
99
|
return Buffer.concat([
|
|
80
|
-
Buffer.from([
|
|
100
|
+
Buffer.from([testVersion]),
|
|
81
101
|
Buffer.from(domain, 'ascii'),
|
|
82
102
|
Buffer.from([0]),
|
|
83
103
|
date,
|
|
@@ -132,7 +152,10 @@ beforeEach(() => {
|
|
|
132
152
|
}
|
|
133
153
|
var url = new URL(urlString);
|
|
134
154
|
|
|
135
|
-
|
|
155
|
+
// A real creator serves each version of the format at its own
|
|
156
|
+
// path and returns 404 for the others, so answering any version
|
|
157
|
+
// here would hide a request sent to the wrong one.
|
|
158
|
+
if (url.pathname === "/owid/api/v" + testVersion + "/creator") {
|
|
136
159
|
// This domain returns a header only PEM with no key body, which
|
|
137
160
|
// exercises the empty public key guard in the library.
|
|
138
161
|
if (url.hostname == emptyKeyDomain) {
|
|
@@ -169,8 +192,38 @@ test('crypto verify valid OWID passes', () => {
|
|
|
169
192
|
// The library must have used the public key path, so the only
|
|
170
193
|
// request is to the creator end point.
|
|
171
194
|
expect(fetch.mock.calls.length).toBe(1);
|
|
195
|
+
expect(fetch.mock.calls[0][0]).toBe(expectedCreatorUrl(o));
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('crypto verify asks the end point for the version the OWID carries', () => {
|
|
200
|
+
// Every other OWID in this suite is version 3, the same value a constant
|
|
201
|
+
// in the path would give, so this is the test that catches a constant
|
|
202
|
+
// put back. A version 2 OWID must ask the version 2 end point, which
|
|
203
|
+
// the mocked creator does not serve, so the key is unavailable and the
|
|
204
|
+
// one request that was made names the right path.
|
|
205
|
+
var date = Buffer.alloc(4);
|
|
206
|
+
date.writeUInt32LE(testDateInMinutes);
|
|
207
|
+
var payload = Buffer.from("example");
|
|
208
|
+
var length = Buffer.alloc(4);
|
|
209
|
+
length.writeUInt32LE(payload.length);
|
|
210
|
+
var unsigned = Buffer.concat([
|
|
211
|
+
Buffer.from([2]),
|
|
212
|
+
Buffer.from(creatorDomain, 'ascii'),
|
|
213
|
+
Buffer.from([0]),
|
|
214
|
+
date,
|
|
215
|
+
length,
|
|
216
|
+
payload
|
|
217
|
+
]);
|
|
218
|
+
var o = read(signOWID(unsigned, creatorKeyPair.privateKey));
|
|
219
|
+
expect(o.version).toBe(2);
|
|
220
|
+
|
|
221
|
+
return o.checkSignature().then(r => {
|
|
222
|
+
expect(r.status).toBe(owid.SignatureStatus.KEY_UNAVAILABLE);
|
|
223
|
+
expect(fetch.mock.calls.length).toBe(1);
|
|
172
224
|
expect(fetch.mock.calls[0][0]).toBe(
|
|
173
|
-
"//" + creatorDomain + "/owid/api/
|
|
225
|
+
"//" + creatorDomain + "/owid/api/v2/creator?date=" +
|
|
226
|
+
testDateInMinutes);
|
|
174
227
|
});
|
|
175
228
|
});
|
|
176
229
|
|
|
@@ -139,6 +139,18 @@ fixtures.forEach(f => {
|
|
|
139
139
|
publicKeys[f.domain] = f.publicKeySPKI;
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The creator key URL the library must request for an OWID. The version
|
|
144
|
+
* segment comes from the OWID's own version byte, which is the value the
|
|
145
|
+
* library uses, so this expectation cannot drift away from the code.
|
|
146
|
+
* @param {Object} o - the OWID that was read.
|
|
147
|
+
* @returns {string} the expected URL.
|
|
148
|
+
*/
|
|
149
|
+
function expectedCreatorUrl(o) {
|
|
150
|
+
return "//" + o.domain + "/owid/api/v" + o.version +
|
|
151
|
+
"/creator?date=" + o.date;
|
|
152
|
+
}
|
|
153
|
+
|
|
142
154
|
/**
|
|
143
155
|
* Returns the base 64 string with a single byte changed at the given offset
|
|
144
156
|
* of the decoded byte array.
|
|
@@ -164,7 +176,12 @@ beforeEach(() => {
|
|
|
164
176
|
}
|
|
165
177
|
var url = new URL(urlString);
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
// Every fixture is a version 3 OWID and a real creator serves each
|
|
180
|
+
// version of the format at its own path, returning 404 for the
|
|
181
|
+
// others, so the key is only handed back on the path that names the
|
|
182
|
+
// version the OWID was written in.
|
|
183
|
+
if (url.pathname === "/owid/api/v3/creator" &&
|
|
184
|
+
publicKeys[url.hostname]) {
|
|
168
185
|
return Promise.resolve(JSON.stringify({
|
|
169
186
|
publicKeySPKI: publicKeys[url.hostname]
|
|
170
187
|
}));
|
|
@@ -186,8 +203,8 @@ fixtures.forEach(f => {
|
|
|
186
203
|
// The library must have used the public key path, so the only
|
|
187
204
|
// request is to the creator end point.
|
|
188
205
|
expect(fetch.mock.calls.length).toBe(1);
|
|
189
|
-
expect(fetch.mock.calls[0][0]).toBe(
|
|
190
|
-
|
|
206
|
+
expect(fetch.mock.calls[0][0]).toBe(expectedCreatorUrl(o));
|
|
207
|
+
expect(o.version).toBe(3);
|
|
191
208
|
});
|
|
192
209
|
});
|
|
193
210
|
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/* ****************************************************************************
|
|
2
|
+
* Copyright 2021 51 Degrees Mobile Experts Limited (51degrees.com)
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
5
|
+
* use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
12
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
13
|
+
* License for the specific language governing permissions and limitations
|
|
14
|
+
* under the License.
|
|
15
|
+
* ***************************************************************************/
|
|
16
|
+
|
|
17
|
+
// These tests verify a real identifier issued by a live creator against that
|
|
18
|
+
// creator's real published signing key schedule, rather than against a key
|
|
19
|
+
// pair the test made up for itself. The other suites build their own OWIDs,
|
|
20
|
+
// so they prove the library is self consistent but they cannot prove it can
|
|
21
|
+
// talk to a creator that actually exists.
|
|
22
|
+
//
|
|
23
|
+
// The test data in testdata was taken on 4 September 2026 from
|
|
24
|
+
// cloud.51degrees.com, and the identifier names 51d.es as its creator. Both
|
|
25
|
+
// files are public. An identifier is meant to be handed to anyone who asks,
|
|
26
|
+
// and the key schedule is the set of public keys the creator publishes so
|
|
27
|
+
// that anyone can check a signature, so neither carries a secret and neither
|
|
28
|
+
// can be used to sign anything.
|
|
29
|
+
//
|
|
30
|
+
// The creator is stood in for here rather than called over the network, so
|
|
31
|
+
// the suite stays offline and repeatable, but the stand in behaves the way
|
|
32
|
+
// the real service does. It serves each version of the format at its own path
|
|
33
|
+
// and returns 404 for the others, and it picks the signing key by the
|
|
34
|
+
// creation date the request asks for. Both of those matter. Measured against
|
|
35
|
+
// the live service on 4 September 2026, GET /owid/api/v1/creator and
|
|
36
|
+
// /owid/api/v2/creator both answered 404 whilst /owid/api/v3/creator answered
|
|
37
|
+
// 401, meaning it exists and wants a credential.
|
|
38
|
+
|
|
39
|
+
const owid = require('./v1');
|
|
40
|
+
const nodeCrypto = require('crypto');
|
|
41
|
+
const fs = require('fs');
|
|
42
|
+
const path = require('path');
|
|
43
|
+
|
|
44
|
+
Object.defineProperty(global.self, 'crypto', {
|
|
45
|
+
value: {
|
|
46
|
+
subtle: nodeCrypto.webcrypto.subtle
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// The identifier as it was handed out, together with the facts recorded
|
|
51
|
+
// alongside it at the time it was taken.
|
|
52
|
+
const fixture = JSON.parse(fs.readFileSync(
|
|
53
|
+
path.join(__dirname, 'testdata', '51did-identifier.json'), 'utf8'));
|
|
54
|
+
|
|
55
|
+
// The creator's published signing key schedule, oldest first. A key runs from
|
|
56
|
+
// its own start until the next key starts.
|
|
57
|
+
const schedule = JSON.parse(fs.readFileSync(
|
|
58
|
+
path.join(__dirname, 'testdata', '51did-public-keys.json'), 'utf8'))
|
|
59
|
+
.slice()
|
|
60
|
+
.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
|
|
61
|
+
|
|
62
|
+
// The facts the fixture was recorded with. The identifier is a version 3
|
|
63
|
+
// OWID created on 4 September 2026 by 51d.es.
|
|
64
|
+
const expectedVersion = 3;
|
|
65
|
+
const expectedDomain = "51d.es";
|
|
66
|
+
const expectedDate = 3510720;
|
|
67
|
+
|
|
68
|
+
// The moment the stand in treats as now, in minutes since the OWID base
|
|
69
|
+
// date, being 14 September 2026, ten days after the identifier was created
|
|
70
|
+
// and in the week that followed. Every port's stand in uses this moment. A
|
|
71
|
+
// real creator answers an undated request with the key in force at the
|
|
72
|
+
// moment of the request, so by then that is no longer the key that signed
|
|
73
|
+
// this identifier.
|
|
74
|
+
const requestMoment = expectedDate + 10 * 24 * 60;
|
|
75
|
+
|
|
76
|
+
// The OWID base date as a millisecond timestamp, so a date in minutes can be
|
|
77
|
+
// compared with the start of a key's window.
|
|
78
|
+
const owidBase = Date.UTC(2020, 0, 1);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Returns the key from the published schedule that was in force at the
|
|
82
|
+
* creation date a creator request asks for, which is the way a real creator
|
|
83
|
+
* answers the date parameter.
|
|
84
|
+
* @param {number} dateInMinutes - minutes since the OWID base date.
|
|
85
|
+
* @returns {Object|null} the key, or null when the date falls before the
|
|
86
|
+
* schedule starts.
|
|
87
|
+
*/
|
|
88
|
+
function keyInForceAt(dateInMinutes) {
|
|
89
|
+
var at = owidBase + dateInMinutes * 60000;
|
|
90
|
+
var found = null;
|
|
91
|
+
schedule.forEach(k => {
|
|
92
|
+
if (Date.parse(k.startsAt) <= at) {
|
|
93
|
+
found = k;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return found;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reads an OWID that the test expects to be valid, asserting the three facts
|
|
101
|
+
* a read always reports before handing back the OWID itself.
|
|
102
|
+
* @param {string} data - the OWID as base 64.
|
|
103
|
+
* @returns {Object} the OWID.
|
|
104
|
+
*/
|
|
105
|
+
function read(data) {
|
|
106
|
+
var r = owid.parse(data);
|
|
107
|
+
expect(r.ok).toBe(true);
|
|
108
|
+
expect(r.status).toBe(owid.ParseStatus.PARSED);
|
|
109
|
+
expect(r.owid).not.toBeNull();
|
|
110
|
+
return r.owid;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Stands in for the creator. Only the path naming the version given answers,
|
|
115
|
+
* every other path returns the 404 the live service returns, and the key
|
|
116
|
+
* handed back is the one in force at the date on the request unless the
|
|
117
|
+
* stand in is asked to ignore the date. As the live service does, a request
|
|
118
|
+
* naming no date is answered with the key in force at the moment of the
|
|
119
|
+
* request, a date later than that moment is read as that moment, and a date
|
|
120
|
+
* that is not a number is refused with a 400.
|
|
121
|
+
* @param {Object} [options] - servedVersion is the only version served, and
|
|
122
|
+
* ignoreDate set to true returns the key in force at requestMoment whatever
|
|
123
|
+
* date is asked for, which is what a creator that ignores the date does.
|
|
124
|
+
*/
|
|
125
|
+
function mockCreator(options) {
|
|
126
|
+
var servedVersion = options && options.servedVersion !== undefined
|
|
127
|
+
? options.servedVersion
|
|
128
|
+
: expectedVersion;
|
|
129
|
+
var ignoreDate = options && options.ignoreDate === true;
|
|
130
|
+
fetchMock.mockResponse(req => {
|
|
131
|
+
var urlString = req.url;
|
|
132
|
+
if (urlString.startsWith("//")) {
|
|
133
|
+
urlString = "https:" + urlString;
|
|
134
|
+
}
|
|
135
|
+
var url = new URL(urlString);
|
|
136
|
+
if (url.hostname !== expectedDomain ||
|
|
137
|
+
url.pathname !== "/owid/api/v" + servedVersion + "/creator") {
|
|
138
|
+
return Promise.resolve({
|
|
139
|
+
status: 404,
|
|
140
|
+
body: "Status code: 404, method not found"
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
var asked = url.searchParams.get("date");
|
|
144
|
+
var at;
|
|
145
|
+
if (ignoreDate || asked === null) {
|
|
146
|
+
at = requestMoment;
|
|
147
|
+
} else if (/^\d+$/.test(asked) === false) {
|
|
148
|
+
return Promise.resolve({
|
|
149
|
+
status: 400,
|
|
150
|
+
body: "date must be the number of minutes since 2020-01-01"
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
at = Math.min(Number(asked), requestMoment);
|
|
154
|
+
}
|
|
155
|
+
var key = keyInForceAt(at);
|
|
156
|
+
if (key === null) {
|
|
157
|
+
return Promise.resolve({
|
|
158
|
+
status: 404,
|
|
159
|
+
body: "no published key covers that date"
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return Promise.resolve(JSON.stringify({
|
|
163
|
+
publicKeySPKI: key.publicKey
|
|
164
|
+
}));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
beforeEach(() => {
|
|
169
|
+
fetchMock.resetMocks();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('the published identifier reads as the version 3 OWID it was ' +
|
|
173
|
+
'recorded as', () => {
|
|
174
|
+
var o = read(fixture.identifier);
|
|
175
|
+
|
|
176
|
+
expect(o.version).toBe(expectedVersion);
|
|
177
|
+
expect(o.domain).toBe(expectedDomain);
|
|
178
|
+
expect(o.date).toBe(expectedDate);
|
|
179
|
+
expect(o.signature.length).toBe(64);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('the published identifier verifies against the published key schedule',
|
|
183
|
+
() => {
|
|
184
|
+
mockCreator();
|
|
185
|
+
var o = read(fixture.identifier);
|
|
186
|
+
|
|
187
|
+
return o.verify().then(valid => {
|
|
188
|
+
expect(valid).toBe(true);
|
|
189
|
+
// One request, to the end point that serves the version this
|
|
190
|
+
// identifier was written in, asking for the key that was in force
|
|
191
|
+
// when it was created.
|
|
192
|
+
expect(fetch.mock.calls.length).toBe(1);
|
|
193
|
+
expect(fetch.mock.calls[0][0]).toBe(
|
|
194
|
+
"//" + o.domain + "/owid/api/v" + o.version +
|
|
195
|
+
"/creator?date=" + o.date);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('the published identifier reports a valid signature', () => {
|
|
200
|
+
mockCreator();
|
|
201
|
+
var o = read(fixture.identifier);
|
|
202
|
+
|
|
203
|
+
return o.checkSignature().then(r => {
|
|
204
|
+
expect(r.ok).toBe(true);
|
|
205
|
+
expect(r.status).toBe(owid.SignatureStatus.SIGNATURE_VALID);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test('a creator that only serves an older version leaves the signature ' +
|
|
210
|
+
'unjudged', () => {
|
|
211
|
+
// This is the outcome the library produced against the live service for
|
|
212
|
+
// as long as it asked for version 1 whatever version the OWID named.
|
|
213
|
+
// Nothing was forged and nothing was wrong with the identifier, the key
|
|
214
|
+
// simply could never be fetched.
|
|
215
|
+
mockCreator({ servedVersion: 1 });
|
|
216
|
+
var o = read(fixture.identifier);
|
|
217
|
+
|
|
218
|
+
return o.checkSignature().then(r => {
|
|
219
|
+
expect(r.ok).toBe(false);
|
|
220
|
+
expect(r.status).toBe(owid.SignatureStatus.KEY_UNAVAILABLE);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('the key is chosen by the creation date, so the key in force in the ' +
|
|
225
|
+
'following week does not verify an older identifier', () => {
|
|
226
|
+
// The key that signed this identifier is not the key in force in the
|
|
227
|
+
// following week, so a creator that ignored the date and handed back the
|
|
228
|
+
// key in force at the moment of the request would report a genuine
|
|
229
|
+
// identifier as a forgery. That is what the date parameter is for.
|
|
230
|
+
var signing = keyInForceAt(expectedDate);
|
|
231
|
+
expect(signing).not.toBeNull();
|
|
232
|
+
expect(signing.startsAt).not.toBe(keyInForceAt(requestMoment).startsAt);
|
|
233
|
+
|
|
234
|
+
mockCreator({ ignoreDate: true });
|
|
235
|
+
var o = read(fixture.identifier);
|
|
236
|
+
|
|
237
|
+
return o.verify().then(valid => {
|
|
238
|
+
expect(valid).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('the identifier verifies offline against the published key on its own',
|
|
243
|
+
() => {
|
|
244
|
+
// No network at all, which proves the fixture and the published schedule
|
|
245
|
+
// agree independently of how the creator URL is built.
|
|
246
|
+
var o = read(fixture.identifier);
|
|
247
|
+
|
|
248
|
+
return o.verifyWithPublicKey(keyInForceAt(o.date).publicKey)
|
|
249
|
+
.then(valid => {
|
|
250
|
+
expect(valid).toBe(true);
|
|
251
|
+
expect(fetch.mock.calls.length).toBe(0);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
@@ -66,7 +66,12 @@ beforeEach(() => {
|
|
|
66
66
|
}
|
|
67
67
|
var url = new URL(urlString);
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
// Every OWID these tests read is version 2, and a real creator
|
|
70
|
+
// serves each version of the format at its own path, so only the
|
|
71
|
+
// version 2 verify path answers. A request to any other version
|
|
72
|
+
// path is the defect this guards against, and it falls through to
|
|
73
|
+
// the 404 below.
|
|
74
|
+
if (url.pathname === "/owid/api/v2/verify") {
|
|
70
75
|
// The library sends the OWID being verified as form parameters
|
|
71
76
|
// in the POST body, so read them from there.
|
|
72
77
|
var body = new URLSearchParams(await req.text());
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "4.4.32-context.3",
|
|
3
|
+
"createdAt": "2026-09-04T20:37:00.4032665Z",
|
|
4
|
+
"identifier": "AzUxZC5lcwDAkTUAOAAAAAFkcBNhYL0rPISwcMhuxl0ezIe0Nywzr/lhMtzX5QjydfVQA40Aw6iylkIfGYQWecrhzDfF8g11B1KtuOBxa98MEyJZOXw3PB/EBuyOfGxZ/pu6rlt8zpCyIn1Prbu7V300bQBqrqyYfU0nNeZf/PCwLtXJRak76A==",
|
|
5
|
+
"source": "cloud.51degrees.com"
|
|
6
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"startsAt": "2026-05-11T00:00:00Z",
|
|
4
|
+
"weekStart": "2026-05-11T00:00:00Z",
|
|
5
|
+
"created": "2026-05-13T07:53:00Z",
|
|
6
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1S5u0ke8IvXO9tKBBjkNgUTLkMRR\nHcdbVUCYIDZbhOvvU2Sa7OTVfb/jDwcHwd/KVrl33uHBFHuH2E/UdBXBSw==\n-----END PUBLIC KEY-----"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"startsAt": "2026-05-18T00:00:00Z",
|
|
10
|
+
"weekStart": "2026-05-18T00:00:00Z",
|
|
11
|
+
"created": "2026-05-18T05:31:00Z",
|
|
12
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMaXEnA/hG6e9ZBIBxRnqaOspCS2f\nMDZ7MRaGMVo2CL0hcqdI4rP+KJll83xUxQq0nwwo11j/C2BwWfCbfcjFbw==\n-----END PUBLIC KEY-----"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"startsAt": "2026-05-25T00:00:00Z",
|
|
16
|
+
"weekStart": "2026-05-25T00:00:00Z",
|
|
17
|
+
"created": "2026-05-25T05:41:00Z",
|
|
18
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7GW67FrL7KfFZpxWt94xM4mgqtXB\n3jLL1gE/bcLaXVO7Myj5eo38oGTggos5iWAxlpY0bFUuqHSTkffQ+2jxog==\n-----END PUBLIC KEY-----"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"startsAt": "2026-06-01T00:00:00Z",
|
|
22
|
+
"weekStart": "2026-06-01T00:00:00Z",
|
|
23
|
+
"created": "2026-06-01T05:46:00Z",
|
|
24
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOUaE86mCaq/kUcSbfdp6lIckGvPd\nnbDr++RVrj6WmJbOXpvdKk/nFfPb27TYz1P/mT0/YgGLsNRii/DK41Ag2g==\n-----END PUBLIC KEY-----"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"startsAt": "2026-06-08T00:00:00Z",
|
|
28
|
+
"weekStart": "2026-06-08T00:00:00Z",
|
|
29
|
+
"created": "2026-06-08T05:44:00Z",
|
|
30
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6FK+7t+HkffkPe9Yhqtuy+lt8bgL\nPGUYty3nFid3mGub6QnIJFkyj9aAPe3VRcPY77Oaux78Xy+2tcdSBb91LA==\n-----END PUBLIC KEY-----"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"startsAt": "2026-06-15T00:00:00Z",
|
|
34
|
+
"weekStart": "2026-06-15T00:00:00Z",
|
|
35
|
+
"created": "2026-06-15T05:57:00Z",
|
|
36
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYU6uwIX2RJ6YtC516iCEITSs0W++\nRLM/Yo3ZmM2iCYe/HfSgqJwfy7ioVce3784+/YPgkmX8LBNwJTarVy/SmA==\n-----END PUBLIC KEY-----"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"startsAt": "2026-06-22T00:00:00Z",
|
|
40
|
+
"weekStart": "2026-06-22T00:00:00Z",
|
|
41
|
+
"created": "2026-06-22T05:59:00Z",
|
|
42
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJTOx47gMykTRMwsZq6xMrwO0+2ny\npeIxKfa6gvPWpBvDFFJMbNR9cUbHzrb0iFs1WzlKfEAjSrCtxaSfsNXkoA==\n-----END PUBLIC KEY-----"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"startsAt": "2026-06-29T00:00:00Z",
|
|
46
|
+
"weekStart": "2026-06-29T00:00:00Z",
|
|
47
|
+
"created": "2026-06-29T05:44:00Z",
|
|
48
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoKU47SHVpEjqD9txbXA4/StmOz2O\n1taTquaTes9lE+0jHB9/A8EUcodt8+oAG/YRRA6pjpe01/FlkgKIKWrhlw==\n-----END PUBLIC KEY-----"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"startsAt": "2026-07-06T00:00:00Z",
|
|
52
|
+
"weekStart": "2026-07-06T00:00:00Z",
|
|
53
|
+
"created": "2026-07-06T05:33:00Z",
|
|
54
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEx2jFmRxOqUH74IRCEPgNG0/e7FyN\neWstmBx0GVRNORYou5LtA++OlygptcuPRy/XqSy+/etiz6o8SzUiZ2F4qQ==\n-----END PUBLIC KEY-----"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"startsAt": "2026-07-13T00:00:00Z",
|
|
58
|
+
"weekStart": "2026-07-13T00:00:00Z",
|
|
59
|
+
"created": "2026-07-13T05:15:00Z",
|
|
60
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhBOts6uqkfMIjfkNtoyYxNNAFtA1\nRvkx7ZdvbvlQDDgze7YadBUmvJwMNzBNeOeyAIshl8FklLB8R2VpyAkIRg==\n-----END PUBLIC KEY-----"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"startsAt": "2026-07-20T00:00:00Z",
|
|
64
|
+
"weekStart": "2026-07-20T00:00:00Z",
|
|
65
|
+
"created": "2026-07-20T05:19:00Z",
|
|
66
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElZGKUk21yUH5DaJj41X3NiqDUoGa\niGgq/mZFQcTQkHQ2mr/Y6W6JbcSRiRFfTT21bpYd7BkatRotGtpHxXPuvQ==\n-----END PUBLIC KEY-----"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"startsAt": "2026-07-27T00:00:00Z",
|
|
70
|
+
"weekStart": "2026-07-27T00:00:00Z",
|
|
71
|
+
"created": "2026-07-27T05:22:00Z",
|
|
72
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEayA4kh6boraOurRdy4epwDcW5Gay\ntuKdpqdLtcz5yEtH4bpmJxx74ZGbStWuilAWvLutBOWp0mAjpUu5JgPE3A==\n-----END PUBLIC KEY-----"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"startsAt": "2026-08-03T00:00:00Z",
|
|
76
|
+
"weekStart": "2026-08-03T00:00:00Z",
|
|
77
|
+
"created": "2026-08-03T05:18:00Z",
|
|
78
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZMR1ut4GRhbc1dOxwXree/efQTtg\nDqzK2dicaCRO5Pz4E5ms3rDksBrv382MI0W7BgrSPR5VAtPEA93S/xcmFg==\n-----END PUBLIC KEY-----"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"startsAt": "2026-08-10T00:00:00Z",
|
|
82
|
+
"weekStart": "2026-08-10T00:00:00Z",
|
|
83
|
+
"created": "2026-08-10T04:35:00Z",
|
|
84
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2UwwNdW+L68uziCcJUegj49Xi07P\nY4EGiGgMlESa2xoJfwVHoUc6oqRNqrPBnsrqQYsU2uYlR9QOWIomui5qEw==\n-----END PUBLIC KEY-----"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"startsAt": "2026-08-17T00:00:00Z",
|
|
88
|
+
"weekStart": "2026-08-17T00:00:00Z",
|
|
89
|
+
"created": "2026-08-17T04:18:00Z",
|
|
90
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpcTDCZlVsO1glWnDqfBiTOZysOIz\ndx2eFdPbrndBTWz7fu588pjZACM2CCs03dslwehiCuOHqJtdmHQv41V6Yw==\n-----END PUBLIC KEY-----"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"startsAt": "2026-08-24T00:00:00Z",
|
|
94
|
+
"weekStart": "2026-08-24T00:00:00Z",
|
|
95
|
+
"created": "2026-08-24T04:19:00Z",
|
|
96
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJ7YEHH6liCiSn6jmcZXXydRRiCAR\nHaZHkyazSq1bsUipbYOmz3kCrk1r3DmqrqiKBWZZS64yrGckLf5UkNsteg==\n-----END PUBLIC KEY-----"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"startsAt": "2026-08-31T00:00:00Z",
|
|
100
|
+
"weekStart": "2026-08-31T00:00:00Z",
|
|
101
|
+
"created": "2026-08-31T04:21:00Z",
|
|
102
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEilbjpzqx8zx3oShIDgDoGTcBqivw\n08FKqFvRtX8rCS4Ftguvu2RwXDFLEwho0IhD/boxM1IwZ6u34hwkhf5AiQ==\n-----END PUBLIC KEY-----"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"startsAt": "2026-09-07T00:00:00Z",
|
|
106
|
+
"weekStart": "2026-09-07T00:00:00Z",
|
|
107
|
+
"created": "2026-09-01T10:54:00Z",
|
|
108
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0KhXTjSD4xyW7Zc9d+kHWPzhx1yZ\n7c3gAMCF0iFHJokWejq9FrWSVEc9bMBJPv1Br/q/oIiPTfPuhiOJ1xMkFQ==\n-----END PUBLIC KEY-----"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"startsAt": "2026-09-14T00:00:00Z",
|
|
112
|
+
"weekStart": "2026-09-14T00:00:00Z",
|
|
113
|
+
"created": "2026-09-01T10:54:00Z",
|
|
114
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEXKsoKyAZRkK9o1k4heQjAzUjHEP\nPWFnE0KKA5RI9wZHQffQcrK6rb2hcnObeZsYz7OQ/FneOMWpeiqK03OKHA==\n-----END PUBLIC KEY-----"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"startsAt": "2026-09-21T00:00:00Z",
|
|
118
|
+
"weekStart": "2026-09-21T00:00:00Z",
|
|
119
|
+
"created": "2026-09-01T10:54:00Z",
|
|
120
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFGOV57ItWDb76wzvzx+m2GWsJ+dX\n5OvtQFdPkAFV9OL4w0ntiVG0iUzZEGDRyCE5Xla82jhvA8YILz0gTdMFHQ==\n-----END PUBLIC KEY-----"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"startsAt": "2026-09-28T00:00:00Z",
|
|
124
|
+
"weekStart": "2026-09-28T00:00:00Z",
|
|
125
|
+
"created": "2026-09-01T10:54:00Z",
|
|
126
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEi85ASgFPo4LerVK/QU3J5mdaW4o\nCYRzjqNqLzRjXWoiAQTyB7LB6MwDXSv4svsh7SNpjNmOFXcjVJ3CwwoNjA==\n-----END PUBLIC KEY-----"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"startsAt": "2026-10-05T00:00:00Z",
|
|
130
|
+
"weekStart": "2026-10-05T00:00:00Z",
|
|
131
|
+
"created": "2026-09-01T10:54:00Z",
|
|
132
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoRogg/dXpCiV3psJPu9ffND7JvBm\nFg9gOgRlXrCXFBIIoEWvGb/7q1MsquKoTF1uKkHy7HEJTkr9CUvSd83CcQ==\n-----END PUBLIC KEY-----"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"startsAt": "2026-10-12T00:00:00Z",
|
|
136
|
+
"weekStart": "2026-10-12T00:00:00Z",
|
|
137
|
+
"created": "2026-09-01T10:54:00Z",
|
|
138
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBkAwOOX+Oykv6xHewe0CJuXzSGts\npAFEc82QhwzlanYJlY1lHLuP2D1xsEGOqsKXf9BOb/SesRjNHSTmi6ZGpw==\n-----END PUBLIC KEY-----"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"startsAt": "2026-10-19T00:00:00Z",
|
|
142
|
+
"weekStart": "2026-10-19T00:00:00Z",
|
|
143
|
+
"created": "2026-09-01T10:54:00Z",
|
|
144
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkkUuirYrxuFQmWjYZRWGSyvJuYcA\nOWz4zIP6c33VOKqEEtkvGJDoCV0Qm6EdgGJspDRQ2d7dtbKV2kMPnKW7UA==\n-----END PUBLIC KEY-----"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"startsAt": "2026-10-26T00:00:00Z",
|
|
148
|
+
"weekStart": "2026-10-26T00:00:00Z",
|
|
149
|
+
"created": "2026-09-01T10:54:00Z",
|
|
150
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnqgWDgDUXTqY2ZMOePx7qBFGgD/w\nepMX7HmpyRWr0XyZSUzeq2duV+VMJzNiZmQ0x34F1auNd+Dcf/3JkvXa/w==\n-----END PUBLIC KEY-----"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"startsAt": "2026-11-02T00:00:00Z",
|
|
154
|
+
"weekStart": "2026-11-02T00:00:00Z",
|
|
155
|
+
"created": "2026-09-01T10:54:00Z",
|
|
156
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENlPq/5aO/kU6VbLMipaZMukRQFre\nMsE7Tp+8CqIZA7HPi/ikrgCOOeimi5QURTjXin8JoUiVNae3SFxBRwTsYQ==\n-----END PUBLIC KEY-----"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"startsAt": "2026-11-09T00:00:00Z",
|
|
160
|
+
"weekStart": "2026-11-09T00:00:00Z",
|
|
161
|
+
"created": "2026-09-01T10:54:00Z",
|
|
162
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET3UEAs41VZiXt+SmzEzL/4pyJJxV\nwoY+sD/haSnvyRUxSurp7ju8ACZm/bDKOPtM9xmZtRbmQaU2y221EB+Okw==\n-----END PUBLIC KEY-----"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"startsAt": "2026-11-16T00:00:00Z",
|
|
166
|
+
"weekStart": "2026-11-16T00:00:00Z",
|
|
167
|
+
"created": "2026-09-01T10:54:00Z",
|
|
168
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgEbUOGc6d+rJNVrW6FSozCr3MXYr\njDf1ap19zD2pJZaRI0ORxs5A19mAEf11Nl64NT0gPI2ls9RVnMDY1tq8sg==\n-----END PUBLIC KEY-----"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"startsAt": "2026-11-23T00:00:00Z",
|
|
172
|
+
"weekStart": "2026-11-23T00:00:00Z",
|
|
173
|
+
"created": "2026-09-01T10:54:00Z",
|
|
174
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKAazotnWdw0hbDJMRJjdCwa5Eaem\nMfwA2+Aks6g7NelJ4GsU4yLhITmrmcFWexSz3JzCa+wN255rZMqiIFSHIA==\n-----END PUBLIC KEY-----"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"startsAt": "2026-11-30T00:00:00Z",
|
|
178
|
+
"weekStart": "2026-11-30T00:00:00Z",
|
|
179
|
+
"created": "2026-09-01T10:54:00Z",
|
|
180
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhDrkhpx28KTSNqXvs8vEXoUJEmLD\nqEyaVONFOZxgsnJehJqBtHVOevjptFfY6G1E6T4Opi4hH6m+/elwh8R2aA==\n-----END PUBLIC KEY-----"
|
|
181
|
+
}
|
|
182
|
+
]
|
package/node_modules/owid/v1.js
CHANGED
|
@@ -1016,6 +1016,23 @@ var owid = (function () {
|
|
|
1016
1016
|
});
|
|
1017
1017
|
}
|
|
1018
1018
|
|
|
1019
|
+
/**
|
|
1020
|
+
* Builds the URL of one of the creator's end points for the OWID being
|
|
1021
|
+
* verified. The version in the path is the OWID's own version byte,
|
|
1022
|
+
* because a creator serves each version of the format at its own path
|
|
1023
|
+
* and only the end point that understands the version an OWID was
|
|
1024
|
+
* written in can answer for it. Both the key request and the fall back
|
|
1025
|
+
* verify request are built here so the two cannot name different
|
|
1026
|
+
* versions of the same creator.
|
|
1027
|
+
* @param {Object} instance - the OWID being verified.
|
|
1028
|
+
* @param {string} method - the end point, "creator" or "verify".
|
|
1029
|
+
* @returns {string} the URL, with no query string.
|
|
1030
|
+
*/
|
|
1031
|
+
function creatorApiUrl(instance, method) {
|
|
1032
|
+
return "//" + instance.domain +
|
|
1033
|
+
"/owid/api/v" + instance.version + "/" + method;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1019
1036
|
/**
|
|
1020
1037
|
* Fetches the creator's public key and checks the signature here. The key
|
|
1021
1038
|
* is requested for the OWID's own creation date, so OWIDs signed before a
|
|
@@ -1027,7 +1044,7 @@ var owid = (function () {
|
|
|
1027
1044
|
*/
|
|
1028
1045
|
function verifyWithCreatorKey(instance, unsigned, extra) {
|
|
1029
1046
|
var subtle = getSubtle();
|
|
1030
|
-
var url =
|
|
1047
|
+
var url = creatorApiUrl(instance, "creator");
|
|
1031
1048
|
if (instance.date != null) {
|
|
1032
1049
|
url += "?date=" + instance.date;
|
|
1033
1050
|
}
|
|
@@ -1096,8 +1113,7 @@ var owid = (function () {
|
|
|
1096
1113
|
var body = new URLSearchParams();
|
|
1097
1114
|
body.append("parent", encodeBase64(joined));
|
|
1098
1115
|
body.append("owid", instance.data);
|
|
1099
|
-
var url = "
|
|
1100
|
-
"/owid/api/v" + instance.version + "/verify";
|
|
1116
|
+
var url = creatorApiUrl(instance, "verify");
|
|
1101
1117
|
return fetch(url, {
|
|
1102
1118
|
method: "POST",
|
|
1103
1119
|
mode: "cors",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fiftyone.pipeline.did",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.38",
|
|
4
4
|
"description": "Strongly typed reader for the 51Did (51Degrees Identifier) value returned by the 51Degrees Cloud service. Parses the OWID envelope and exposes the Flags, License Id and match key plus the identifier type. Compare match keys, never envelopes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"51degrees",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"author": "51Degrees Engineering <engineering@51degrees.com>",
|
|
18
18
|
"license": "EUPL-1.2",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"owid": "github:51Degrees/owid-js#
|
|
20
|
+
"owid": "github:51Degrees/owid-js#9aeb0d24"
|
|
21
21
|
},
|
|
22
22
|
"bundleDependencies": [
|
|
23
23
|
"owid"
|
package/readme.md
CHANGED
|
@@ -158,7 +158,7 @@ and `FodId.checkSignature()` run without contacting a network endpoint.
|
|
|
158
158
|
|
|
159
159
|
The library is not on the npm registry, so `package.json` names it as a
|
|
160
160
|
GitHub reference, which npm resolves by cloning the repository. The reference
|
|
161
|
-
is `github:51Degrees/owid-js#
|
|
161
|
+
is `github:51Degrees/owid-js#9aeb0d24`, the commit on `main` that carries the key selection fix
|
|
162
162
|
of the [51Degrees/owid-js](https://github.com/51Degrees/owid-js) fork. That
|
|
163
163
|
applies only when working in this repository, because the published
|
|
164
164
|
`fiftyone.pipeline.did` package carries the OWID source inside its own
|