@sphereon/ssi-sdk.vc-status-list 0.33.1-feature.vcdm2.tsup.50 → 0.33.1-feature.vcdm2.tsup.51
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/dist/index.cjs +40 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +40 -40
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/impl/encoding/cbor.ts +55 -50
|
@@ -1,14 +1,24 @@
|
|
|
1
|
+
import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
|
|
1
2
|
import { StatusList } from '@sd-jwt/jwt-status-list'
|
|
2
3
|
import { deflate, inflate } from 'pako'
|
|
3
|
-
import
|
|
4
|
+
import { com, kotlin } from '@sphereon/kmp-mdoc-core'
|
|
5
|
+
// import * as cborpkg from '@sphereon/kmp-cbor'
|
|
4
6
|
import base64url from 'base64url'
|
|
5
7
|
import type { IRequiredContext, SignedStatusListData } from '../../types'
|
|
6
8
|
import { type DecodedStatusListPayload, resolveIdentifier } from './common'
|
|
7
|
-
import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
10
|
+
export type IKey = com.sphereon.crypto.IKey
|
|
11
|
+
export type CborItem<T> = com.sphereon.cbor.CborItem<T>
|
|
12
|
+
export const CborByteString = com.sphereon.cbor.CborByteString
|
|
13
|
+
export type CborByteStringType = com.sphereon.cbor.CborByteString
|
|
14
|
+
export const CborUInt = com.sphereon.cbor.CborUInt
|
|
15
|
+
export type CborUIntType = com.sphereon.cbor.CborUInt
|
|
16
|
+
export const CborString = com.sphereon.cbor.CborString
|
|
17
|
+
export type CborStringType = com.sphereon.cbor.CborString
|
|
18
|
+
|
|
19
|
+
// const cbor = cborpkg.com.sphereon.cbor
|
|
20
|
+
// const kmp = cborpkg.com.sphereon.kmp
|
|
21
|
+
// const kotlin = cborpkg.kotlin
|
|
12
22
|
const decompressRawStatusList = (StatusList as any).decodeStatusList.bind(StatusList)
|
|
13
23
|
|
|
14
24
|
const CWT_CLAIMS = {
|
|
@@ -34,23 +44,26 @@ export const createSignedCbor = async (
|
|
|
34
44
|
const compressedList = deflate(encodeStatusList, { level: 9 })
|
|
35
45
|
const compressedBytes = new Int8Array(compressedList)
|
|
36
46
|
|
|
37
|
-
const statusListMap = new cbor.CborMap(
|
|
47
|
+
const statusListMap = new com.sphereon.cbor.CborMap(
|
|
38
48
|
kotlin.collections.KtMutableMap.fromJsMap(
|
|
39
|
-
new Map<
|
|
40
|
-
[
|
|
41
|
-
|
|
49
|
+
new Map<CborStringType, CborItem<any>>([
|
|
50
|
+
[
|
|
51
|
+
new com.sphereon.cbor.CborString('bits'),
|
|
52
|
+
new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(statusList.getBitsPerStatus())),
|
|
53
|
+
],
|
|
54
|
+
[new com.sphereon.cbor.CborString('lst'), new com.sphereon.cbor.CborByteString(compressedBytes)],
|
|
42
55
|
]),
|
|
43
56
|
),
|
|
44
57
|
)
|
|
45
58
|
|
|
46
|
-
const protectedHeader = new cbor.CborMap(
|
|
59
|
+
const protectedHeader = new com.sphereon.cbor.CborMap(
|
|
47
60
|
kotlin.collections.KtMutableMap.fromJsMap(
|
|
48
|
-
new Map([[new cbor.CborUInt(kmp.LongKMP.fromNumber(16)), new cbor.CborString('statuslist+cwt')]]), // "type"
|
|
61
|
+
new Map([[new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(16)), new com.sphereon.cbor.CborString('statuslist+cwt')]]), // "type"
|
|
49
62
|
),
|
|
50
63
|
)
|
|
51
|
-
const protectedHeaderEncoded = cbor.Cbor.encode(protectedHeader)
|
|
64
|
+
const protectedHeaderEncoded = com.sphereon.cbor.Cbor.encode(protectedHeader)
|
|
52
65
|
const claimsMap = buildClaimsMap(id, issuerString, statusListMap, expiresAt)
|
|
53
|
-
const claimsEncoded: Int8Array = cbor.Cbor.encode(claimsMap)
|
|
66
|
+
const claimsEncoded: Int8Array = com.sphereon.cbor.Cbor.encode(claimsMap)
|
|
54
67
|
|
|
55
68
|
const signedCWT: string = await context.agent.keyManagerSign({
|
|
56
69
|
keyRef: identifier.kmsKeyRef,
|
|
@@ -63,13 +76,13 @@ export const createSignedCbor = async (
|
|
|
63
76
|
const signatureBytes = base64url.decode(signedCWT)
|
|
64
77
|
const signatureInt8 = new Int8Array(Buffer.from(signatureBytes))
|
|
65
78
|
|
|
66
|
-
const cwtArrayElements: Array<
|
|
67
|
-
new
|
|
68
|
-
new
|
|
69
|
-
new
|
|
79
|
+
const cwtArrayElements: Array<CborItem<any>> = [
|
|
80
|
+
new CborByteString(protectedHeaderEncodedInt8),
|
|
81
|
+
new CborByteString(claimsEncodedInt8),
|
|
82
|
+
new CborByteString(signatureInt8),
|
|
70
83
|
]
|
|
71
|
-
const cwtArray = new cbor.CborArray(kotlin.collections.KtMutableList.fromJsArray(cwtArrayElements))
|
|
72
|
-
const cwtEncoded = cbor.Cbor.encode(cwtArray)
|
|
84
|
+
const cwtArray = new com.sphereon.cbor.CborArray(kotlin.collections.KtMutableList.fromJsArray(cwtArrayElements))
|
|
85
|
+
const cwtEncoded = com.sphereon.cbor.Cbor.encode(cwtArray)
|
|
73
86
|
const cwtBuffer = Buffer.from(cwtEncoded)
|
|
74
87
|
return {
|
|
75
88
|
statusListCredential: base64url.encode(cwtBuffer),
|
|
@@ -77,43 +90,38 @@ export const createSignedCbor = async (
|
|
|
77
90
|
}
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
function buildClaimsMap(
|
|
81
|
-
id: string,
|
|
82
|
-
issuerString: string,
|
|
83
|
-
statusListMap: cborpkg.com.sphereon.cbor.CborMap<cborpkg.com.sphereon.cbor.CborString, cborpkg.com.sphereon.cbor.CborItem<any>>,
|
|
84
|
-
expiresAt?: Date,
|
|
85
|
-
) {
|
|
93
|
+
function buildClaimsMap(id: string, issuerString: string, statusListMap: com.sphereon.cbor.CborMap<CborStringType, CborItem<any>>, expiresAt?: Date) {
|
|
86
94
|
const ttl = 65535 // FIXME figure out what value should be / come from and what the difference is with exp
|
|
87
|
-
const claimsEntries: Array<[
|
|
88
|
-
[new
|
|
89
|
-
[new
|
|
95
|
+
const claimsEntries: Array<[CborUIntType, CborItem<any>]> = [
|
|
96
|
+
[new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.SUBJECT)), new com.sphereon.cbor.CborString(id)], // "sub"
|
|
97
|
+
[new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.ISSUER)), new com.sphereon.cbor.CborString(issuerString)], // "iss"
|
|
90
98
|
[
|
|
91
|
-
new
|
|
92
|
-
new
|
|
99
|
+
new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.ISSUED_AT)),
|
|
100
|
+
new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(Math.floor(Date.now() / 1000))), // "iat"
|
|
93
101
|
],
|
|
94
102
|
]
|
|
95
103
|
|
|
96
104
|
if (expiresAt) {
|
|
97
105
|
claimsEntries.push([
|
|
98
|
-
new cbor.CborUInt(kmp.LongKMP.fromNumber(CWT_CLAIMS.EXPIRATION)),
|
|
99
|
-
new cbor.CborUInt(kmp.LongKMP.fromNumber(Math.floor(expiresAt.getTime() / 1000))), // "exp"
|
|
106
|
+
new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.EXPIRATION)),
|
|
107
|
+
new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(Math.floor(expiresAt.getTime() / 1000))), // "exp"
|
|
100
108
|
])
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
if (ttl) {
|
|
104
112
|
claimsEntries.push([
|
|
105
|
-
new cbor.CborUInt(kmp.LongKMP.fromNumber(CWT_CLAIMS.TIME_TO_LIVE)),
|
|
106
|
-
new cbor.CborUInt(kmp.LongKMP.fromNumber(ttl)), // "time to live"
|
|
113
|
+
new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.TIME_TO_LIVE)),
|
|
114
|
+
new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(ttl)), // "time to live"
|
|
107
115
|
])
|
|
108
116
|
}
|
|
109
117
|
|
|
110
|
-
claimsEntries.push([new cbor.CborUInt(kmp.LongKMP.fromNumber(CWT_CLAIMS.STATUS_LIST)), statusListMap])
|
|
118
|
+
claimsEntries.push([new com.sphereon.cbor.CborUInt(com.sphereon.kmp.LongKMP.fromNumber(CWT_CLAIMS.STATUS_LIST)), statusListMap])
|
|
111
119
|
|
|
112
|
-
const claimsMap = new cbor.CborMap(kotlin.collections.KtMutableMap.fromJsMap(new Map(claimsEntries)))
|
|
120
|
+
const claimsMap = new com.sphereon.cbor.CborMap(kotlin.collections.KtMutableMap.fromJsMap(new Map(claimsEntries)))
|
|
113
121
|
return claimsMap
|
|
114
122
|
}
|
|
115
123
|
|
|
116
|
-
const getCborValueFromMap = <T>(map: Map<
|
|
124
|
+
const getCborValueFromMap = <T>(map: Map<CborItem<any>, CborItem<any>>, key: number): T => {
|
|
117
125
|
const value = getCborOptionalValueFromMap<T>(map, key)
|
|
118
126
|
if (value === undefined) {
|
|
119
127
|
throw new Error(`Required claim ${key} not found`)
|
|
@@ -121,11 +129,8 @@ const getCborValueFromMap = <T>(map: Map<cborpkg.com.sphereon.cbor.CborItem<any>
|
|
|
121
129
|
return value
|
|
122
130
|
}
|
|
123
131
|
|
|
124
|
-
const getCborOptionalValueFromMap = <T>(
|
|
125
|
-
map
|
|
126
|
-
key: number,
|
|
127
|
-
): T | undefined | never => {
|
|
128
|
-
const value = map.get(new cborpkg.com.sphereon.cbor.CborUInt(kmp.LongKMP.fromNumber(key)))
|
|
132
|
+
const getCborOptionalValueFromMap = <T>(map: Map<CborItem<any>, CborItem<any>>, key: number): T | undefined | never => {
|
|
133
|
+
const value = map.get(new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(key)))
|
|
129
134
|
if (!value) {
|
|
130
135
|
return undefined
|
|
131
136
|
}
|
|
@@ -135,28 +140,28 @@ const getCborOptionalValueFromMap = <T>(
|
|
|
135
140
|
export const decodeStatusListCWT = (cwt: string): DecodedStatusListPayload => {
|
|
136
141
|
const encodedCbor = base64url.toBuffer(cwt)
|
|
137
142
|
const encodedCborArray = new Int8Array(encodedCbor)
|
|
138
|
-
const decodedCbor =
|
|
143
|
+
const decodedCbor = com.sphereon.cbor.Cbor.decode(encodedCborArray)
|
|
139
144
|
|
|
140
|
-
if (!(decodedCbor instanceof
|
|
145
|
+
if (!(decodedCbor instanceof com.sphereon.cbor.CborArray)) {
|
|
141
146
|
throw new Error('Invalid CWT format: Expected a CBOR array')
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
const [, payload] = decodedCbor.value.asJsArrayView()
|
|
145
|
-
if (!(payload instanceof
|
|
150
|
+
if (!(payload instanceof com.sphereon.cbor.CborByteString)) {
|
|
146
151
|
throw new Error('Invalid payload format: Expected a CBOR ByteString')
|
|
147
152
|
}
|
|
148
153
|
|
|
149
|
-
const claims =
|
|
150
|
-
if (!(claims instanceof
|
|
154
|
+
const claims = com.sphereon.cbor.Cbor.decode(payload.value)
|
|
155
|
+
if (!(claims instanceof com.sphereon.cbor.CborMap)) {
|
|
151
156
|
throw new Error('Invalid claims format: Expected a CBOR map')
|
|
152
157
|
}
|
|
153
158
|
|
|
154
159
|
const claimsMap = claims.value.asJsMapView()
|
|
155
160
|
|
|
156
|
-
const statusListMap = claimsMap.get(new
|
|
161
|
+
const statusListMap = claimsMap.get(new CborUInt(com.sphereon.kmp.LongKMP.fromNumber(65533))).value.asJsMapView()
|
|
157
162
|
|
|
158
|
-
const bits = Number(statusListMap.get(new
|
|
159
|
-
const decoded = new Uint8Array(statusListMap.get(new
|
|
163
|
+
const bits = Number(statusListMap.get(new CborString('bits')).value) as BitsPerStatus
|
|
164
|
+
const decoded = new Uint8Array(statusListMap.get(new CborString('lst')).value)
|
|
160
165
|
const uint8Array = inflate(decoded)
|
|
161
166
|
const rawStatusList = decompressRawStatusList(uint8Array, bits)
|
|
162
167
|
const statusList = new StatusList(rawStatusList, bits)
|