@openade/fe
Version:
Fatturazione Elettronica - Electronic Invoicing for Sistema di Interscambio (SDI)
119 lines • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SignatureManager = void 0;
exports.createSignatureManager = createSignatureManager;
exports.signInvoiceXml = signInvoiceXml;
exports.verifySignedInvoiceXml = verifySignedInvoiceXml;
const signature_service_1 = require("./signature.service");
class SignatureManager {
constructor(config) {
this.config = {
algorithm: 'RSA-SHA256',
includeTimestamp: false,
...config,
};
this.signatureService = new signature_service_1.SignatureService();
}
async signInvoice(xmlContent) {
const privateKey = await this.getPrivateKey();
const algorithm = this.config.algorithm;
const signatureResult = await this.signatureService.sign(Buffer.from(xmlContent, 'utf8'), privateKey, algorithm);
const timestamp = this.config.includeTimestamp ? new Date().toISOString() : undefined;
const signedXml = this.createSignedXml(xmlContent, signatureResult.signature, signatureResult.digest, timestamp);
return {
signedXml,
digest: signatureResult.digest,
algorithm: signatureResult.algorithm,
timestamp,
};
}
async verifySignature(signedXml) {
try {
const certificate = await this.getCertificate();
const { xmlContent, signature, algorithm } = this.extractSignatureData(signedXml);
return await this.signatureService.verify(Buffer.from(xmlContent, 'utf8'), signature, certificate, algorithm);
}
catch {
return false;
}
}
async getPrivateKey() {
if (this.config.privateKey) {
return this.config.privateKey;
}
if (this.config.privateKeyPath) {
const keyContent = await this.config.fileStorage.retrieve(this.config.privateKeyPath);
if (!keyContent) {
throw new Error(`Private key file not found: ${this.config.privateKeyPath}`);
}
return Buffer.from(keyContent).toString('utf8');
}
throw new Error('Private key not provided. Set privateKey or privateKeyPath in config.');
}
async getCertificate() {
if (this.config.certificate) {
return this.config.certificate;
}
if (this.config.certificatePath) {
const certContent = await this.config.fileStorage.retrieve(this.config.certificatePath);
if (!certContent) {
throw new Error(`Certificate file not found: ${this.config.certificatePath}`);
}
return Buffer.from(certContent).toString('utf8');
}
throw new Error('Certificate not provided. Set certificate or certificatePath in config.');
}
createSignedXml(xmlContent, signature, digest, timestamp) {
const signatureElement = `
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>${digest}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>${signature}</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>${this.getCertificateContent()}</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
${timestamp ? `<ds:Object><Timestamp>${timestamp}</Timestamp></ds:Object>` : ''}
</ds:Signature>`;
return xmlContent.replace('</p:FatturaElettronica>', `${signatureElement}\n</p:FatturaElettronica>`);
}
extractSignatureData(signedXml) {
const signatureMatch = signedXml.match(/<ds:SignatureValue>(.*?)<\/ds:SignatureValue>/);
const digestMatch = signedXml.match(/<ds:DigestValue>(.*?)<\/ds:DigestValue>/);
if (!signatureMatch || !digestMatch) {
throw new Error('Invalid signed XML format');
}
const xmlContent = signedXml.replace(/<ds:Signature[\s\S]*?<\/ds:Signature>/, '');
return {
xmlContent,
signature: signatureMatch[1],
algorithm: 'RSA-SHA256',
};
}
getCertificateContent() {
return 'CERTIFICATE_CONTENT_PLACEHOLDER';
}
}
exports.SignatureManager = SignatureManager;
function createSignatureManager(config) {
return new SignatureManager(config);
}
async function signInvoiceXml(xmlContent, config) {
const manager = createSignatureManager(config);
return await manager.signInvoice(xmlContent);
}
async function verifySignedInvoiceXml(signedXml, config) {
const manager = createSignatureManager(config);
return await manager.verifySignature(signedXml);
}
//# sourceMappingURL=signature.manager.js.map