xades-bes-signer 1.0.3 → 1.0.5
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.
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as forge from "node-forge";
|
|
2
|
-
import {
|
|
2
|
+
import { PKCS8Bags } from "./types";
|
|
3
3
|
export declare function getP12(certificate: Uint8Array<ArrayBufferLike>, certKey: string): forge.pkcs12.Pkcs12Pfx;
|
|
4
4
|
export declare function getIssuerName(cert: forge.pkcs12.Bag): string | undefined;
|
|
5
|
-
export declare function getKeyContainer(pkcs8Bags:
|
|
5
|
+
export declare function getKeyContainer(pkcs8Bags: PKCS8Bags, friendlyName: string): forge.pkcs12.Bag;
|
|
6
6
|
export declare function getKey(pckcs8: forge.pkcs12.Bag): forge.pki.rsa.PrivateKey;
|
|
7
7
|
export declare function getCertificate(certBag: forge.pkcs12.Bag[]): forge.pkcs12.Bag;
|
|
8
8
|
export declare function isCerticateValid(certficate: forge.pki.Certificate): boolean;
|
|
@@ -22,10 +22,10 @@ export declare function getPCK12CertInfo(certificate: Uint8Array<ArrayBufferLike
|
|
|
22
22
|
certInfo: {
|
|
23
23
|
digestValue: string;
|
|
24
24
|
issuerName: string | undefined;
|
|
25
|
-
issuerSerialNumber:
|
|
25
|
+
issuerSerialNumber: string;
|
|
26
26
|
signingTime: string;
|
|
27
27
|
certificateX509: string;
|
|
28
|
-
modulus: string
|
|
28
|
+
modulus: string;
|
|
29
29
|
exponent: string;
|
|
30
30
|
key: forge.pki.rsa.PrivateKey;
|
|
31
31
|
};
|
|
@@ -54,7 +54,7 @@ function getIssuerName(cert) {
|
|
|
54
54
|
const issuerTributes = (_a = cert.cert) === null || _a === void 0 ? void 0 : _a.issuer.attributes;
|
|
55
55
|
let issuerName = issuerTributes === null || issuerTributes === void 0 ? void 0 : issuerTributes.reverse().map((attr) => {
|
|
56
56
|
return `${attr.shortName}=${attr.value}`;
|
|
57
|
-
}).join(",
|
|
57
|
+
}).join(",");
|
|
58
58
|
return issuerName;
|
|
59
59
|
}
|
|
60
60
|
function getKeyContainer(pkcs8Bags, friendlyName) {
|
|
@@ -133,14 +133,26 @@ function getPCK12CertInfo(certificate, certKey) {
|
|
|
133
133
|
let key = getKey(pckcs8);
|
|
134
134
|
const pem = certX509ToPem(cert);
|
|
135
135
|
let certificateX509 = pem.substring(pem.indexOf("\n") + 1, pem.indexOf("-----END CERTIFICATE-----"));
|
|
136
|
-
certificateX509
|
|
137
|
-
|
|
136
|
+
certificateX509 = certificateX509
|
|
137
|
+
.replace(/\r?\n|\r/g, "")
|
|
138
|
+
.replace(/([^\0]{76})/g, "$1\n");
|
|
139
|
+
const currentDate = new Date();
|
|
140
|
+
const timeZone = (currentDate.getTimezoneOffset() / 60) * -1;
|
|
141
|
+
const signingTime = `${currentDate.getFullYear()}-` +
|
|
142
|
+
`${(currentDate.getMonth() + 1).toString().padStart(2, "0")}-` +
|
|
143
|
+
`${currentDate.getDate().toString().padStart(2, "0")}T` +
|
|
144
|
+
`${currentDate.getHours().toString().padStart(2, "0")}:` +
|
|
145
|
+
`${currentDate.getMinutes().toString().padStart(2, "0")}:` +
|
|
146
|
+
`${currentDate.getSeconds().toString().padStart(2, "0")}` +
|
|
147
|
+
`${timeZone > 0 ? "+" : "-"}` +
|
|
148
|
+
`${(timeZone > 0 ? timeZone.toString() : timeZone.toString().substring(1)).padStart(2, "0")}:00`;
|
|
138
149
|
const certificateANS1 = certX509ToASN1(cert);
|
|
139
150
|
const certificateDER = forge.asn1.toDer(certificateANS1).getBytes();
|
|
140
|
-
const
|
|
141
|
-
const certificateX509SN =
|
|
151
|
+
const hashCertificateX509DER = (0, security_1.sha1ToBase64)(certificateDER);
|
|
152
|
+
const certificateX509SN = BigInt(`0x${cert.serialNumber}`).toString(10);
|
|
142
153
|
const exponent = (0, security_1.hexToBase64)(key.e.data[0].toString(16));
|
|
143
|
-
|
|
154
|
+
let modulus = (0, security_1.bigintToBase64)(BigInt(key.n.toString()));
|
|
155
|
+
modulus = modulus.replace(/\r?\n|\r/g, "").replace(/([^\0]{76})/g, "$1\n");
|
|
144
156
|
const certificateNumber = (0, security_1.getRandomValues)(999990, 9999999);
|
|
145
157
|
const signatureNumber = (0, security_1.getRandomValues)(99990, 999999);
|
|
146
158
|
const signedPropertiesNumber = (0, security_1.getRandomValues)(99990, 999999);
|
|
@@ -161,10 +173,10 @@ function getPCK12CertInfo(certificate, certKey) {
|
|
|
161
173
|
objectNumber,
|
|
162
174
|
},
|
|
163
175
|
certInfo: {
|
|
164
|
-
digestValue:
|
|
176
|
+
digestValue: hashCertificateX509DER,
|
|
165
177
|
issuerName,
|
|
166
178
|
issuerSerialNumber: certificateX509SN,
|
|
167
|
-
signingTime:
|
|
179
|
+
signingTime: signingTime,
|
|
168
180
|
certificateX509,
|
|
169
181
|
modulus,
|
|
170
182
|
exponent,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Encoding } from "node:crypto";
|
|
2
1
|
import * as forge from "node-forge";
|
|
3
|
-
export declare function sha1ToBase64(text: string, encoding
|
|
2
|
+
export declare function sha1ToBase64(text: string, encoding?: forge.Encoding): string;
|
|
4
3
|
export declare function hexToBase64(hashHex: string): string;
|
|
5
4
|
export declare function bigintToBase64(param: bigint): string | undefined;
|
|
6
5
|
export declare function getRandomValues(min?: number, max?: number): number;
|
|
@@ -40,12 +40,14 @@ exports.getRandomValues = getRandomValues;
|
|
|
40
40
|
exports.isHexString = isHexString;
|
|
41
41
|
exports.toSha1 = toSha1;
|
|
42
42
|
exports.toBase64String = toBase64String;
|
|
43
|
-
const crypto = __importStar(require("node:crypto"));
|
|
44
43
|
const forge = __importStar(require("node-forge"));
|
|
45
44
|
function sha1ToBase64(text, encoding) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
let md = forge.md.sha1.create();
|
|
46
|
+
forge.util.encode64(forge.sha1.create().update(text).digest().bytes());
|
|
47
|
+
md.update(text, encoding);
|
|
48
|
+
const HASH = md.digest().toHex();
|
|
49
|
+
const BUFFER = Buffer.from(HASH, "hex").toString("base64");
|
|
50
|
+
return BUFFER;
|
|
49
51
|
}
|
|
50
52
|
function hexToBase64(hashHex) {
|
|
51
53
|
if (hashHex.length % 2 !== 0) {
|
|
@@ -81,6 +83,5 @@ function toSha1(content, encoding) {
|
|
|
81
83
|
return md;
|
|
82
84
|
}
|
|
83
85
|
function toBase64String(content) {
|
|
84
|
-
|
|
85
|
-
return buffer.toString('base64');
|
|
86
|
+
return forge.util.encode64(content);
|
|
86
87
|
}
|
package/dist/src/libs/signer.js
CHANGED
|
@@ -40,21 +40,22 @@ function getXML(path) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
function getSignedPropertiesNode(params) {
|
|
43
|
-
return (`<etsi:SignedProperties Id="Signature${params.signatureNumber}
|
|
43
|
+
return (`<etsi:SignedProperties Id="Signature${params.signatureNumber}-SignedProperties${params.signedPropertiesNumber}">` +
|
|
44
44
|
`<etsi:SignedSignatureProperties>` +
|
|
45
|
-
`<etsi:
|
|
45
|
+
`<etsi:SigningTime>${params.signingTime}</etsi:SigningTime>` +
|
|
46
46
|
`<etsi:SigningCertificate>` +
|
|
47
47
|
`<etsi:Cert>` +
|
|
48
|
-
`<etsi:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"
|
|
49
|
-
`<
|
|
48
|
+
`<etsi:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>` +
|
|
49
|
+
`<ds:DigestValue>${params.digestValue}</ds:DigestValue></etsi:CertDigest>` +
|
|
50
50
|
`<etsi:IssuerSerial>` +
|
|
51
51
|
`<ds:X509IssuerName>${params.issuerName}</ds:X509IssuerName>` +
|
|
52
52
|
`<ds:X509SerialNumber>${params.issuerSerialNumber}</ds:X509SerialNumber>` +
|
|
53
53
|
`</etsi:IssuerSerial>` +
|
|
54
54
|
`</etsi:Cert>` +
|
|
55
55
|
`</etsi:SigningCertificate>` +
|
|
56
|
+
`</etsi:SignedSignatureProperties>` +
|
|
56
57
|
`<etsi:SignedDataObjectProperties>` +
|
|
57
|
-
`<etsi:DataObjectFormat ObjectReference="#Reference-ID
|
|
58
|
+
`<etsi:DataObjectFormat ObjectReference="#Reference-ID-${params.referenceIdNumber}">` +
|
|
58
59
|
`<etsi:Description>contenido comprobante</etsi:Description>` +
|
|
59
60
|
`<etsi:MimeType>text/xml</etsi:MimeType>` +
|
|
60
61
|
`</etsi:DataObjectFormat>` +
|
|
@@ -66,32 +67,32 @@ function getKeyInfoNode(params) {
|
|
|
66
67
|
`\n<ds:X509Data>` +
|
|
67
68
|
`\n<ds:X509Certificate>\n${params.certificateX509}\n</ds:X509Certificate>` +
|
|
68
69
|
`\n</ds:X509Data>` +
|
|
69
|
-
`\n
|
|
70
|
-
`\n<ds:Exponent
|
|
70
|
+
`\n<ds:KeyValue>\n<ds:RSAKeyValue>\n<ds:Modulus>\n${params.modulus}\n</ds:Modulus>` +
|
|
71
|
+
`\n<ds:Exponent>${params.exponent}</ds:Exponent>` +
|
|
71
72
|
`\n</ds:RSAKeyValue>` +
|
|
73
|
+
`\n</ds:KeyValue>` +
|
|
72
74
|
`\n</ds:KeyInfo>`);
|
|
73
75
|
}
|
|
74
76
|
function getSignedInfoNode(params) {
|
|
75
77
|
return (`<ds:SignedInfo Id="Signature-SignedInfo${params.signedInfoNumber}">` +
|
|
76
|
-
`\n<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-
|
|
77
|
-
`\n<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
|
78
|
-
`\n<ds:Reference Id="SignedPropertiesID${params.signedPropertiesIdNumber}"
|
|
79
|
-
|
|
80
|
-
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>` +
|
|
78
|
+
`\n<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>` +
|
|
79
|
+
`\n<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>` +
|
|
80
|
+
`\n<ds:Reference Id="SignedPropertiesID${params.signedPropertiesIdNumber}" Type="http://uri.etsi.org/01903#SignedProperties" URI="#Signature${params.signatureNumber}-SignedProperties${params.signedPropertiesNumber}">` +
|
|
81
|
+
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>` +
|
|
81
82
|
`\n<ds:DigestValue>${params.sha1SignedProperties}</ds:DigestValue>` +
|
|
82
83
|
`\n</ds:Reference>` +
|
|
83
|
-
`\n<ds:Reference URI="Certificate${params.certificateNumber}">` +
|
|
84
|
-
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"
|
|
84
|
+
`\n<ds:Reference URI="#Certificate${params.certificateNumber}">` +
|
|
85
|
+
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>` +
|
|
85
86
|
`\n<ds:DigestValue>${params.sha1KeyInfo}</ds:DigestValue>` +
|
|
86
87
|
`\n</ds:Reference>` +
|
|
87
88
|
`\n<ds:Reference Id="Reference-ID-${params.referenceIdNumber}" URI="#comprobante">` +
|
|
88
89
|
`\n<ds:Transforms>` +
|
|
89
|
-
`\n<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"
|
|
90
|
+
`\n<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>` +
|
|
90
91
|
`\n</ds:Transforms>` +
|
|
91
|
-
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"
|
|
92
|
+
`\n<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>` +
|
|
92
93
|
`\n<ds:DigestValue>${params.sha1Xml}</ds:DigestValue>` +
|
|
93
94
|
`\n</ds:Reference>` +
|
|
94
|
-
|
|
95
|
+
`\n</ds:SignedInfo>`);
|
|
95
96
|
}
|
|
96
97
|
function getSignatureObject(params) {
|
|
97
98
|
const objectSignature = `<ds:Object Id="Signature${params.signatureNumber}-Object${params.objectNumber}">` +
|
|
@@ -132,11 +133,12 @@ function sign(params) {
|
|
|
132
133
|
.replace(/(?=<\>)(\r?\n)|(\r?\n)(?=\<\/) /g, "")
|
|
133
134
|
.trim()
|
|
134
135
|
.replace(/(?=<\>)(\s*)/g, "")
|
|
135
|
-
.replace(/\t|\r/g, "")
|
|
136
|
+
.replace(/\t|\r/g, "")
|
|
137
|
+
.replace(/>\s+</g, "><");
|
|
136
138
|
const arayuint8 = new Uint8Array(p12Buffer === null || p12Buffer === void 0 ? void 0 : p12Buffer.buffer);
|
|
137
139
|
let certInfo = (0, credentials_1.getPCK12CertInfo)(arayuint8, p12Password);
|
|
138
140
|
const sha1Xml = (0, security_1.sha1ToBase64)(xmlData.replace(`<?xml version="1.0" encoding="UTF-8"?>`, ""), "utf8");
|
|
139
|
-
const namespaces = 'xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:
|
|
141
|
+
const namespaces = 'xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#"';
|
|
140
142
|
let signedProperties = getSignedPropertiesNode({
|
|
141
143
|
signatureNumber: certInfo.radomValues.signatureNumber,
|
|
142
144
|
signedPropertiesNumber: certInfo.radomValues.signedPropertiesNumber,
|
|
@@ -151,7 +153,7 @@ function sign(params) {
|
|
|
151
153
|
nodeName: "<etsi:SignedProperties",
|
|
152
154
|
namespaces,
|
|
153
155
|
});
|
|
154
|
-
const sha1SignedProperties = (0, security_1.sha1ToBase64)(signedPropertiesCanonicalized
|
|
156
|
+
const sha1SignedProperties = (0, security_1.sha1ToBase64)(signedPropertiesCanonicalized);
|
|
155
157
|
const keyInfo = getKeyInfoNode({
|
|
156
158
|
certificateNumber: certInfo.radomValues.certificateNumber,
|
|
157
159
|
certificateX509: certInfo.certInfo.certificateX509,
|
|
@@ -163,7 +165,7 @@ function sign(params) {
|
|
|
163
165
|
nodeName: "<ds:KeyInfo",
|
|
164
166
|
namespaces,
|
|
165
167
|
});
|
|
166
|
-
const sha1KeyInfo = (0, security_1.sha1ToBase64)(keyInfoCanonicalized
|
|
168
|
+
const sha1KeyInfo = (0, security_1.sha1ToBase64)(keyInfoCanonicalized);
|
|
167
169
|
const signedInfo = getSignedInfoNode({
|
|
168
170
|
signedInfoNumber: certInfo.radomValues.signedInfoNumber,
|
|
169
171
|
signedPropertiesIdNumber: certInfo.radomValues.signedPropertiesIdNumber,
|
|
@@ -183,8 +185,8 @@ function sign(params) {
|
|
|
183
185
|
const md = (0, security_1.toSha1)(signedInfoCanonicalized, "utf8");
|
|
184
186
|
const signatureValue = (_b = (_a = (0, security_1.toBase64String)(certInfo.certInfo.key.sign(md))
|
|
185
187
|
.match(/.{1,76}/g)) === null || _a === void 0 ? void 0 : _a.join("\n")) !== null && _b !== void 0 ? _b : "";
|
|
186
|
-
const signatureValueNode =
|
|
187
|
-
|
|
188
|
+
const signatureValueNode = `<ds:SignatureValue Id="SignatureValue${certInfo.radomValues.signatureValueNumber}">` +
|
|
189
|
+
`\n${signatureValue}\n</ds:SignatureValue>`;
|
|
188
190
|
const objectSignature = getSignatureObject({
|
|
189
191
|
signatureNumber: certInfo.radomValues.signatureNumber,
|
|
190
192
|
objectNumber: certInfo.radomValues.objectNumber,
|
|
@@ -199,7 +201,7 @@ function sign(params) {
|
|
|
199
201
|
objectSignarureNode: objectSignature,
|
|
200
202
|
});
|
|
201
203
|
return addSignatureNode({
|
|
202
|
-
xml: xmlData,
|
|
204
|
+
xml: xmlData.replace(`encoding="UTF-8"?>`, 'encoding="UTF-8"?>\n'),
|
|
203
205
|
rootElement: params.rootElement,
|
|
204
206
|
signatureNode,
|
|
205
207
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xades-bes-signer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "XAdES-BES signer utilities for Node.js (TypeScript) — certificate handling and XAdES-BES signature helpers.",
|
|
5
5
|
"main": "/dist/src/main.js",
|
|
6
6
|
"types": "/dist/src/main.d.ts",
|