/** * Copyright [2009] [NIC Labs] * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or * agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * **/ package cl.nic.dte.extension; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509Certificate; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Date; import java.util.HashMap; import javax.xml.crypto.MarshalException; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.xmlbeans.XmlAnySimpleType; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import cl.nic.dte.TimbreException; import cl.nic.dte.VerifyResult; import cl.nic.dte.util.Utilities; import cl.nic.dte.util.XMLUtil; import cl.sii.siiDte.CAFType; import cl.sii.siiDte.DTEDefType; import cl.sii.siiDte.FechaHoraType; import cl.sii.siiDte.DTEDefType.Documento; import cl.sii.siiDte.DTEDefType.Exportaciones; import cl.sii.siiDte.DTEDefType.Liquidacion; import cl.sii.siiDte.DTEDefType.Documento.Detalle; import cl.sii.siiDte.DTEDefType.Documento.Encabezado.IdDoc; import cl.sii.siiDte.DTEDefType.Documento.TED.FRMT.Algoritmo; import cl.sii.siiDte.dsig.SignatureType; public class DTEDefTypeExtensionHandler { public static VerifyResult verifyXML(DTEDefType dte) { return XMLUtil.verifyXML(dte); } public static VerifyResult verifySignature(DTEDefType dte) { // Ojo, verifica la firma usando el keyValue, pero no verifica la // validez del // certificado. SignatureType sign = dte.getSignature(); // Find Signature element if (sign == null || sign.isNil()) { return new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels .getString("XML_SIGNATURE_ERROR_NOTFOUND")); } Date date = null; if (dte.isSetDocumento()) date = dte.getDocumento().getTmstFirma().getTime(); if (dte.isSetLiquidacion()) date = dte.getLiquidacion().getTmstFirma().getTime(); if (dte.isSetExportaciones()) date = dte.getExportaciones().getTmstFirma().getTime(); HashMap<String, String> namespaces = new HashMap<String, String>(); namespaces.put("", "http://www.sii.cl/SiiDte"); namespaces.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); XmlOptions opts = new XmlOptions(); opts.setSaveOuter(); opts.setSaveImplicitNamespaces(namespaces); try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document dte2 = dbf.newDocumentBuilder().parse( dte.newInputStream(opts)); NodeList nl = dte2.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nl.getLength() == 0) { return new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels .getString("XML_SIGNATURE_ERROR_NOTFOUND")); } return (XMLUtil.verifySignature(nl.item(0), date)); } catch (SAXException e) { return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels .getString("XML_SIGNATURE_ERROR_UNKNOWN") + ": " + e.getMessage())); } catch (IOException e) { return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels .getString("XML_SIGNATURE_ERROR_UNKNOWN") + ": " + e.getMessage())); } catch (ParserConfigurationException e) { return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels .getString("XML_SIGNATURE_ERROR_UNKNOWN") + ": " + e.getMessage())); } } public static byte[] sign(DTEDefType dte, PrivateKey pKey, X509Certificate cert) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyException, MarshalException, XMLSignatureException, SAXException, IOException, ParserConfigurationException, XmlException { String uri = ""; FechaHoraType now = FechaHoraType.Factory .newValue(Utilities.fechaHoraFormat.format(new Date())); if (dte.isSetDocumento()) { uri = dte.getDocumento().getID(); dte.getDocumento().xsetTmstFirma(now); } else if (dte.isSetLiquidacion()) { uri = dte.getLiquidacion().getID(); dte.getLiquidacion().xsetTmstFirma(now); } else if (dte.isSetExportaciones()) { uri = dte.getExportaciones().getID(); dte.getExportaciones().xsetTmstFirma(now); } uri = "#" + uri; HashMap<String, String> namespaces = new HashMap<String, String>(); namespaces.put("", "http://www.sii.cl/SiiDte"); XMLUtil.signEmbededApache(dte.getDomNode().getOwnerDocument(), uri, pKey, cert); XmlOptions opts = new XmlOptions(); opts.setCharacterEncoding("ISO-8859-1"); opts.setSaveImplicitNamespaces(namespaces); ByteArrayOutputStream out = new ByteArrayOutputStream(); dte.save(out, opts); return out.toByteArray(); } public static void timbrar(DTEDefType dte, CAFType caf, PrivateKey pKey) throws TimbreException, NoSuchAlgorithmException, SignatureException, InvalidKeyException { PublicKey pubKey = null; try { pubKey = caf.getPublicKey(); } catch (InvalidKeySpecException e1) { throw new InvalidKeyException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_KEY") + ": " + e1.getMessage()); } if (dte.isSetDocumento()) timbrar(dte.getDocumento(), caf.getCAFforDocument(), pubKey, pKey); else if (dte.isSetLiquidacion()) timbrar(dte.getLiquidacion(), caf.getCAFforLiquidacion(), pubKey, pKey); else if (dte.isSetExportaciones()) timbrar(dte.getExportaciones(), caf.getCAFforExportacion(), pubKey, pKey); } public static VerifyResult verifyTimbre(DTEDefType dte) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { if (dte.isSetDocumento()) return verifyTimbre(dte.getDocumento()); if (dte.isSetLiquidacion()) return verifyTimbre(dte.getLiquidacion()); if (dte.isSetExportaciones()) return verifyTimbre(dte.getExportaciones()); return null; } private static VerifyResult verifyTimbre(Exportaciones doc) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { DTEDefType.Exportaciones.TED.DD data = doc.getTED().getDD(); DTEDefType.Exportaciones.TED.FRMT frmt = doc.getTED().getFRMT(); DTEDefType.Exportaciones.TED.DD.CAF caf = data.getCAF(); cl.sii.siiDte.DTEDefType.Exportaciones.Encabezado.IdDoc iddoc = doc .getEncabezado().getIdDoc(); cl.sii.siiDte.DTEDefType.Exportaciones.Detalle[] det = doc .getDetalleArray(); if (!data.getTD().equals(iddoc.getTipoDTE()) || data.getF() != iddoc.getFolio() || !data.getRE().equals( doc.getEncabezado().getEmisor().getRUTEmisor()) || !data.getRR().equals( doc.getEncabezado().getReceptor().getRUTRecep()) || !data.getFE().equals(iddoc.getFchEmis()) || data.getMNT().longValue() != doc.getEncabezado() .getTotales().getMntTotal().longValue() || !data .getRSR() .equals( doc .getEncabezado() .getReceptor() .getRznSocRecep() .substring( 0, doc.getEncabezado() .getReceptor() .getRznSocRecep() .length() > 40 ? 40 : doc .getEncabezado() .getReceptor() .getRznSocRecep() .length())) || det == null || det.length > 0 || !data.getIT1().equals( det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0].getNmbItem().length())))) { return new VerifyResult(VerifyResult.TED_CONTENTS_WRONG, false, Utilities.verificationLabels .getString("TED_WRONG_CONTENTS")); } if (data.getF() < caf.getDA().getRNG().getD() || data.getF() > caf.getDA().getRNG().getH() || !data.getRE().equals(caf.getDA().getRE()) || !data.getTD().equals(caf.getDA().getTD())) { return new VerifyResult(VerifyResult.TED_WRONG_CAF, false, Utilities.verificationLabels.getString("TED_WRONG_CAF")); } Signature sig = null; cl.sii.siiDte.DTEDefType.Exportaciones.TED.FRMT.Algoritmo.Enum alg = frmt .getAlgoritmo(); PublicKey pKey = null; if (alg.equals(Algoritmo.SHA_1_WITH_RSA)) { sig = Signature.getInstance("SHA1withRSA"); DTEDefType.Exportaciones.TED.DD.CAF.DA.RSAPK kk = caf.getDA() .getRSAPK(); KeySpec keys = new RSAPublicKeySpec(new BigInteger(kk.getM()), new BigInteger(kk.getE())); pKey = KeyFactory.getInstance("RSA").generatePublic(keys); } else if (alg.equals(Algoritmo.SHA_1_WITH_DSA)) { sig = Signature.getInstance("SHA1withDSA"); DTEDefType.Exportaciones.TED.DD.CAF.DA.DSAPK kk = caf.getDA() .getDSAPK(); KeySpec keys = new DSAPublicKeySpec(new BigInteger(kk.getY()), new BigInteger(kk.getP()), new BigInteger(kk.getQ()), new BigInteger(kk.getG())); pKey = KeyFactory.getInstance("DSA").generatePublic(keys); } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); sig.initVerify(pKey); sig.update(XMLUtil.getCleaned(data)); if (sig.verify(frmt.getByteArrayValue())) { return new VerifyResult(VerifyResult.TED_OK, true, null); } else { return new VerifyResult(VerifyResult.TED_BAD_SIGNATURE, false, Utilities.verificationLabels.getString("TED_BAD_SIGNATURE")); } } private static VerifyResult verifyTimbre(Documento doc) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { DTEDefType.Documento.TED.DD data = doc.getTED().getDD(); DTEDefType.Documento.TED.FRMT frmt = doc.getTED().getFRMT(); DTEDefType.Documento.TED.DD.CAF caf = data.getCAF(); IdDoc iddoc = doc.getEncabezado().getIdDoc(); Detalle[] det = doc.getDetalleArray(); if (!data.getTD().equals(iddoc.getTipoDTE()) || data.getF() != iddoc.getFolio() || !data.getRE().equals( doc.getEncabezado().getEmisor().getRUTEmisor()) || !data.getRR().equals( doc.getEncabezado().getReceptor().getRUTRecep()) || !data.getFE().equals(iddoc.getFchEmis()) || data.getMNT().longValue() != doc.getEncabezado() .getTotales().getMntTotal() || !data .getRSR() .equals( doc .getEncabezado() .getReceptor() .getRznSocRecep() .substring( 0, doc.getEncabezado() .getReceptor() .getRznSocRecep() .length() > 40 ? 40 : doc .getEncabezado() .getReceptor() .getRznSocRecep() .length())) || det == null || det.length <= 0 || !data.getIT1().equals( det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0].getNmbItem().length())))) { return new VerifyResult(VerifyResult.TED_CONTENTS_WRONG, false, Utilities.verificationLabels .getString("TED_WRONG_CONTENTS")); } if (data.getF() < caf.getDA().getRNG().getD() || data.getF() > caf.getDA().getRNG().getH() || !data.getRE().equals(caf.getDA().getRE()) || !data.getTD().equals(caf.getDA().getTD())) { return new VerifyResult(VerifyResult.TED_WRONG_CAF, false, Utilities.verificationLabels.getString("TED_WRONG_CAF")); } Signature sig = null; Algoritmo.Enum alg = frmt.getAlgoritmo(); PublicKey pKey = null; if (alg.equals(Algoritmo.SHA_1_WITH_RSA)) { sig = Signature.getInstance("SHA1withRSA"); DTEDefType.Documento.TED.DD.CAF.DA.RSAPK kk = caf.getDA() .getRSAPK(); KeySpec keys = new RSAPublicKeySpec(new BigInteger(1, kk.getM()), new BigInteger(1, kk.getE())); pKey = KeyFactory.getInstance("RSA").generatePublic(keys); } else if (alg.equals(Algoritmo.SHA_1_WITH_DSA)) { sig = Signature.getInstance("SHA1withDSA"); DTEDefType.Documento.TED.DD.CAF.DA.DSAPK kk = caf.getDA() .getDSAPK(); KeySpec keys = new DSAPublicKeySpec(new BigInteger(kk.getY()), new BigInteger(kk.getP()), new BigInteger(kk.getQ()), new BigInteger(kk.getG())); pKey = KeyFactory.getInstance("DSA").generatePublic(keys); } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); sig.initVerify(pKey); sig.update(XMLUtil.getCleaned(data)); if (sig.verify(frmt.getByteArrayValue())) { return new VerifyResult(VerifyResult.TED_OK, true, null); } else { return new VerifyResult(VerifyResult.TED_BAD_SIGNATURE, false, Utilities.verificationLabels.getString("TED_BAD_SIGNATURE")); } } private static VerifyResult verifyTimbre(Liquidacion doc) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { DTEDefType.Liquidacion.TED.DD data = doc.getTED().getDD(); DTEDefType.Liquidacion.TED.FRMT frmt = doc.getTED().getFRMT(); DTEDefType.Liquidacion.TED.DD.CAF caf = data.getCAF(); cl.sii.siiDte.DTEDefType.Liquidacion.Encabezado.IdDoc iddoc = doc .getEncabezado().getIdDoc(); cl.sii.siiDte.DTEDefType.Liquidacion.Detalle[] det = doc .getDetalleArray(); if (!data.getTD().equals(iddoc.getTipoDTE()) || data.getF() != iddoc.getFolio() || !data.getRE().equals( doc.getEncabezado().getEmisor().getRUTEmisor()) || !data.getRR().equals( doc.getEncabezado().getReceptor().getRUTRecep()) || !data.getFE().equals(iddoc.getFchEmis()) || data.getMNT().longValue() != doc.getEncabezado() .getTotales().getMntTotal() || !data .getRSR() .equals( doc .getEncabezado() .getReceptor() .getRznSocRecep() .substring( 0, doc.getEncabezado() .getReceptor() .getRznSocRecep() .length() > 40 ? 40 : doc .getEncabezado() .getReceptor() .getRznSocRecep() .length())) || det == null || det.length > 0 || !data.getIT1().equals( det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0].getNmbItem().length())))) { return new VerifyResult(VerifyResult.TED_CONTENTS_WRONG, false, Utilities.verificationLabels .getString("TED_WRONG_CONTENTS")); } if (data.getF() < caf.getDA().getRNG().getD() || data.getF() > caf.getDA().getRNG().getH() || !data.getRE().equals(caf.getDA().getRE()) || !data.getTD().equals(caf.getDA().getTD())) { return new VerifyResult(VerifyResult.TED_WRONG_CAF, false, Utilities.verificationLabels.getString("TED_WRONG_CAF")); } Signature sig = null; cl.sii.siiDte.DTEDefType.Liquidacion.TED.FRMT.Algoritmo.Enum alg = frmt .getAlgoritmo(); PublicKey pKey = null; if (alg.equals(Algoritmo.SHA_1_WITH_RSA)) { sig = Signature.getInstance("SHA1withRSA"); DTEDefType.Liquidacion.TED.DD.CAF.DA.RSAPK kk = caf.getDA() .getRSAPK(); KeySpec keys = new RSAPublicKeySpec(new BigInteger(kk.getM()), new BigInteger(kk.getE())); pKey = KeyFactory.getInstance("RSA").generatePublic(keys); } else if (alg.equals(Algoritmo.SHA_1_WITH_DSA)) { sig = Signature.getInstance("SHA1withDSA"); DTEDefType.Liquidacion.TED.DD.CAF.DA.DSAPK kk = caf.getDA() .getDSAPK(); KeySpec keys = new DSAPublicKeySpec(new BigInteger(kk.getY()), new BigInteger(kk.getP()), new BigInteger(kk.getQ()), new BigInteger(kk.getG())); pKey = KeyFactory.getInstance("DSA").generatePublic(keys); } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); sig.initVerify(pKey); sig.update(XMLUtil.getCleaned(data)); if (sig.verify(frmt.getByteArrayValue())) { return new VerifyResult(VerifyResult.TED_OK, true, null); } else { return new VerifyResult(VerifyResult.TED_BAD_SIGNATURE, false, Utilities.verificationLabels.getString("TED_BAD_SIGNATURE")); } } private static void timbrar(Documento doc, DTEDefType.Documento.TED.DD.CAF caf, PublicKey pubKey, PrivateKey pKey) throws TimbreException, NoSuchAlgorithmException, SignatureException, InvalidKeyException { IdDoc iddoc = doc.getEncabezado().getIdDoc(); if (!iddoc.getTipoDTE().equals(caf.getDA().getTD())) throw new TimbreException(Utilities.exceptions .getString("CAF_NOT_CORRESPONDING")); long folio = iddoc.getFolio(); if (folio < caf.getDA().getRNG().getD() || folio > caf.getDA().getRNG().getH()) throw new TimbreException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_FOLIO")); if (!Utilities.correspond(pubKey, pKey)) throw new InvalidKeyException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_KEY")); Signature sig = null; Algoritmo.Enum siiAlg = null; String alg = pKey.getAlgorithm(); if (alg.equals("RSA")) { sig = Signature.getInstance("SHA1withRSA"); siiAlg = Algoritmo.SHA_1_WITH_RSA; } else if (alg.equals("DSA")) { sig = Signature.getInstance("SHA1withDSA"); siiAlg = Algoritmo.SHA_1_WITH_DSA; } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); DTEDefType.Documento.TED ted = doc.addNewTED(); XmlAnySimpleType version = XmlAnySimpleType.Factory.newInstance(); version.setStringValue("1.0"); ted.setVersion(version); DTEDefType.Documento.TED.DD data = ted.addNewDD(); data.addNewCAF().set(caf); data.setRE(doc.getEncabezado().getEmisor().getRUTEmisor()); data.setTD(iddoc.getTipoDTE()); data.setF(iddoc.getFolio()); data.setFE(iddoc.getFchEmis()); data.setRR(doc.getEncabezado().getReceptor().getRUTRecep()); data.setRSR(doc.getEncabezado().getReceptor().getRznSocRecep() .substring( 0, (doc.getEncabezado().getReceptor().getRznSocRecep() .length() > 40 ? 40 : doc.getEncabezado() .getReceptor().getRznSocRecep().length()))); data.setMNT(BigInteger.valueOf(doc.getEncabezado().getTotales() .getMntTotal())); Detalle[] det = doc.getDetalleArray(); if (det != null && det.length > 0) data.setIT1(det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0] .getNmbItem().length()))); data.xsetTSTED(FechaHoraType.Factory.newValue(Utilities.fechaHoraFormat .format(new Date()))); sig.initSign(pKey); sig.update(XMLUtil.getCleaned(data)); // sig.update(XMLUtil.getBytesXML(data)); DTEDefType.Documento.TED.FRMT frmt = ted.addNewFRMT(); frmt.setAlgoritmo(siiAlg); frmt.setByteArrayValue(sig.sign()); } private static void timbrar(Exportaciones doc, DTEDefType.Exportaciones.TED.DD.CAF caf, PublicKey pubKey, PrivateKey pKey) throws TimbreException, NoSuchAlgorithmException, SignatureException, InvalidKeyException { cl.sii.siiDte.DTEDefType.Exportaciones.Encabezado.IdDoc iddoc = doc .getEncabezado().getIdDoc(); if (!iddoc.getTipoDTE().equals(caf.getDA().getTD())) throw new TimbreException(Utilities.exceptions .getString("CAF_NOT_CORRESPONDING")); long folio = iddoc.getFolio(); if (folio < caf.getDA().getRNG().getD() || folio > caf.getDA().getRNG().getH()) throw new TimbreException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_FOLIO")); if (!Utilities.correspond(pubKey, pKey)) throw new InvalidKeyException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_KEY")); Signature sig = null; DTEDefType.Exportaciones.TED.FRMT.Algoritmo.Enum siiAlg = null; String alg = pKey.getAlgorithm(); if (alg.equals("RSA")) { sig = Signature.getInstance("SHA1withRSA"); siiAlg = DTEDefType.Exportaciones.TED.FRMT.Algoritmo.SHA_1_WITH_RSA; } else if (alg.equals("DSA")) { sig = Signature.getInstance("SHA1withDSA"); siiAlg = DTEDefType.Exportaciones.TED.FRMT.Algoritmo.SHA_1_WITH_DSA; } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); DTEDefType.Exportaciones.TED ted = doc.addNewTED(); XmlAnySimpleType version = XmlAnySimpleType.Factory.newInstance(); version.setStringValue("1.0"); ted.setVersion(version); DTEDefType.Exportaciones.TED.DD data = ted.addNewDD(); data.addNewCAF().set(caf); data.setRE(doc.getEncabezado().getEmisor().getRUTEmisor()); data.setTD(iddoc.getTipoDTE()); data.setF(iddoc.getFolio()); data.setFE(iddoc.getFchEmis()); data.setRR(doc.getEncabezado().getReceptor().getRUTRecep()); data.setRSR(doc.getEncabezado().getReceptor().getRznSocRecep()); data.setMNT(new BigDecimal(doc.getEncabezado().getTotales() .getMntTotal().unscaledValue())); cl.sii.siiDte.DTEDefType.Exportaciones.Detalle[] det = doc .getDetalleArray(); if (det != null && det.length > 0) data.setIT1(det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0] .getNmbItem().length()))); data.xsetTSTED(FechaHoraType.Factory.newValue(Utilities.fechaHoraFormat .format(new Date()))); sig.initSign(pKey); sig.update(XMLUtil.getCleaned(data)); DTEDefType.Exportaciones.TED.FRMT frmt = ted.addNewFRMT(); frmt.setAlgoritmo(siiAlg); frmt.setByteArrayValue(sig.sign()); } private static void timbrar(Liquidacion doc, DTEDefType.Liquidacion.TED.DD.CAF caf, PublicKey pubKey, PrivateKey pKey) throws TimbreException, NoSuchAlgorithmException, SignatureException, InvalidKeyException { cl.sii.siiDte.DTEDefType.Liquidacion.Encabezado.IdDoc iddoc = doc .getEncabezado().getIdDoc(); if (!iddoc.getTipoDTE().equals(caf.getDA().getTD())) throw new TimbreException(Utilities.exceptions .getString("CAF_NOT_CORRESPONDING")); long folio = iddoc.getFolio(); if (folio < caf.getDA().getRNG().getD() || folio > caf.getDA().getRNG().getH()) throw new TimbreException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_FOLIO")); if (!Utilities.correspond(pubKey, pKey)) throw new InvalidKeyException(Utilities.exceptions .getString("TIMBRE_ERROR_BAD_KEY")); Signature sig = null; DTEDefType.Liquidacion.TED.FRMT.Algoritmo.Enum siiAlg = null; String alg = pKey.getAlgorithm(); if (alg.equals("RSA")) { sig = Signature.getInstance("SHA1withRSA"); siiAlg = DTEDefType.Liquidacion.TED.FRMT.Algoritmo.SHA_1_WITH_RSA; } else if (alg.equals("DSA")) { sig = Signature.getInstance("SHA1withDSA"); siiAlg = DTEDefType.Liquidacion.TED.FRMT.Algoritmo.SHA_1_WITH_DSA; } else throw new NoSuchAlgorithmException(Utilities.exceptions .getString("ALG_NOT_SUPPORTED")); DTEDefType.Liquidacion.TED ted = doc.addNewTED(); XmlAnySimpleType version = XmlAnySimpleType.Factory.newInstance(); version.setStringValue("1.0"); ted.setVersion(version); DTEDefType.Liquidacion.TED.DD data = ted.addNewDD(); data.addNewCAF().set(caf); data.setRE(doc.getEncabezado().getEmisor().getRUTEmisor()); data.setTD(iddoc.getTipoDTE()); data.setF(iddoc.getFolio()); data.setFE(iddoc.getFchEmis()); data.setRR(doc.getEncabezado().getReceptor().getRUTRecep()); data.setRSR(doc.getEncabezado().getReceptor().getRznSocRecep()); data.setMNT(BigInteger.valueOf(doc.getEncabezado().getTotales() .getMntTotal())); cl.sii.siiDte.DTEDefType.Liquidacion.Detalle[] det = doc .getDetalleArray(); if (det != null && det.length > 0) data.setIT1(det[0].getNmbItem().substring( 0, (det[0].getNmbItem().length() > 40 ? 40 : det[0] .getNmbItem().length()))); data.xsetTSTED(FechaHoraType.Factory.newValue(Utilities.fechaHoraFormat .format(new Date()))); sig.initSign(pKey); sig.update(XMLUtil.getCleaned(data)); DTEDefType.Liquidacion.TED.FRMT frmt = ted.addNewFRMT(); frmt.setAlgoritmo(siiAlg); frmt.setByteArrayValue(sig.sign()); } public static X509Certificate getCertificate(DTEDefType dte) { return XMLUtil.getCertificate(dte.getSignature()); } public static byte[] getBytes(DTEDefType dte) throws IOException { HashMap<String, String> namespaces = new HashMap<String, String>(); namespaces.put("", "http://www.sii.cl/SiiDte"); XmlOptions opts = new XmlOptions(); opts.setCharacterEncoding("ISO-8859-1"); opts.setSaveImplicitNamespaces(namespaces); ByteArrayOutputStream out = new ByteArrayOutputStream(); dte.save(out, opts); return out.toByteArray(); } }