Firmar datos usando PKCS #7 en JAVA

Quiero firmar un archivo de texto (puede ser un .exe archivo o algo más en el futuro) usando PKCS#7 y verifique la firma usando Java.

  1. ¿Qué necesito saber?
  2. ¿Dónde encontraré una API (.jar y documentación)?
  3. ¿Cuáles son los pasos que debo seguir para firmar los datos y verificar los datos?

Por favor, proporcione un fragmento de código si es posible.

preguntado el 22 de mayo de 12 a las 14:05

Estimado usuario, por favor vuelva a visitar esta vieja pregunta. He votado para cerrar la otra pregunta. Haga do su tarea antes de hacer preguntas. -

¿Desea que Windows reconozca el archivo exe firmado como firmado? -

2 Respuestas

Calculo que necesita los siguientes 2 frascos de Bouncy Castle para generar la firma digital PKCS7:

  • bcprov-jdk15on-147.jar (para JDK 1.5 - JDK 1.7)

  • bcmail-jdk15on-147.jar (para JDK 1.5 - JDK 1.7)

Puedes descargar los botes de Bouncy Castle desde aquí.

Debe configurar su almacén de claves con el par de claves pública y privada. Solo necesita la clave privada para generar la firma digital y la clave pública para verificarla.

Así es como firmarías el contenido de pkcs7 (se omite el manejo de excepciones por brevedad):

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;

public final class PKCS7Signer {

    private static final String PATH_TO_KEYSTORE = "/path/to/keyStore";
    private static final String KEY_ALIAS_IN_KEYSTORE = "My_Private_Key";
    private static final String KEYSTORE_PASSWORD = "MyPassword";
    private static final String SIGNATUREALGO = "SHA1withRSA";

    public PKCS7Signer() {
    }

    KeyStore loadKeyStore() throws Exception {

        KeyStore keystore = KeyStore.getInstance("JKS");
        InputStream is = new FileInputStream(PATH_TO_KEYSTORE);
        keystore.load(is, KEYSTORE_PASSWORD.toCharArray());
        return keystore;
    }

    CMSSignedDataGenerator setUpProvider(final KeyStore keystore) throws Exception {

        Security.addProvider(new BouncyCastleProvider());

        Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(KEY_ALIAS_IN_KEYSTORE);

        final List<Certificate> certlist = new ArrayList<Certificate>();

        for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
            certlist.add(certchain[i]);
        }

        Store certstore = new JcaCertStore(certlist);

        Certificate cert = keystore.getCertificate(KEY_ALIAS_IN_KEYSTORE);

        ContentSigner signer = new JcaContentSignerBuilder(SIGNATUREALGO).setProvider("BC").
                build((PrivateKey) (keystore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray())));

        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

        generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
                build()).build(signer, (X509Certificate) cert));

        generator.addCertificates(certstore);

        return generator;
    }

    byte[] signPkcs7(final byte[] content, final CMSSignedDataGenerator generator) throws Exception {

        CMSTypedData cmsdata = new CMSProcessableByteArray(content);
        CMSSignedData signeddata = generator.generate(cmsdata, true);
        return signeddata.getEncoded();
    }

    public static void main(String[] args) throws Exception {

        PKCS7Signer signer = new PKCS7Signer();
        KeyStore keyStore = signer.loadKeyStore();
        CMSSignedDataGenerator signatureGenerator = signer.setUpProvider(keyStore);
        String content = "some bytes to be signed";
        byte[] signedBytes = signer.signPkcs7(content.getBytes("UTF-8"), signatureGenerator);
        System.out.println("Signed Encoded Bytes: " + new String(Base64.encode(signedBytes)));
    }
}

contestado el 24 de mayo de 12 a las 06:05

¿Cómo genero una clave pública y privada? ¿Qué algoritmo puedo usar para firmar? no hemos mencionado la longitud de bits. ¿Puede proporcionar alguna referencia de material de estudio para que pueda entender a2z? user1269042

@ usuario1269042, Ver Criptografía de clave pública para comenzar. Google alrededor para encontrar más. Aunque un poco anticuado, Comenzando con la criptografía con Java es una excelente referencia. - Zaki

Olvidó mencionar la necesidad de bcpkix-jdk15on-147.jar (ahora 148) para las importaciones de org.bouncycastle.cms. - cirilo n

quieres decir que no necesitamos bcpkix-jdk15on ? - Hosein Aqajani

PKCS#7 ahora se conoce como CMS (sintaxis criptográfica de mensajes), y necesitará las bibliotecas PKIX de Bouncy Castle para crear una. Tiene una amplia documentación y una lista de correo bien establecida.

No proporcionaré un fragmento de código, va en contra de las reglas de la casa. Pruébate tú mismo primero.

contestado el 22 de mayo de 12 a las 20:05

La versión actual se llama bcpkix-jdk15on-147.jar, buscalo en Google. - Maarten Bodewes

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.