@file-viewer/renderer-ofd 3.0.2 → 3.1.0

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-ofd",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone OFD renderer plugin for File Viewer powered by DLTech21/ofd.js.",
@@ -54,10 +54,11 @@
54
54
  "LICENSE"
55
55
  ],
56
56
  "dependencies": {
57
- "@file-viewer/core": "3.0.2",
58
- "jszip": "^3.10.1"
57
+ "@file-viewer/core": "3.1.0",
58
+ "jszip": "3.10.2"
59
59
  },
60
60
  "devDependencies": {
61
+ "@xmldom/xmldom": "0.9.12",
61
62
  "linkedom": "^0.18.12",
62
63
  "typescript": "^6.0.3"
63
64
  },
@@ -72,6 +73,7 @@
72
73
  "verify:image-placement": "node scripts/verify-image-placement.mjs",
73
74
  "verify:pageblock-render": "node scripts/verify-pageblock-render.mjs",
74
75
  "verify:render-fidelity": "node scripts/verify-render-fidelity.mjs",
75
- "verify:github-177": "pnpm --filter @file-viewer/core build && pnpm exec tsc -b tsconfig.json --force && node scripts/verify-github-177.mjs"
76
+ "verify:github-177": "pnpm --filter @file-viewer/core build && pnpm exec tsc -b tsconfig.json --force && node scripts/verify-github-177.mjs",
77
+ "verify:github-266": "node scripts/verify-github-266.mjs"
76
78
  }
77
79
  }
@@ -43,6 +43,12 @@ const appendChildValue = function (target, key, value) {
43
43
  target[key] = value;
44
44
  }
45
45
 
