Firma digitale: il nuovo formato CAdES

Un semplice algoritmo di firma digitale
Data: 30/09/2013 Autore: Iasparra Francesco 

Aggiungiamo il provider di Baucy Castle che utilizzeremo per la generazione del nostro file firmato digitalmente con le nuove specifiche CAdES:

Security.addProvider(new BouncyCastleProvider());

Otteniamo dal keystor le informazioni necessarie sulla private key e sulla catena dei certificati.

KeyStore.Entry entry = ks.getEntry(alias, pp);
boolean isPrivateKeyEntry = ks.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class);
if (isPrivateKeyEntry){
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
    PrivateKey pk = privateKeyEntry.getPrivateKey();
    java.security.cert.Certificate[] chainx = privateKeyEntry.getCertificateChain();

Otteniamo il primo certificato di chiave pubblica che utilizzeremo per il nostro involucro:

ArrayList<X509Certificate> certsin=new ArrayList<X509Certificate>();for (int i=0;i<chainx.length;i++) certsin.add((X509Certificate) chainx[i]);X509Certificate cert=certsin.get(0);

Nel nuovo standard di firma digitale e' richiesto l'hash del certificato di sottoscrizione:

String digestAlgorithm = "SHA-256";
String digitalSignatureAlgorithmName = "SHA256withRSA";
MessageDigest sha = MessageDigest.getInstance(digestAlgorithm);
byte[] digestedCert = sha.digest(cert.getEncoded());

Viene ora create l'attributo ESSCertID versione 2 cosi come richiesto nel nuovo standard:

AlgorithmIdentifier aiSha256 = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
ESSCertIDv2 essCert1 = new ESSCertIDv2(aiSha256,digestedCert);
ESSCertIDv2[] essCert1Arr = {essCert1};
SigningCertificateV2 scv2 = new SigningCertificateV2(essCert1Arr);
Attribute certHAttribute = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2,new DERSet(scv2));

Aggiungiamo l'attributo al vettore degli attributi da firmare:

ASN1EncodableVector v = new ASN1EncodableVector();
v.add(certHAttribute);
AttributeTable at = new AttributeTable(v);
CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at);

Creaiamo l'oggetto che firma e crea l'involucro attraverso le librerie di Bouncy Castle:

SignerInfoGeneratorBuilder genBuild = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
genBuild.setSignedAttributeGenerator(attrGen);

Si effettua la firma con l'algoritmo SHA256withRSA che crea l'hash e lo firma con l'algoritmo RSA:

CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner shaSigner = new JcaContentSignerBuilder("SHA256withRSA").build(pk);
SignerInfoGenerator sifGen = genBuild.build(shaSigner, new X509CertificateHolder(cert.getEncoded()));
gen.addSignerInfoGenerator(sifGen);
X509CollectionStoreParameters x509CollectionStoreParameters = new X509CollectionStoreParameters(certsin);
JcaCertStore jcaCertStore = new JcaCertStore(certsin);
gen.addCertificates(jcaCertStore);

Attraverso la funzione loadFile carichiamo il file in un array di byte e lo firmiamo e lo alleghiamo al file involucro P7M:

byte[] plainfile = loadFile();
CMSTypedData msg = new CMSProcessableByteArray(plainfile);
CMSSignedData sigData = gen.generate(msg, true);
byte[] encoded = sigData.getEncoded();
FileOutputStream fos = new FileOutputStream("F:\\text.rtf.7.p7m");
fos.write(encoded);
fos.flush();
fos.close();


  • Java
  • Php
  • Mysql
  • Apache ant
  • Eclipse
  • Spring
  • Hibernate
  • Netbeans
  • Debian
  • Linux
  • Maven

by Iasparra Francesco - © Copyright 2021

E' vietata la riproduzione anche parziale dei materiali presenti in questo sito.

I marchi e le immagini esposti sono Copyright dei rispettivi proprietari.