Java tutorial
/* Copyright (C) 2011 [Gobierno de Espana] * This file is part of "Cliente @Firma". * "Cliente @Firma" is free software; you can redistribute it and/or modify it under the terms of: * - the GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, or (at your option) any later version. * - or The European Software License; either version 1.1 or (at your option) any later version. * Date: 11/01/11 * You may contact the copyright holder at: soporte.afirma5@mpt.es */ package es.gob.afirma.signers.pkcs7; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.cms.EncryptedContentInfo; /** Método base para la generación deun tipo Signed and Enveloped * Data del estandar pkcs#7 basado en la RFC-2315. * La implementación del código ha seguido los pasos necesarios * para crear un SignedAndEnvelopedData desarrollado en BouncyCastle: <a * href="http://www.bouncycastle.org/">www.bouncycastle.org</a>. * <pre> * SignedAndEnvelopedData ::= SEQUENCE { * version Version, * recipientInfos RecipientInfos, * digestAlgorithms DigestAlgorithmIdentifiers, * encryptedContentInfo EncryptedContentInfo, * certificates [0] IMPLICIT Certificates OPTIONAL, * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, * signerInfos SignerInfos } * * RecipientInfos ::= SET OF RecipientInfo * * DigestAlgorithmIdentifiers ::= CHOICE { * daSet SET OF DigestAlgorithmIdentifier, * daSequence SEQUENCE OF DigestAlgorithmIdentifier } * * EncryptedContentInfo ::= SEQUENCE { * contentType ContentType, * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } * * </pre> */ public final class SignedAndEnvelopedData extends ASN1Object { private final ASN1Integer version; private final ASN1Set recipientInfos; /** <code>DigestAlgorithmIdentifiers</code>, que puede ser tanto un <code>SET</code> como una <code>SEQUENCE</code> * ASN.1 de estructuras <code>DigestAlgorithmIdentifier</code>. */ private ASN1Primitive digestAlgorithms; private final EncryptedContentInfo encryptedContentInfo; private ASN1Set certificates; private ASN1Set crls; private final ASN1Set signerInfos; /** Crea un objecto CMS SignedAndEnvelopedData. * @param recipientInfos RecipientInfo * @param digestAlgorithms ALgoritmos de huella digital * @param encryptedContentInfo EncryptedContentInfo * @param certificates Certificados * @param crls Listas de revoación de certificados * @param signerInfos SignerInfo */ public SignedAndEnvelopedData(final ASN1Set recipientInfos, final ASN1Primitive digestAlgorithms, final EncryptedContentInfo encryptedContentInfo, final ASN1Set certificates, final ASN1Set crls, final ASN1Set signerInfos) { this.version = new ASN1Integer(1); // Siempre 1 this.recipientInfos = recipientInfos; this.digestAlgorithms = digestAlgorithms; this.encryptedContentInfo = encryptedContentInfo; this.certificates = certificates; this.crls = crls; this.signerInfos = signerInfos; } /** Crea un objecto CMS SignedAndEnvelopedData a partir de una Secuencia ASN.1. * @param seq Secuencia ASN.1 origen */ public SignedAndEnvelopedData(final ASN1Sequence seq) { int index = 0; this.version = (ASN1Integer) seq.getObjectAt(index++); this.recipientInfos = ASN1Set.getInstance(seq.getObjectAt(index++)); // Los DigestAlgorithmIdentifiers pueden ser SET o SEQUENCE, probamos ambos final ASN1Encodable dai = seq.getObjectAt(index++); try { this.digestAlgorithms = ASN1Set.getInstance(dai); } catch (final IllegalArgumentException e) { this.digestAlgorithms = ASN1Sequence.getInstance(dai); } this.encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(index++)); if (seq.size() > 5) { if (seq.size() == 6) { this.certificates = ASN1Set.getInstance((ASN1TaggedObject) seq.getObjectAt(index++), false); } else { this.certificates = ASN1Set.getInstance((ASN1TaggedObject) seq.getObjectAt(index++), false); this.crls = ASN1Set.getInstance((ASN1TaggedObject) seq.getObjectAt(index++), false); } } this.signerInfos = ASN1Set.getInstance(seq.getObjectAt(index++)); } /** Obtiene un SignedAndEnvelopedData a partir de un objeto dado (que puede ser una secuencia ASN.1 o un mismo SignedAndEnvelopedData) * @param obj * El objeto que queremos convertir en un SignedAndEnvelopedData * @return SignedAndEnvelopedData creado a partir del objeto proporcionado * @exception IllegalArgumentException * si el objeto de entrada no puede ser convertido */ public static SignedAndEnvelopedData getInstance(final Object obj) { if (obj == null || obj instanceof SignedAndEnvelopedData) { return (SignedAndEnvelopedData) obj; } if (obj instanceof ASN1Sequence) { return new SignedAndEnvelopedData((ASN1Sequence) obj); } throw new IllegalArgumentException("EnvelopedData invalido: " + obj.getClass().getName()); //$NON-NLS-1$ } /** Obtiene la versión de la especificación usada. * @return La versión es siempre <code>1</code>*/ public ASN1Integer getVersion() { return this.version; } /** Obtiene los RecipientInfo en forma de Set ASN.1. * @return RecipientInfos */ public ASN1Set getRecipientInfos() { return this.recipientInfos; } /** Obtiene los algoritmos de huella digital en forma de Set ASN.1. * @return Algoritmos de huella digital */ public ASN1Primitive getDigestAlgorithms() { return this.digestAlgorithms; } /** Obtiene el EncryptedContentInfo. * @return EncryptedContentInfo */ public EncryptedContentInfo getEncryptedContentInfo() { return this.encryptedContentInfo; } /** Obtiene los Certificados en forma de Set ASN.1. * @return Certificados */ public ASN1Set getCertificates() { return this.certificates; } /** Obtiene los SignerInfo en forma de Set ASN.1. * @return SignerInfos */ public ASN1Set getSignerInfos() { return this.signerInfos; } /** Produce an object suitable for an ASN1OutputStream. * * <pre> * SignedAndEnvelopedData ::= SEQUENCE { * version Version, * recipientInfos RecipientInfos, * digestAlgorithms DigestAlgorithmIdentifiers, * encryptedContentInfo EncryptedContentInfo, * certificates * [0] IMPLICIT ExtendedCertificatesAndCertificates * OPTIONAL, * crls * [1] IMPLICIT CertificateRevocationLists OPTIONAL, * signerInfos SignerInfos } * * </pre> */ @Override public ASN1Primitive toASN1Primitive() { final ASN1EncodableVector v = new ASN1EncodableVector(); v.add(this.version); v.add(this.recipientInfos); v.add(this.digestAlgorithms); v.add(this.encryptedContentInfo); if (this.certificates != null) { v.add(new DERTaggedObject(false, 1, this.certificates)); } if (this.crls != null) { v.add(new DERTaggedObject(false, 1, this.crls)); } v.add(this.signerInfos); return new BERSequence(v); } }