Esta firma es la mas barata del mercado.
En formato:
Extención .p12
Estándar: X.509
Algoritmo: RSA-SHA1
Podre disponible para los lenguajes de programación Java y C#.
Java (Probado con el JDK de oracle):
1. Lo que tenemos que hacer es bajarnos las bibliotecas recomendadas inclusive en la documentacion del SRI.
Ingresamos a:
http://oficinavirtual.mityc.es/componentes/
Luego en descagas:
http://oficinavirtual.mityc.es/componentes/downloads.html
Nos bajamos los componentes incluyendo las dependencias.
componentes-1.1.7-with-deps.zip (Version al momento de escribir esta entrada).
2. Agregamos las referencias al proyecto donde estamos desarrollando. Preferiblemente incluir todas y las librerias de la firma.
Los jasrs estan dentro de la caperpeta deps y core.
3. De acuerdo a la documentacion debemos crear una clase que sirva como clase generica para la firma y una clase especifiquemos las lineas de codigo para nuestro tipo de firma.
En la documentacion del SRI explica que debemos usar el tipo de firma XAdES_BES. Por lo que la segunda clase nos ayudara para espicificar esto.
Clase FirmaGenerica (Clase abstracta como se muestra en la documentacion):
public abstract class GenericXMLSignature {
//Path de la firma electronica
private String pathSignature;
//calve de la firma electronica
private String passSignature;
/**
*
* Ejecución del ejemplo. La ejecución consistirá en la firma de los datos
* creados por el método abstracto
createDataToSign
mediante el* certificado declarado en la constante
PKCS12_FILE
. El* resultado del proceso de firma será almacenado en un fichero XML en el
* directorio correspondiente a la constante
OUTPUT_DIRECTORY
* del usuario bajo el nombre devuelto por el método abstracto
*
getSignFileName
*
*/
/*Metodos Getters y Setters (Propiedades)*/
public String getPathSignature() {
return pathSignature;
}
public void setPathSignature(String pathSignature) {
this.pathSignature = pathSignature;
}
public String getPassSignature() {
return passSignature;
}
public void setPassSignature(String passSignature) {
this.passSignature = passSignature;
}
protected void execute() {
// Obtencion del gestor de claves
KeyStore keyStore = getKeyStore();
if(keyStore==null){
System.err.println("No se pudo obtener almacen de firma.");
return;
}
String alias=getAlias(keyStore);
// Obtencion del certificado para firmar. Utilizaremos el primer
// certificado del almacen.
X509Certificate certificate = null;
try {
certificate = (X509Certificate)keyStore.getCertificate(alias);
if (certificate == null) {
System.err.println("No existe ningún certificado para firmar.");
return;
}
} catch (KeyStoreException e1) {
e1.printStackTrace();
}
// Obtención de la clave privada asociada al certificado
PrivateKey privateKey = null;
KeyStore tmpKs = keyStore;
try {
privateKey = (PrivateKey) tmpKs.getKey(alias, this.passSignature.toCharArray());
} catch (UnrecoverableKeyException e) {
System.err.println("No existe clave privada para firmar.");
e.printStackTrace();
} catch (KeyStoreException e) {
System.err.println("No existe clave privada para firmar.");
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
System.err.println("No existe clave privada para firmar.");
e.printStackTrace();
}
// Obtención del provider encargado de las labores criptográficas
Provider provider = keyStore.getProvider();
/*
* Creación del objeto que contiene tanto los datos a firmar como la
* configuración del tipo de firma
*/
DataToSign dataToSign = createDataToSign();
/*
* Creación del objeto encargado de realizar la firma
*/
FirmaXML firma = new FirmaXML();
// Firmamos el documento
Document docSigned = null;
try {
Object[] res = firma.signFile(certificate, dataToSign, privateKey, provider);
docSigned = (Document) res[0];
} catch (Exception ex) {
System.err.println("Error realizando la firma");
ex.printStackTrace();
return;
}
// Guardamos la firma a un fichero en el home del usuario
String filePath = getPathOut() + File.separatorChar + getSignatureFileName();
System.out.println("Firma salvada en en: " + filePath);
saveDocumenteDisk(docSigned, filePath);
}
/**
*
* Crea el objeto DataToSign que contiene toda la información de la firma
* que se desea realizar. Todas las implementaciones deberán proporcionar
* una implementación de este método
*
*
* @return El objeto DataToSign que contiene toda la información de la firma
* a realizar
*/
protected abstract DataToSign createDataToSign();
protected abstract String getSignatureFileName();
protected abstract String getPathOut();
protected Document getDocument(String resource) {
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
File file = new File(resource);
try {
DocumentBuilder db = dbf.newDocumentBuilder();
doc=db.parse(file);
} catch (ParserConfigurationException ex) {
System.err.println("Error al parsear el documento");
ex.printStackTrace();
System.exit(-1);
} catch (SAXException ex) {
System.err.println("Error al parsear el documento");
ex.printStackTrace();
System.exit(-1);
} catch (IOException ex) {
System.err.println("Error al parsear el documento");
ex.printStackTrace();
System.exit(-1);
} catch (IllegalArgumentException ex) {
System.err.println("Error al parsear el documento");
ex.printStackTrace();
System.exit(-1);
}
return doc;
}
private KeyStore getKeyStore()
{
KeyStore ks = null;
try {
ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(pathSignature), passSignature.toCharArray());
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return ks;
}
private static String getAlias(KeyStore keyStore)
{
String alias = null;
Enumeration
try {
nombres = keyStore.aliases();
while(nombres.hasMoreElements())
{
String tmpAlias = (String)nombres.nextElement();
if(keyStore.isKeyEntry(tmpAlias))
alias=tmpAlias;
}
}
catch (KeyStoreException e) {
e.printStackTrace();
}
return alias;
}
public static void saveDocumenteDisk(Document document,String pathXml)
{
try {
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(pathXml));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer;
transformer = transformerFactory.newTransformer();
transformer.transform(source, result);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
////Esta es la clase que extiende de Generic.
public class XAdESBESSignature extends GenericXMLSignature{
private static String nameFile;
private static String pathFile;
/**
*
* Recurso a firmar
*
*/
private String fileToSign;
/**
*
* Fichero donde se desea guardar la firma
*
*/
public XAdESBESSignature(String fileToSign) {
super();
this.fileToSign = fileToSign;
}
/**
*
* Punto de entrada al programa
*
*
* @param args
* Argumentos del programa
*/
public static void firmar(String xmlPath,String pathSignature,String passSignature,String pathOut,String nameFileOut)
{
//Document document=UtilApplication.convertStringToDocument(xml);
//String pathXml=UtilApplication.getTempPath()+"\\"+UUID.randomUUID().toString()+".xml";
//UtilApplication.saveDocumenteDisk(document, pathXml);
XAdESBESSignature signature = new XAdESBESSignature(xmlPath);
signature.setPassSignature(passSignature);
signature.setPathSignature(pathSignature);
pathFile=pathOut;
nameFile=nameFileOut;
signature.execute();
}
@Override
protected DataToSign createDataToSign() {
DataToSign datosAFirmar = new DataToSign();
datosAFirmar.setXadesFormat(es.mityc.javasign.EnumFormatoFirma.XAdES_BES);
datosAFirmar.setEsquema(XAdESSchemas.XAdES_132);
datosAFirmar.setXMLEncoding("UTF-8");
datosAFirmar.setEnveloped(true);
datosAFirmar.addObject(new ObjectToSign(new InternObjectToSign("comprobante"), "contenido comprobante", null, "text/xml", null));
datosAFirmar.setParentSignNode("comprobante");
Document docToSign = getDocument(fileToSign);
datosAFirmar.setDocument(docToSign);
return datosAFirmar;
}
@Override
protected String getSignatureFileName() {
return XAdESBESSignature.nameFile;
}
@Override
protected String getPathOut() {
return XAdESBESSignature.pathFile;
}
}
//Como usar dicha clase
XAdESBESSignature.firmar(String xmlPath,String pathFirma,String clavefirma,String directoriosalida, String nombreArchivoSalida);
//Hasta aqui la firma.
Los jars de referencias y necesarios son:
bcmail-jdk16-1.45.jar
bcprov-jdk16-1.45.jar
bctsp-jdk16-1.45.jar
commons-codec-1.8.jar
commons-httpclient-3.0.1.jar
commons-lang-2.4.jar
commons-logging-1.1.3.jar
DNIeJCAProvider-1.4.jar
iaikPkcs11Wrapper-1.1.7.jar
jss-4.2.5.jar
MITyCLibAPI-1.1.7.jar
MITyCLibCert-1.1.7.jar
MITyCLibOCSP-1.1.7.jar
MITyCLibTrust-1.1.7.jar
MITyCLibTSA-1.1.7.jar
MITyCLibXADES-1.1.7.jar
serializer-2.7.1.jar
sunpkcs11-1.0.jar
xalan-2.7.1.jar
xml-apis-1.3.04.jar
xmlsec-1.4.2-ADSI-1.1.jar
xmlsec-1.5.5.jar
///Para c# al momento lo que he logrado es esto por cuestiones de tiempo no he logrado terminar si alguien tiene terminao hagamelo saber.
public class Signature { Random rnd = new Random(DateTime.Now.
public const string XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/
public void Xml(String pathXml,String pathSignature,String passFirma)
{
//Declaro variable XMLDocument
XmlDocument xmlDoc = new XmlDocument();
// Cargo el documento en el xmlDoc
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(pathXml);
//Obtengo la firma en el Certificado X509
X509Certificate2 uidCert = new X509Certificate2(
//Inicializo el RSA
RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)
//Agrego el SgnedXml que permite firmar el xml
SignedXml signedXml = new SignedXml(xmlDoc);
// Add the key to the SignedXml document.
signedXml.SigningKey = rsaKey;
//signedXml.Signature.Id = newID("Signature");
//Agregamos el metodo de firmado
signedXml.SignedInfo.
//signedXml.SignedInfo.Id = newID("Signature-SignedInfo");
// Create a reference to be signed.
Reference reference = new Reference();
//reference.Id = newID("SignedPropertiesID");
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTrans
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(
// Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data clause = new KeyInfoX509Data();
clause.AddSubjectName(uidCert.
clause.AddCertificate(uidCert)
keyInfo.AddClause(clause);
//keyInfo.Id = newID("Certificate1");
signedXml.KeyInfo = keyInfo;
// Compute the signature.
signedXml.ComputeSignature();
Boolean respuesta = signedXml.CheckSignature();
System.Console.WriteLine(
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
//XmlElement signature = signedXml.GetXml();
foreach (XmlNode node in xmlDigitalSignature.
"descendant-or-self::*[
{
node.Prefix = "ds";
}
System.Console.WriteLine(
// Append the element to the XML document.
xmlDoc.DocumentElement.
xmlDoc.Save(@"D:\Xml\firmado.
}
private String newID(String prefix)
{
String newID = prefix + rnd.Next(1048576);
newID = prefix + rnd.Next(1048576);
return newID;
}
}
A mis amigos de los diferentes lenguajes que no sean java les recomiendo tratar de consumir los webservices del por medio de soap. Existe un software llamado SOAPUI. que permite o muestra como se consume en webservice. http://sourceforge.net/projects/soapui/files/
En .net he tenido problemas si se agrega como referencia no se porque no llena los objetos de retorno cuando se consume.
Es mi experiencia si alguie lo tiene no dude en compartir.
Disculpas no puedo subir proyectos por la sutacion comercial que puedan dar al mismo mi intencion es dar directrices que lo puedan lograr.
Por favor si algo no funciona sean mas especificos. error exacto.
Mas información (Comercial): http://www.corvustec.com/index.php?option=com_content&view=article&id=58&Itemid=87