46
+ const xmlElementName = function (element) {
47
+ return element.namespaceURI === 'http://www.ofdspec.org/2016'
48
+ ? `ofd:${element.localName}`
49
+ : element.nodeName;
50
+ }
51
+
46
52
  const parseXmlElement = function (element, options, order) {
47
53
  const attrPrefix = options.attributeNamePrefix ?? '@_';
48
54
  const result = {};
@@ -64,7 +70,7 @@ const parseXmlElement = function (element, options, order) {
64
70
  if (parsedChild && typeof parsedChild === 'object' && pfIndex !== undefined) {
65
71
  parsedChild.pfIndex = pfIndex;
66
72
  }
67
- appendChildValue(result, child.nodeName, parsedChild);
73
+ appendChildValue(result, xmlElementName(child), parsedChild);
68
74
  continue;
69
75
  }
70
76
  if (child.nodeType === 3 || child.nodeType === 4) {
@@ -72,7 +78,10 @@ const parseXmlElement = function (element, options, order) {
72
78
  }
73
79
  }
74
80
 
75
- const text = textParts.join('').trim();
81
+ // TextCode whitespace consumes explicitly positioned glyph slots. Trimming
82
+ // it moves right-aligned dates and also shifts their DeltaX indices.
83
+ const rawText = textParts.join('');
84
+ const text = xmlElementName(element) === 'ofd:TextCode' ? rawText : rawText.trim();
76
85
  if (text) {
77
86
  if (Object.keys(result).length === 0) {
78
87
  return text;
@@ -103,7 +112,7 @@ const parseXmlToJson = function (xmlData, options = {}) {
103
112
  return {};
104
113
  }
105
114
  return {
106
- [root.nodeName]: parseXmlElement(root, options, { next: 0 })
115
+ [xmlElementName(root)]: parseXmlElement(root, options, { next: 0 })
107
116
  };
108
117
  }
109
118
 
@@ -159,18 +168,13 @@ const joinZipPath = function (...parts) {
159
168
  }
160
169
 
161
170
  const startsWithZipRoot = function (path, root) {
162
- const normalizedPath = normalizeZipPath(path);
163
- const normalizedRoot = normalizeZipPath(root);
171
+ const normalizedPath = normalizeZipPath(path).toLowerCase();
172
+ const normalizedRoot = normalizeZipPath(root).toLowerCase();
164
173
  return normalizedPath === normalizedRoot || normalizedPath.startsWith(`${normalizedRoot}/`);
165
174
  }
166
175
 
167
176
  const getZipEntry = function (zip, candidates) {
168
177
  const paths = asArray(candidates).map(normalizeZipPath).filter(Boolean);
169
- for (const path of paths) {
170
- if (zip.files[path]) {
171
- return zip.files[path];
172
- }
173
- }
174
178
  let lowerMap = zipEntryMapCache.get(zip);
175
179
  if (!lowerMap) {
176
180
  lowerMap = new Map();
@@ -180,7 +184,7 @@ const getZipEntry = function (zip, candidates) {
180
184
  zipEntryMapCache.set(zip, lowerMap);
181
185
  }
182
186
  for (const path of paths) {
183
- const entry = lowerMap.get(path.toLowerCase());
187
+ const entry = zip.files[path] || lowerMap.get(path.toLowerCase());
184
188
  if (entry) {
185
189
  return entry;
186
190
  }
@@ -190,15 +194,22 @@ const getZipEntry = function (zip, candidates) {
190
194
 
191
195
  const resolveDocumentPath = function (path, doc) {
192
196
  const normalizedPath = normalizeZipPath(path);
193
- if (!normalizedPath || startsWithZipRoot(normalizedPath, doc)) {
197
+ if (!normalizedPath || !doc || /^[\\/]/.test(String(path).trim()) || startsWithZipRoot(normalizedPath, doc)) {
194
198
  return normalizedPath;
195
199
  }
196
- return joinZipPath(doc, normalizedPath);
200
+ return joinZipPath(doc, path);
197
201
  }
198
202
 
199
- const resolveResourceCandidates = function (file, baseLoc, doc) {
203
+ const resolveResourceCandidates = function (file, baseLoc, doc, resourcePath) {
200
204
  const mediaFile = normalizeZipPath(file);
201
205
  const base = normalizeZipPath(baseLoc);
206
+ const rawFile = String(file || '').replace(/\\/g, '/').trim();
207
+ const rawBase = String(baseLoc || '').replace(/\\/g, '/').trim();
208
+ const resourceDirectory = normalizeZipPath(resourcePath).split('/').slice(0, -1).join('/');
209
+ const resourceBase = rawBase.startsWith('/') ? normalizeZipPath(rawBase) : joinZipPath(resourceDirectory, rawBase);
210
+ // Resolve relative components before normalizing '..'. Declared locations
211
+ // outrank compatibility fallbacks, including their case-insensitive matches.
212
+ const declaredPath = rawFile.startsWith('/') ? mediaFile : joinZipPath(resourceBase, rawFile);
202
213
  const candidates = [mediaFile];
203
214
 
204
215
  if (base && !startsWithZipRoot(mediaFile, base)) {
@@ -213,7 +224,7 @@ const resolveResourceCandidates = function (file, baseLoc, doc) {
213
224
  }
214
225
  }
215
226
 
216
- return [...new Set(docCandidates.filter(Boolean))];
227
+ return [...new Set([declaredPath, ...docCandidates].filter(Boolean))];
217
228
  }
218
229
 
219
230
  const getImageMime = function (format) {
@@ -295,7 +306,7 @@ const sealImageMime = function (type) {
295
306
  export const doGetDocRoot = async function (zip, docbody) {
296
307
  let docRoot = docbody['ofd:DocRoot'];
297
308
  docRoot = normalizeZipPath(replaceFirstSlash(docRoot));
298
- const doc = docRoot.split('/')[0];
309
+ const doc = docRoot.split('/').slice(0, -1).join('/');
299
310
  const signatures = docbody['ofd:Signatures'];
300
311
  const stampAnnot = await getSignature(zip, signatures, doc);
301
312
  let stampAnnotArray = {};
@@ -422,7 +433,7 @@ export const getDocumentRes = async function ([zip, doc, Document, stampAnnot, a
422
433
  const documentResObj = data['json']['ofd:Res'];
423
434
  fontResObj = await getFont(documentResObj);
424
435
  drawParamResObj = await getDrawParam(documentResObj);
425
- multiMediaResObj = await getMultiMediaRes(zip, documentResObj, doc);
436
+ multiMediaResObj = await getMultiMediaRes(zip, documentResObj, doc, documentResPath);
426
437
  }
427
438
  }
428
439
  return [zip, doc, Document, stampAnnot, annotationObjs, fontResObj, drawParamResObj, multiMediaResObj];
@@ -439,7 +450,7 @@ export const getPublicRes = async function ([zip, doc, Document, stampAnnot, ann
439
450
  fontResObj = Object.assign(fontResObj, fontObj);
440
451
  let drawParamObj = await getDrawParam(publicResObj);
441
452
  drawParamResObj = Object.assign(drawParamResObj, drawParamObj);
442
- let multiMediaObj = await getMultiMediaRes(zip, publicResObj, doc);
453
+ let multiMediaObj = await getMultiMediaRes(zip, publicResObj, doc, publicResPath);
443
454
  multiMediaResObj = Object.assign(multiMediaResObj, multiMediaObj);
444
455
  }
445
456
  }
@@ -529,14 +540,14 @@ const getDrawParam = async function (res) {
529
540
  return drawParamResObj;
530
541
  }
531
542
 
532
- const getMultiMediaRes = async function (zip, res, doc) {
543
+ const getMultiMediaRes = async function (zip, res, doc, resourcePath) {
533
544
  const multiMedias = res['ofd:MultiMedias'];
534
545
  let multiMediaResObj = {};
535
546
  if (multiMedias) {
536
547
  let array = collectGroupedItems(multiMedias, 'ofd:MultiMedia');
537
548
  for (const item of array) {
538
549
  if (item && item['ofd:MediaFile']) {
539
- const candidates = resolveResourceCandidates(item['ofd:MediaFile'], res['@_BaseLoc'], doc);
550
+ const candidates = resolveResourceCandidates(item['ofd:MediaFile'], res['@_BaseLoc'], doc, resourcePath);
540
551
  const file = getZipEntry(zip, candidates) ? candidates : null;
541
552
  const type = item['@_Type'] ? item['@_Type'].toLowerCase() : '';
542
553
  if (type === 'image') {
@@ -643,6 +654,7 @@ const getSignatureData = async function (zip, signature, signatureID) {
643
654
  'signedInfo': {
644
655
  'signatureID': signatureID,
645
656
  'VerifyRet': sealObj.verifyRet,
657
+ 'VerificationStatus': sealObj.verificationStatus || 'not-verified',
646
658
  'Provider': signedInfoNode['ofd:Provider'],
647
659
  'SignatureMethod': signedInfoNode['ofd:SignatureMethod'],
648
660
  'SignatureDateTime': signedInfoNode['ofd:SignatureDateTime'],
@@ -663,44 +675,32 @@ const getSealDocumentObj = function (stampAnnot) {
663
675
  }
664
676
 
665
677
  const getJsonFromXmlContent = async function (zip, xmlName) {
666
- return new Promise((resolve, reject) => {
667
- const entry = getZipEntry(zip, xmlName);
668
- if (!entry) {
669
- reject(new Error(`OFD XML resource not found: ${normalizeZipPath(xmlName)}`));
670
- return;
671
- }
672
- entry.async('string').then(function (content) {
673
- ensureBrowserGlobal();
674
- let ops = {
675
- attributeNamePrefix: "@_",
676
- ignoreAttributes: false,
677
- parseNodeValue: false,
678
- trimValues: false
679
- };
680
- let jsonObj = parseXmlToJson(content, ops);
681
- let result = {'xml': content, 'json': jsonObj};
682
- resolve(result);
683
- }, function error(e) {
684
- reject(e);
685
- })
686
- });
678
+ const entry = getZipEntry(zip, xmlName);
679
+ if (!entry) {
680
+ throw new Error(`OFD XML resource not found: ${normalizeZipPath(xmlName)}`);
681
+ }
682
+ const content = await entry.async('string');
683
+ ensureBrowserGlobal();
684
+ try {
685
+ const json = parseXmlToJson(content, {
686
+ attributeNamePrefix: "@_",
687
+ ignoreAttributes: false,
688
+ parseNodeValue: false,
689
+ trimValues: false
690
+ });
691
+ return {xml: content, json};
692
+ } catch (error) {
693
+ throw new Error(`OFD XML parse failed (${normalizeZipPath(xmlName)}): ${error.message}`);
694
+ }
687
695
  }
688
696
 
689
697
  const parseJbig2ImageFromZip = async function (zip, name) {
690
- return new Promise((resolve, reject) => {
691
- const entry = getZipEntry(zip, name);
692
- if (!entry) {
693
- resolve(null);
694
- return;
695
- }
696
- entry.async('uint8array').then(function (bytes) {
697
- let jbig2 = new Jbig2Image();
698
- const img = jbig2.parse(bytes);
699
- resolve({img, width: jbig2.width, height: jbig2.height, format: 'gbig2'});
700
- }, function error(e) {
701
- reject(e);
702
- })
703
- });
698
+ const entry = getZipEntry(zip, name);
699
+ if (!entry) return null;
700
+ const bytes = await entry.async('uint8array');
701
+ const jbig2 = new Jbig2Image();
702
+ const img = jbig2.parse(bytes);
703
+ return {img, width: jbig2.width, height: jbig2.height, format: 'gbig2'};
704
704
  }
705
705
 
706
706
  const parseOtherImageFromZip = async function (zip, name, mime = 'image/png') {
@@ -470,8 +470,9 @@ export const renderTextObject = function (drawParamResObj, fontResObj, textObjec
470
470
  for (const textCodePoint of textCodePointList) {
471
471
  if (textCodePoint && !isNaN(textCodePoint.x)) {
472
472
  let text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
473
- text.setAttribute('x', textCodePoint.x);
474
- text.setAttribute('y', textCodePoint.y);
473
+ text.setAttribute('x', textCodePoint.xPositions?.join(' ') || textCodePoint.x);
474
+ text.setAttribute('y', textCodePoint.yPositions?.join(' ') || textCodePoint.y);
475
+ text.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
475
476
  text.textContent = textCodePoint.text;
476
477
  if (ctm) {
477
478
  const ctms = parseCtm(ctm);
@@ -484,7 +485,7 @@ export const renderTextObject = function (drawParamResObj, fontResObj, textObjec
484
485
  const textFillColor = defaultFillColor || defaultStrokeColor || 'rgb(0, 0, 0)';
485
486
  text.setAttribute('fill', textFillColor);
486
487
  text.setAttribute('fill-opacity', defaultFillOpacity);
487
- text.setAttribute('style', `font-weight: ${weight};font-size:${size}px;font-family: ${getFontFamily(fontResObj[font])};color:${textFillColor};`)
488
+ text.setAttribute('style', `white-space:pre;font-weight: ${weight};font-size:${size}px;font-family: ${getFontFamily(fontResObj[font])};color:${textFillColor};`)
488
489
  svg.appendChild(text);
489
490
  }
490
491
 
@@ -142,98 +142,54 @@ export const converterDpi = function (width) {
142
142
  return millimetersToPixel(width, Scale * 25.4);
143
143
  }
144
144
 
145
- export const deltaFormatter = function (delta) {
146
- if (delta.indexOf("g") === -1) {
147
- let floatList = [];
148
- for (let f of delta.split(' ')) {
149
- floatList.push(parseFloat(f));
150
- }
151
- return floatList;
152
- } else {
153
- const array = delta.split(' ');
154
- let gFlag = false;
155
- let gProcessing = false;
156
- let gItemCount = 0;
157
- let floatList = [];
158
- for (const s of array) {
159
- if ('g' === s) {
160
- gFlag = true;
161
- } else {
162
- if (!s || s.trim().length == 0) {
163
- continue;
164
- }
165
- if (gFlag) {
166
- gItemCount = parseInt(s);
167
- gProcessing = true;
168
- gFlag = false;
169
- } else if (gProcessing) {
170
- for (let j = 0; j < gItemCount; j++) {
171
- floatList.push(parseFloat(s));
172
- }
173
- gProcessing = false;
174
- } else {
175
- floatList.push(parseFloat(s));
176
- }
177
- }
145
+ export const deltaFormatter = function (delta, maxValues = 100000) {
146
+ const tokens = String(delta ?? '').trim().split(/\s+/);
147
+ const values = [];
148
+ const limit = Math.max(0, Math.min(100000, maxValues));
149
+ for (let i = 0; i < tokens.length && values.length < limit; i++) {
150
+ let count = 1;
151
+ if (tokens[i] === 'g') {
152
+ count = Number(tokens[++i]);
153
+ i++;
154
+ if (!Number.isSafeInteger(count) || count < 0) break;
178
155
  }
179
- return floatList;
156
+ const value = Number(tokens[i]);
157
+ if (!tokens[i] || !Number.isFinite(value)) break;
158
+ count = Math.min(count, limit - values.length);
159
+ for (let j = 0; j < count; j++) values.push(value);
180
160
  }
161
+ return values;
181
162
  }
182
163
 
183
164
  export const calTextPoint = function (textCodes) {
184
- let x = 0;
185
- let y = 0;
186
- let textCodePointList = [];
187
- if (!textCodes) {
188
- return textCodePointList;
189
- }
190
- for (let textCode of textCodes) {
191
- if (!textCode) {
192
- continue
193
- }
194
- x = parseFloat(textCode['@_X']);
195
- y = parseFloat(textCode['@_Y']);
196
-
197
- if (isNaN(x)) {
198
- x = 0;
199
- }
200
- if (isNaN(y)) {
201
- y = 0;
202
- }
203
-
204
- let deltaXList = [];
205
- let deltaYList = [];
206
- if (textCode['@_DeltaX'] && textCode['@_DeltaX'].length > 0) {
207
- deltaXList = deltaFormatter(textCode['@_DeltaX']);
208
- }
209
- if (textCode['@_DeltaY'] && textCode['@_DeltaY'].length > 0) {
210
- deltaYList = deltaFormatter(textCode['@_DeltaY']);
211
- }
212
- let textStr = textCode['#text'];
213
- if (textStr) {
214
- textStr += '';
215
- textStr = decodeOfdText(textStr);
216
- for (let i = 0; i < textStr.length; i++) {
217
- if (i > 0 && deltaXList.length > 0) {
218
- x += deltaXList[(i - 1)];
219
- }
220
- if (i > 0 && deltaYList.length > 0) {
221
- y += deltaYList[(i - 1)];
222
- }
223
- let text = textStr.substring(i, i + 1);
224
- let filterPointY = textCodePointList.filter((textCodePoint) => {
225
- return textCodePoint.y == converterDpi(y)
226
- });
227
- if (filterPointY && filterPointY.length) { // Y坐标相同,无需再创建text标签
228
- filterPointY[0].text += text;
229
- } else {
230
- let textCodePoint = { 'x': converterDpi(x), 'y': converterDpi(y), 'text': text };
231
- textCodePointList.push(textCodePoint);
232
- }
165
+ const runs = [];
166
+ for (const code of textCodes || []) {
167
+ if (code == null) continue;
168
+ const value = typeof code === 'string' ? code : code['#text'];
169
+ if (value == null || value === '') continue;
170
+ const text = decodeOfdText(String(value));
171
+ const count = Array.from(text).length;
172
+ const finite = value => Number.isFinite(Number.parseFloat(value)) ? Number.parseFloat(value) : 0;
173
+ const x = finite(code['@_X']);
174
+ const y = finite(code['@_Y']);
175
+ const positions = (start, delta) => {
176
+ const list = [converterDpi(start)];
177
+ for (const offset of deltaFormatter(delta, count - 1)) {
178
+ start += offset;
179
+ list.push(converterDpi(start));
233
180
  }
234
- }
181
+ return list;
182
+ };
183
+ // One SVG text run per TextCode preserves shaping and avoids one DOM
184
+ // node per glyph. Position lists honor explicit advances (including
185
+ // spaces); omitted advances retain the browser's natural text advance.
186
+ runs.push({
187
+ x: converterDpi(x), y: converterDpi(y), text,
188
+ xPositions: positions(x, code['@_DeltaX']),
189
+ yPositions: positions(y, code['@_DeltaY']),
190
+ });
235
191
  }
236
- return textCodePointList;
192
+ return runs;
237
193
  }
238
194
 
239
195
  export const replaceFirstSlash = function (str) {
@@ -311,6 +267,9 @@ let FONT_FAMILY = {
311
267
  };
312
268
 
313
269
  export const getFontFamily = function (font) {
270
+ if (typeof font !== 'string' || !font.trim()) {
271
+ return 'sans-serif';
272
+ }
314
273
  if (FONT_FAMILY[font.toLowerCase()]) {
315
274
  font = FONT_FAMILY[font.toLowerCase()];
316
275
  }
@@ -33,6 +33,38 @@ const HexApi = unwrapDefault(Hex);
33
33
  const Base64Api = unwrapDefault(Base64);
34
34
  const ASN1Api = unwrapDefault(ASN1);
35
35
 
36
+ // SignedData is not an SES seal. In particular, tax invoices use the GM/T
37
+ // ContentInfo OID and draw their visible stamp as an ordinary page resource.
38
+ const signedDataOids = new Set(['1.2.840.113549.1.7.2', '1.2.156.10197.6.1.4.2.2']);
39
+ const universal = (node, number) => node?.tag?.tagClass === 0 && node.tag.tagNumber === number;
40
+ const parseSignedData = function (node) {
41
+ if (!universal(node?.sub?.[0], 6)) return null;
42
+ const oidNode = node.sub[0];
43
+ const start = oidNode.stream.pos + oidNode.header;
44
+ const oid = oidNode.stream.parseOID(start, start + oidNode.length).split('\n', 1)[0];
45
+ if (!signedDataOids.has(oid)) throw new Error('Unsupported signature ContentInfo type');
46
+ const wrapper = node.sub[1];
47
+ const signed = wrapper?.sub?.[0];
48
+ if (!universal(node, 16) || node.sub.length !== 2 ||
49
+ wrapper?.tag?.tagClass !== 2 || wrapper.tag.tagNumber !== 0 ||
50
+ !wrapper.tag.tagConstructed || wrapper.sub.length !== 1 ||
51
+ !universal(signed, 16) || signed.sub.length < 4 ||
52
+ !universal(signed.sub[0], 2) || !universal(signed.sub[1], 17) ||
53
+ !universal(signed.sub[2], 16) || !universal(signed.sub[2]?.sub?.[0], 6) ||
54
+ !universal(signed.sub.at(-1), 17)) {
55
+ throw new Error('Malformed SignedData structure');
56
+ }
57
+ return {
58
+ type: 'signed-data',
59
+ verificationStatus: 'not-verified',
60
+ verifyRet: null,
61
+ SES_Signature: {
62
+ format: 'signed-data', contentType: oid, displayOnly: true,
63
+ verificationStatus: 'not-verified',
64
+ },
65
+ };
66
+ };
67
+
36
68
  export const parseSesSignature = async function (zip, name, getEntry) {
37
69
  const entry = typeof getEntry === 'function' ? getEntry(zip, name) : zip.files[name];
38
70
  if (!entry) {
@@ -60,7 +92,10 @@ const decodeText = function (val) {
60
92
  const decode = function (der, offset) {
61
93
  offset = offset || 0;
62
94
  try {
63
- const SES_Signature = decodeSES_Signature(der, offset);
95
+ const root = ASN1Api.decode(der, offset);
96
+ const signedData = parseSignedData(root);
97
+ if (signedData) return signedData;
98
+ const SES_Signature = decodeSES_Signature(root);
64
99
  const picture = SES_Signature?.toSign?.eseal?.esealInfo?.picture;
65
100
  if (!picture?.data?.byte?.length) {
66
101
  return {};
@@ -73,12 +108,15 @@ const decode = function (der, offset) {
73
108
  SES_Signature: {
74
109
  realVersion: SES_Signature.realVersion,
75
110
  displayOnly: true,
111
+ verificationStatus: 'not-verified',
76
112
  pictureType: type,
77
113
  pictureWidth: picture.width,
78
114
  pictureHeight: picture.height,
79
115
  sealName: SES_Signature.toSign?.eseal?.esealInfo?.property?.name,
80
116
  },
81
- verifyRet: true,
117
+ // Displaying an image is not cryptographic signature verification.
118
+ verifyRet: null,
119
+ verificationStatus: 'not-verified',
82
120
  };
83
121
  } catch (e) {
84
122
  console.warn('[ofd] decode SES signature failed', e);
@@ -122,9 +160,7 @@ const parseTimeNode = function (node, utc) {
122
160
  return decodeUTCTime(raw);
123
161
  };
124
162
 
125
- const decodeSES_Signature = function (der, offset) {
126
- offset = offset || 0;
127
- const asn1 = ASN1Api.decode(der, offset);
163
+ const decodeSES_Signature = function (asn1) {
128
164
  let SES_Signature;
129
165
  try {
130
166
  // V1