Skip to content

Commit cd4ac72

Browse files
authored
fix: cbor decode should not treat maps as objects (#36)
1 parent c4dd8a3 commit cd4ac72

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

src/cat.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ export class CommonAccessToken {
337337
plaintext as unknown as string,
338338
recipient
339339
);
340-
const decoded = cbor.decode(coseMessage).value;
340+
const decoder = new cbor.Decoder({ mapsAsObjects: false });
341+
const decoded = decoder.decode(coseMessage).value;
341342
const coseTag = new cbor.Tag(decoded, 17);
342343
const cwtTag = new cbor.Tag(coseTag, CWT_TAG);
343344
this.data = cbor.encode(cwtTag);
@@ -358,18 +359,21 @@ export class CommonAccessToken {
358359
expectCwtTag: boolean;
359360
}
360361
): Promise<void> {
361-
const coseMessage = cbor.decode(token);
362+
const decoder = new cbor.Decoder({ mapsAsObjects: false });
363+
const coseMessage = decoder.decode(token);
362364
if (opts?.expectCwtTag && coseMessage.tag !== 61) {
363365
throw new Error('Expected CWT tag');
364366
}
365367
if (coseMessage.tag === CWT_TAG) {
366368
const cborCoseMessage = cbor.encode(coseMessage.value);
367369
const buf = await cose.mac.read(cborCoseMessage, key.k);
368-
const json = await cbor.decode(buf);
370+
const json = await decoder.decode(buf);
369371
this.payload = updateMapFromClaims(json);
370372
} else {
371373
const buf = await cose.mac.read(token, key.k);
372-
this.payload = await cbor.decode(Buffer.from(buf.toString('hex'), 'hex'));
374+
this.payload = await decoder.decode(
375+
Buffer.from(buf.toString('hex'), 'hex')
376+
);
373377
}
374378
this.kid = key.kid;
375379
}

src/catif.ts

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { claimsToLabels, CommonAccessTokenDict, labelsToClaim } from './cat';
2+
import { CommonAccessTokenUri } from './catu';
23

34
type CatIfValue = Map<number, [number, { [key: string]: string }]>;
45
export type CommonAccessTokenIfMap = Map<number, CatIfValue>;
@@ -11,9 +12,59 @@ export type CatIfDictValue = {
1112
];
1213
};
1314

