dte-signer-sv
Version:
Sign Digital Tax Documents (DTE) for El Salvador's Ministry of Finance
280 lines (211 loc) • 7.1 kB
Markdown
[](https://badge.fury.io/js/dte-signer-sv)
[](https://opensource.org/licenses/MIT)
A Node.js package for signing Digital Tax Documents (DTE) for El Salvador's Ministry of Finance (Ministerio de Hacienda). This package provides a simple interface to digitally sign DTEs using certificates issued by the government.
## Features
- 🔐 Sign DTEs using government-issued certificates
- 📝 Support for XML certificate format (.crt files)
- 🔑 RSA-SHA512 (RS512) digital signatures
- 📦 TypeScript support with full type definitions
- ✅ Comprehensive test coverage
- 🚀 Zero runtime dependencies (only `xml2js` and `node-jose`)
## Installation
```bash
npm install dte-signer-sv
```
Or using yarn:
```bash
yarn add dte-signer-sv
```
## Usage
### Basic Example
```javascript
import { signDTE } from 'dte-signer-sv';
// Your DTE object following MH specifications
const dte = {
identificacion: {
version: 1,
ambiente: "00",
tipoDte: "01",
numeroControl: "DTE-01-00000001-000000000000001",
codigoGeneracion: "UUID-HERE",
tipoModelo: 1,
tipoOperacion: 1,
tipoContingencia: null,
motivoContigencia: null,
fecEmi: "2024-01-01",
horEmi: "10:30:00",
tipoMoneda: "USD"
},
// ... rest of your DTE structure
};
// Sign the DTE
const signedDTE = await signDTE({
dte: dte,
privatePassword: "yourPrivateKeyPassword",
certificate: "./path/to/certificate.crt",
loadCertificateFromPath: true
});
console.log(signedDTE); // JWS compact format string
```
```javascript
import { signDTE } from 'dte-signer-sv';
import fs from 'fs';
// Read certificate content
const certificateXML = fs.readFileSync('./certificate.crt', 'utf8');
// Sign the DTE
const signedDTE = await signDTE({
dte: myDTEObject,
privatePassword: "yourPrivateKeyPassword",
certificate: certificateXML,
loadCertificateFromPath: false // or omit this parameter
});
```
Signs a DTE document and returns a JWS (JSON Web Signature) in compact format.
#### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `dte` | `object` | Yes | The DTE object to be signed |
| `privatePassword` | `string` | Yes | Password for the private key |
| `certificate` | `string` | Yes | Certificate XML content or file path |
| `loadCertificateFromPath` | `boolean` | No | If true, treats certificate as file path (default: false) |
#### Returns
Returns a `Promise<string>` that resolves to the signed DTE in JWS compact format (header.payload.signature).
#### Throws
- `Error("Invalid private password")` - If the provided password is incorrect
- File system errors - If certificate file is not found (when using file path)
- Parsing errors - If the certificate XML is invalid
## Certificate Format
This package works with certificates in the XML format provided by El Salvador's Ministry of Finance. The certificate file (.crt) should contain:
- Public key in X.509 format
- Private key in PKCS#8 format
- Password hash for validation
### Creating Test Certificates
For development and testing, you can create test certificates using the script available at:
[Create Test Certificate Script](https://gist.github.com/mcalero11/03af55c0e9872407b121dd77cc41f833)
## Integration with MH Systems
The signed DTE can be sent to the Ministry of Finance's reception system. The signature is created using:
- **Algorithm**: RS512 (RSA signature with SHA-512)
- **Format**: JWS Compact Serialization
- **Standard**: Compliant with RFC 7515
## Development
### Prerequisites
- Node.js >= 14
- npm or yarn
1. Clone the repository:
```bash
git clone https://github.com/mcalero11/dte-signer-sv.git
cd dte-signer-sv
```
2. Install dependencies:
```bash
npm install
```
3. Run tests:
```bash
npm test
```
4. Build the package:
```bash
npm run build
```
```bash
npm test
npm test -- --watch
npm test -- --coverage
```
```javascript
import { signDTE } from 'dte-signer-sv';
const dte = {
identificacion: {
version: 1,
ambiente: "00",
tipoDte: "01",
numeroControl: "DTE-01-00000001-000000000000001",
codigoGeneracion: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
tipoModelo: 1,
tipoOperacion: 1,
fecEmi: "2024-01-01",
horEmi: "10:30:00",
tipoMoneda: "USD"
},
emisor: {
nit: "06142803901234",
nrc: "1234567",
nombre: "EMPRESA DE PRUEBA S.A. DE C.V.",
codActividad: "01234",
descActividad: "Venta de productos",
telefono: "2234-5678",
correo: "info@empresa.com",
// ... rest of emisor data
},
receptor: {
tipoDocumento: "36",
numDocumento: "06142803901234",
nombre: "CLIENTE DE PRUEBA",
// ... rest of receptor data
},
// ... rest of DTE structure
};
try {
const signedDTE = await signDTE({
dte: dte,
privatePassword: "mySecurePassword",
certificate: "./certificates/company.crt",
loadCertificateFromPath: true
});
console.log("Successfully signed DTE:", signedDTE);
// Send to MH API
// await sendToMH(signedDTE);
} catch (error) {
console.error("Error signing DTE:", error.message);
}
```
```javascript
try {
const signedDTE = await signDTE({
dte: myDTE,
privatePassword: password,
certificate: certificatePath,
loadCertificateFromPath: true
});
} catch (error) {
if (error.message === "Invalid private password") {
console.error("The password for the certificate is incorrect");
} else if (error.code === 'ENOENT') {
console.error("Certificate file not found");
} else {
console.error("Unexpected error:", error);
}
}
```
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
If you encounter any problems or have questions, please:
1. Check the [issues](https://github.com/mcalero11/dte-signer-sv/issues) page
2. Create a new issue if your problem isn't already listed
3. Provide as much detail as possible
## Acknowledgments
- Ministry of Finance of El Salvador for the DTE specifications
- The original Java implementation that inspired this Node.js port
## Disclaimer
This package is not officially affiliated with or endorsed by the Ministry of Finance of El Salvador. It is an independent implementation based on public specifications.