xades-bes-signer 1.0.4 → 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,7 +22,7 @@ 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
28
|
modulus: string;
|
|
@@ -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,15 +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 = 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()));
|
|
144
|
-
modulus = modulus.replace(/\r?\n|\r/g,
|
|
155
|
+
modulus = modulus.replace(/\r?\n|\r/g, "").replace(/([^\0]{76})/g, "$1\n");
|
|
145
156
|
const certificateNumber = (0, security_1.getRandomValues)(999990, 9999999);
|
|
146
157
|
const signatureNumber = (0, security_1.getRandomValues)(99990, 999999);
|
|
147
158
|
const signedPropertiesNumber = (0, security_1.getRandomValues)(99990, 999999);
|
|
@@ -162,10 +173,10 @@ function getPCK12CertInfo(certificate, certKey) {
|
|
|
162
173
|
objectNumber,
|
|
163
174
|
},
|
|
164
175
|
certInfo: {
|
|
165
|
-
digestValue:
|
|
176
|
+
digestValue: hashCertificateX509DER,
|
|
166
177
|
issuerName,
|
|
167
178
|
issuerSerialNumber: certificateX509SN,
|
|
168
|
-
signingTime:
|
|
179
|
+
signingTime: signingTime,
|
|
169
180
|
certificateX509,
|
|
170
181
|
modulus,
|
|
171
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,19 +40,20 @@ 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
58
|
`<etsi:DataObjectFormat ObjectReference="#Reference-ID-${params.referenceIdNumber}">` +
|
|
58
59
|
`<etsi:Description>contenido comprobante</etsi:Description>` +
|
|
@@ -66,29 +67,29 @@ 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:KeyValue>\n<ds:RSAKeyValue>\n<ds:Modulus>\n${params.modulus}\n</ds:Modulus>` +
|
|
70
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>`);
|
|
@@ -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,
|
|
@@ -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",
|