@verii/jwt 1.0.0-pre.1752076816 → 1.0.0-pre.1753171788

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@verii/jwt",
3
- "version": "1.0.0-pre.1752076816",
4
- "description": "Set of JWT related functions used in Velocity Foundation projects",
3
+ "version": "1.0.0-pre.1753171788",
4
+ "description": "Set of JWT related functions used in Verii projects",
5
5
  "repository": "https://github.com/LFDT-Verii/core",
6
6
  "main": "index.js",
7
7
  "publishConfig": {
@@ -16,14 +16,15 @@
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
18
  "@trust/keyto": "~2.0.0-alpha1",
19
- "@verii/crypto": "1.0.0-pre.1752076816",
19
+ "@verii/crypto": "1.0.0-pre.1753171788",
20
+ "canonicalize": "^2.1.0",
20
21
  "date-fns": "~3.6.0",
21
22
  "jose": "~5.10.0",
22
23
  "lodash": "^4.17.21"
23
24
  },
24
25
  "devDependencies": {
25
- "@verii/sample-data": "1.0.0-pre.1752076816",
26
- "@verii/test-regexes": "1.0.0-pre.1752076816",
26
+ "@verii/sample-data": "1.0.0-pre.1753171788",
27
+ "@verii/test-regexes": "1.0.0-pre.1753171788",
27
28
  "eslint": "8.57.1",
28
29
  "eslint-config-airbnb-base": "14.2.1",
29
30
  "eslint-config-prettier": "8.10.0",
@@ -42,5 +43,5 @@
42
43
  "lib"
43
44
  ]
44
45
  },
45
- "gitHead": "5885ce94149cc0102b2bc9cde18834293174bfaf"
46
+ "gitHead": "e6116b2410d04efa61841268ab1b378e1c1c6060"
46
47
  }
package/src/core.js CHANGED
@@ -21,9 +21,14 @@ const {
21
21
  calculateJwkThumbprint,
22
22
  decodeJwt,
23
23
  decodeProtectedHeader,
24
+ base64url,
24
25
  } = require('jose');
26
+ const canonicalize = require('canonicalize');
27
+
28
+ const utf8Decoder = new TextDecoder('utf-8');
25
29
  const keyto = require('@trust/keyto');
26
30
  const { flow, isString, startsWith, split, omit } = require('lodash/fp');