15+
const valueToDict: { [key: string]: (value: any) => any } = {
16+
exp: (value) => {
17+
const [code, headers, kid] = value;
18+
return [code, valueToDict['location'](headers.get('Location')), kid];
19+
},
20+
location: (value) => {
21+
if (typeof value === 'string') {
22+
return { Location: value };
23+
} else {
24+
const [url, map] = value;
25+
const obj: { [key: string]: any } = {};
26+
(map as Map<string, any>).forEach((v, claim) => {
27+
obj[claim] = valueToDict[claim] ? valueToDict[claim](v) : v;
28+
});
29+
return { Location: [url, obj] };
30+
}
31+
},
32+
catu: (value) => CommonAccessTokenUri.fromUnlabeledMap(value).toDict()
33+
};
34+
35+
const dictToValue: { [key: string]: (value: any) => any } = {
36+
exp: (value) => {
37+
const [code, headers, kid] = value;
38+
return [code, dictToValue['location'](headers['Location']), kid];
39+
},
40+
location: (value) => {
41+
if (typeof value === 'string') {
42+
const map = new Map<string, any>();
43+
map.set('Location', value);
44+
return map;
45+
} else {
46+
const [url, dict] = value;
47+
const lmap = new Map<string, any>();
48+
for (const key in dict) {
49+
lmap.set(
50+
key,
51+
dictToValue[key] ? dictToValue[key](dict[key]) : dict[key]
52+
);
53+
}
54+
const map = new Map<string, any>();
55+
map.set('Location', [url, lmap]);
56+
return map;
57+
}
58+
},
59+
catu: (value) => CommonAccessTokenUri.fromDict(value).payload
60+
};
61+
1462
export class CommonAccessTokenIf {
1563
private catIfMap: CommonAccessTokenIfMap = new Map();
1664

65+
/**
66+
* Create a CATIF claim from a dictionary with numbers as keys (labels)
67+
*/
1768
public static fromDictTags(dict: { [key: number]: any }) {
1869
const newDict: { [key: string]: any } = {};
1970
for (const key in dict) {
@@ -23,14 +74,24 @@ export class CommonAccessTokenIf {
2374
return CommonAccessTokenIf.fromDict(newDict);
2475
}
2576

77+
/**
78+
* Create a CATIF claim from a dictionary with string as keys
79+
*/
2680
public static fromDict(dict: { [key: string]: any }) {
2781
const catif = new CommonAccessTokenIf();
2882
for (const catIfClaim in dict) {
29-
catif.catIfMap.set(claimsToLabels[catIfClaim], dict[catIfClaim]);
83+
const v = dict[catIfClaim];
84+
catif.catIfMap.set(
85+
claimsToLabels[catIfClaim],
86+
dictToValue[catIfClaim] ? dictToValue[catIfClaim](v) : v
87+
);
3088
}
3189
return catif;
3290
}
3391

92+
/**
93+
* Create a CATIF claim from a map with string as keys
94+
*/
3495
public static fromMap(map: CommonAccessTokenIfMap) {
3596
const catif = new CommonAccessTokenIf();
3697
catif.catIfMap = map;
@@ -40,7 +101,8 @@ export class CommonAccessTokenIf {
40101
toDict() {
41102
const result: { [key: string]: any } = {};
42103
this.catIfMap.forEach((catIfValue, claim) => {
43-
result[labelsToClaim[claim]] = catIfValue;
104+
result[labelsToClaim[claim]] =
105+
valueToDict[labelsToClaim[claim]](catIfValue);
44106
});
45107
return result;
46108
}

src/catu.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ export type CommonAccessTokenUriMap = Map<number, UriPartMap>;
4848
export class CommonAccessTokenUri {
4949
private catuMap: CommonAccessTokenUriMap = new Map();
5050

51+
/**
52+
* Create a CATU claim from a dictionary with numbers as keys (labels)
53+
*/
5154
public static fromDictTags(dict: { [key: number]: any }) {
5255
const newDict: { [key: string]: any } = {};
5356
for (const uriPartTag in dict) {
@@ -61,6 +64,9 @@ export class CommonAccessTokenUri {
6164
return CommonAccessTokenUri.fromDict(newDict);
6265
}
6366

67+
/**
68+
* Create a CATU claim from a dictionary with string as keys
69+
*/
6470
public static fromDict(dict: { [key: string]: any }) {
6571
const catu = new CommonAccessTokenUri();
6672
for (const uriPart in dict) {
@@ -73,6 +79,25 @@ export class CommonAccessTokenUri {
7379
return catu;
7480
}
7581

82+
/**
83+
* Create a CATU claim from a map with string as keys
84+
*/
85+
public static fromUnlabeledMap(unLabeledMap: Map<string, any>) {
86+
const map: CommonAccessTokenUriMap = new Map();
87+
unLabeledMap.forEach((value, uriPart) => {
88+
const uriPartLabel = uriPartToLabels[uriPart];
89+
const matchMap = new Map<number, MatchValue>();
90+
value.forEach((v: any, matchPart: string) => {
91+
matchMap.set(matchToLabels[matchPart], v);
92+
});
93+
map.set(uriPartLabel, matchMap);
94+
});
95+
return CommonAccessTokenUri.fromMap(map);
96+
}
97+
98+
/**
99+
* Create a CATU claim from a map with number as keys
100+
*/
76101
public static fromMap(map: CommonAccessTokenUriMap) {
77102
const catu = new CommonAccessTokenUri();
78103
catu.catuMap = map;

0 commit comments

Comments
 (0)