31
+ const { KeyAlgorithms } = require('@verii/crypto');
27
32
  const {
28
33
  setIssuedAt,
29
34
  setOptionalNotBefore,
@@ -35,8 +40,11 @@ const {
35
40
  setOptionalSubject,
36
41
  } = require('./jwt-fp');
37
42
 
43
+ const keyAlgorithmToJoseAlg = (keyAlgorithm = KeyAlgorithms.SECP256K1) =>
44
+ keyAlgorithm === KeyAlgorithms.SECP256K1 ? 'ES256K' : keyAlgorithm;
45
+
38
46
  const toKeyObject = (key, header) => {
39
- const alg = header?.alg ?? key.alg ?? 'ES256K';
47
+ const alg = keyAlgorithmToJoseAlg(header?.alg ?? key.alg);
40
48
  return importJWK(key, alg);
41
49
  };
42
50
 
@@ -132,6 +140,13 @@ const jwkFromStringified = (key, priv = true) => {
132
140
  return k.toJwk(priv ? 'private' : 'public');
133
141
  };
134
142
 
143
+ const base64UrlToJwk = (base64String) => {
144
+ const buffer = base64url.decode(base64String);
145
+ return JSON.parse(utf8Decoder.decode(buffer));
146
+ };
147
+
148
+ const jwkToPublicBase64Url = (json) => base64url.encode(canonicalize(json));
149
+
135
150
  const jwkThumbprint = calculateJwkThumbprint;
136
151
 
137
152
  const jwtHeaderDecode = decodeProtectedHeader;
@@ -187,11 +202,13 @@ const toJwk = (key, priv = true) => {
187
202
  const prepAlgAndKey = async (keyOrSecret, optionsAlg) =>
188
203
  isString(keyOrSecret)
189
204
  ? {
190
- alg: optionsAlg ?? DEFAULT_SYMMETRIC_ALG,
205
+ alg: keyAlgorithmToJoseAlg(optionsAlg ?? DEFAULT_SYMMETRIC_ALG),
191
206
  key: new TextEncoder().encode(keyOrSecret),
192
207
  }
193
208
  : {
194
- alg: keyOrSecret.alg ?? optionsAlg ?? DEFAULT_ASYMMETRIC_ALG,
209
+ alg: keyAlgorithmToJoseAlg(
210
+ keyOrSecret.alg ?? optionsAlg ?? DEFAULT_ASYMMETRIC_ALG
211
+ ),
195
212
  key: await toKeyObject(keyOrSecret),
196
213
  };
197
214
 
@@ -211,4 +228,7 @@ module.exports = {
211
228
  stringifyJwk,
212
229
  tamperJwt,
213
230
  toJwk,
231
+ base64UrlToJwk,
232
+ jwkToPublicBase64Url,
233
+ keyAlgorithmToJoseAlg,
214
234
  };
package/src/docs.js CHANGED
@@ -14,15 +14,16 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- const { omit } = require('lodash/fp');
17
+ const { pick } = require('lodash/fp');
18
18
  const { jwkFromSecp256k1Key, jwtSign } = require('./core');
19
19
 
20
20
  const DEFAULT_NOT_BEFORE = '0s';
21
+ const PUBLIC_JWK_PROPS = ['x', 'y', 'e', 'n', 'kty', 'crv', 'use'];
21
22
 
22
23
  const docJti = (doc, options) => (options?.jti != null ? {} : { jti: doc.id });
23
24
 
24
25
  const headerKey = (jwk, kid) =>
25
- kid != null ? { kid } : { jwk: omit(['d'], jwk) };
26
+ kid != null ? { kid } : { jwk: pick(PUBLIC_JWK_PROPS, jwk) };
26
27
 
27
28
  const generateDocJwt = (doc, key, { kid, ...options } = {}) => {
28
29
  const jwk = key.kty != null ? key : jwkFromSecp256k1Key(key);
package/src/vc-mappers.js CHANGED
@@ -17,11 +17,20 @@
17
17
 
18
18
  const { omit } = require('lodash/fp');
19
19
  const { getUnixTime } = require('date-fns/fp');
20
+ const { keyAlgorithmToJoseAlg } = require('./core');
20
21
 
21
22
  // Using credential structure as defined at: https://w3c.github.io/vc-imp-guide/ conformant to JWS JSON Serialization
22
23
  // https://www.rfc-editor.org/rfc/rfc7515#section-7.2.1,
23
- const jsonLdToUnsignedVcJwtContent = (jsonldCredential, kid) => {
24
- const header = { kid, typ: 'JWT' };
24
+ const jsonLdToUnsignedVcJwtContent = (
25
+ jsonldCredential,
26
+ signatureAlgorithm,
27
+ kid
28
+ ) => {
29
+ const header = {
30
+ kid,
31
+ alg: keyAlgorithmToJoseAlg(signatureAlgorithm),
32
+ typ: 'JWT',
33
+ };
25
34
  const iat = getUnixTime(
26
35
  new Date(
27
36
  jsonldCredential.issued ?? jsonldCredential.issuanceDate ?? new Date()
@@ -21,7 +21,7 @@ const { getExpirationISODate, getIssuerId } = require('./vc-mappers');
21
21
 
22
22
  // Using credential structure as defined at: https://w3c.github.io/vc-imp-guide/
23
23
  // Using JWT structure as defined at: https://www.w3.org/TR/vc-data-model/#json-web-token
24
- const generateCredentialJwt = (credentialWrapper, key, kid) => {
24
+ const generateCredentialJwt = (credentialWrapper, key, kid, alg) => {
25
25
  const credential = unwrap('vc', credentialWrapper);
26
26
  const payload = {
27
27
  vc: {
@@ -36,21 +36,22 @@ const generateCredentialJwt = (credentialWrapper, key, kid) => {
36
36
  payload.sub_jwk = credential.credentialSubject.jwk;
37
37
  }
38
38
 
39
- const options = {
39
+ const opts = {
40
40
  ...docJti(credential),
41
41
  ...iatAndNbf(credential),
42
42
  ...issCredential(credential),
43
43
  ...exp(credential),
44
44
  ...sub(credential),
45
45
  kid,
46
+ alg,
46
47
  };
47
48
 
48
- return generateDocJwt(payload, key, options);
49
+ return generateDocJwt(payload, key, opts);
49
50
  };
50
51
 
51
52
  // Using presentation structure as defined at: https://w3c.github.io/vc-imp-guide/
52
53
  // Using JWT structure as defined at: https://www.w3.org/TR/vc-data-model/#json-web-token
53
- const generatePresentationJwt = (presentationWrapper, key, kid) => {
54
+ const generatePresentationJwt = (presentationWrapper, key, kid, alg) => {
54
55
  const presentation = unwrap('vp', presentationWrapper);
55
56
  const payload = {
56
57
  vp: {
@@ -67,6 +68,7 @@ const generatePresentationJwt = (presentationWrapper, key, kid) => {
67
68
  ...issPresentation(presentation),
68
69
  ...aud(presentation),
69
70
  kid,
71
+ alg,
70
72
  };
71
73
 
72
74
  return generateDocJwt(payload, key, options);