List of usage examples for org.bouncycastle.asn1.cms ContentInfo ContentInfo
public ContentInfo(ASN1ObjectIdentifier contentType, ASN1Encodable content)
From source file:es.gob.afirma.signers.multi.cades.CAdESTriPhaseCounterSigner.java
License:Open Source License
/** Crea una contrafirma a partir de los datos * del firmante, el archivo que se firma y del archivo que contiene las * firmas.<br>/*from w w w . ja v a 2 s. c o m*/ * @param parameters * parámetros necesarios que contienen tanto la firma del * archivo a firmar como los datos del firmante. * @param data * Archivo que contiene las firmas. * @param targetType * Lo que se quiere firmar. Puede ser el árbol completo, * las hojas, un nodo determinado o unos determinados firmantes. * @param key Clave privada a usar para firmar. * @param certChain Cadena de certificados del firmante * @param policy Política de firma * @param signingCertificateV2 * <code>true</code> si se desea usar la versión 2 del * atributo <i>Signing Certificate</i> <code>false</code> para * usar la versión 1 * @param contentType * Tipo de contenido definido por su OID. * @param contentDescription * Descripción textual del tipo de contenido firmado. * @return El archivo de firmas con la nueva firma. * @throws java.io.IOException * Excepción cuando se produce algun error con lectura * escritura de ficheros. * @throws java.security.NoSuchAlgorithmException * Excepción cuando no se encuentra el algoritmo de * firma. * @throws java.security.cert.CertificateException * Si se produce alguna excepción con los certificados de * firma. * @throws AOException * Cuando ocurre alguno error con contemplado por las otras * excepciones declaradas */ public CAdESPreCounterSignResult preCounterSign(final P7ContentSignerParameters parameters, final byte[] data, final CounterSignTarget targetType, final PrivateKey key, final java.security.cert.Certificate[] certChain, final AdESPolicy policy, final boolean signingCertificateV2, final String contentType, final String contentDescription) throws IOException, NoSuchAlgorithmException, CertificateException, AOException { // Inicializamos el contador global y la lista de SignedDatas this.counterIndex = 0; this.signedDatas = new ArrayList<byte[]>(); // LEEMOS EL FICHERO QUE NOS INTRODUCEN final ASN1InputStream is = new ASN1InputStream(data); final ASN1Sequence dsq = (ASN1Sequence) is.readObject(); is.close(); final Enumeration<?> e = dsq.getObjects(); // Elementos que contienen los elementos OID SignedData e.nextElement(); // Contenido de SignedData final ASN1TaggedObject doj = (ASN1TaggedObject) e.nextElement(); final ASN1Sequence contentSignedData = (ASN1Sequence) doj.getObject(); final SignedData sd = SignedData.getInstance(contentSignedData); // Obtenemos los signerInfos del SignedData final ASN1Set signerInfosSd = sd.getSignerInfos(); // 4. CERTIFICADOS // obtenemos la lista de certificados ASN1Set certificates = null; final ASN1Set certificatesSigned = sd.getCertificates(); final ASN1EncodableVector vCertsSig = new ASN1EncodableVector(); final Enumeration<?> certs = certificatesSigned.getObjects(); // COGEMOS LOS CERTIFICADOS EXISTENTES EN EL FICHERO while (certs.hasMoreElements()) { vCertsSig.add((ASN1Encodable) certs.nextElement()); } // e introducimos los del firmante actual. if (certChain.length != 0) { final List<ASN1Encodable> ce = new ArrayList<ASN1Encodable>(); for (final java.security.cert.Certificate element : certChain) { ce.add(Certificate.getInstance(ASN1Primitive.fromByteArray(element.getEncoded()))); } certificates = SigUtils.fillRestCerts(ce, vCertsSig); } // CRLS no usado final ASN1Set certrevlist = null; // 5. SIGNERINFO // raiz de la secuencia de SignerInfo ASN1EncodableVector signerInfos = new ASN1EncodableVector(); // FIRMA EN ARBOL if (CounterSignTarget.TREE.equals(targetType)) { signerInfos = counterTree(signerInfosSd, parameters, key, certChain, contentType, contentDescription, policy, signingCertificateV2); } // FIRMA DE LAS HOJAS else if (CounterSignTarget.LEAFS.equals(targetType)) { signerInfos = counterLeaf(signerInfosSd, parameters, key, certChain, contentType, contentDescription, policy, signingCertificateV2); } else { throw new IllegalArgumentException("Modo de contrafirma no soportado: " + targetType); //$NON-NLS-1$ } // construimos el Signed Data y lo devolvemos dentro del resultado return new CAdESPreCounterSignResult( new ContentInfo(PKCSObjectIdentifiers.signedData, new SignedData(sd.getDigestAlgorithms(), sd.getEncapContentInfo(), certificates, certrevlist, new DERSet(signerInfos))).getEncoded(ASN1Encoding.DER), this.signedDatas); }
From source file:eu.europa.ec.markt.dss.validation.cades.CAdESSignature.java
License:Open Source License
@Override public byte[] getArchiveTimestampData(int index, Document originalDocument) throws IOException { ByteArrayOutputStream toTimestamp = new ByteArrayOutputStream(); ContentInfo contentInfo = cmsSignedData.getContentInfo(); SignedData signedData = SignedData.getInstance(contentInfo.getContent()); /* The encapContentInfo should always be present according to the standard, but sometimes it's omitted */ // 5.4.1/*from w w w. j a v a 2 s .co m*/ if (signedData.getEncapContentInfo() == null || signedData.getEncapContentInfo().getContent() == null) { /* Detached signatures have either no encapContentInfo in signedData, or it exists but has no eContent */ if (originalDocument != null) { toTimestamp.write(originalDocument.openStream()); } else { throw new RuntimeException("Signature is detached and no original data provided."); } } else { ContentInfo content = signedData.getEncapContentInfo(); DEROctetString octet = (DEROctetString) content.getContent(); ContentInfo info2 = new ContentInfo(new ASN1ObjectIdentifier("1.2.840.113549.1.7.1"), new BERConstructedOctetString(octet.getOctets())); toTimestamp.write(info2.getEncoded()); } if (signedData.getCertificates() != null) { DEROutputStream output = new DEROutputStream(toTimestamp); output.writeObject(signedData.getCertificates()); output.close(); } if (signedData.getCRLs() != null) { toTimestamp.write(signedData.getCRLs().getEncoded()); } if (signerInformation.getUnsignedAttributes() != null) { ASN1EncodableVector original = signerInformation.getUnsignedAttributes().toASN1EncodableVector(); List<Attribute> timeStampToRemove = getTimeStampToRemove(index); ASN1EncodableVector filtered = new ASN1EncodableVector(); for (int i = 0; i < original.size(); i++) { DEREncodable enc = original.get(i); if (!timeStampToRemove.contains(enc)) { filtered.add(original.get(i)); } } SignerInformation filteredInfo = SignerInformation.replaceUnsignedAttributes(signerInformation, new AttributeTable(filtered)); toTimestamp.write(filteredInfo.toASN1Structure().getEncoded()); } return toTimestamp.toByteArray(); }
From source file:eu.europa.ec.markt.dss.validation102853.cades.CAdESSignature.java
License:Open Source License
/** * This method handles the archive-timestamp-v2 * <p/>// w ww . j a v a2 s . co m * The value of the messageImprint field within TimeStampToken shall be a hash of the concatenation of: * the encapContentInfo element of the SignedData sequence; * any external content being protected by the signature, if the eContent element of the encapContentInfo is omitted; * the Certificates and crls elements of the SignedData sequence, when present; and * all data elements in the SignerInfo sequence including all signed and unsigned attributes. * <p/> * NOTE 1: An alternative archiveTimestamp attribute, identified by an object identifier { iso(1) member-body(2) * us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-aa(2) 27, is defined in prior versions of * TS 101 733. The archiveTimestamp attribute, defined in versions of TS 101 733 prior to 1.5.1, is not * compatible with the attribute defined in the present document. The archiveTimestamp attribute, defined in * versions 1.5.1 to 1.6.3 of TS 101 733, is compatible with the present document if the content is internal to * encapContentInfo. Unless the version of TS 101 733 employed by the signing party is known by all * recipients, use of the archiveTimestamp attribute defined in prior versions of TS 101 733 is deprecated. * NOTE 2: Counter signatures held as countersignature attributes do not require independent archive time-stamps as * they are protected by the archive time-stamp against the containing SignedData structure. * NOTE 3: Unless DER is used throughout, it is recommended that the binary encoding of the ASN.1 structures * being time-stamped be preserved when being archived to ensure that the recalculation of the data hash is * consistent. * NOTE 4: The hash is calculated over the concatenated data elements as received /stored including the Type and * Length encoding. * NOTE 5: Whilst it is recommended that unsigned attributes be DER encoded, it cannot generally be so guaranteed * except by prior arrangement. * * @param timestampToken * @return * @throws DSSException */ private byte[] getArchiveTimestampDataV2(TimestampToken timestampToken) throws DSSException { try { final ByteArrayOutputStream data = new ByteArrayOutputStream(); final ContentInfo contentInfo = cmsSignedData.toASN1Structure(); final SignedData signedData = SignedData.getInstance(contentInfo.getContent()); ContentInfo content = signedData.getEncapContentInfo(); if (content == null || content.getContent() == null) { /* Detached signatures have either no encapContentInfo in signedData, or it exists but has no eContent */ if (getOriginalDocumentBytes() != null) { data.write(content.toASN1Primitive().getEncoded()); data.write(getOriginalDocumentBytes()); } else { throw new DSSException("Signature is detached and no original data provided."); } } else { ASN1OctetString octet = (ASN1OctetString) content.getContent(); ContentInfo info2 = new ContentInfo(PKCSObjectIdentifiers.data, octet); final byte[] contentInfoBytes = info2.getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("Content Info: {}", DSSUtils.toHex(contentInfoBytes)); } data.write(contentInfoBytes); } final ASN1Set certificates = signedData.getCertificates(); if (certificates != null) { final byte[] certificatesBytes = new DERTaggedObject(false, 0, new DERSequence(certificates.toArray())).getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("Certificates: {}", DSSUtils.toHex(certificatesBytes)); } data.write(certificatesBytes); } if (signedData.getCRLs() != null) { final byte[] crlBytes = signedData.getCRLs().getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("CRLs: {}", DSSUtils.toHex(crlBytes)); } data.write(crlBytes); } final SignerInfo signerInfo = signerInformation.toASN1Structure(); final ByteArrayOutputStream signerByteArrayOutputStream = new ByteArrayOutputStream(); final ASN1Set unauthenticatedAttributes = signerInfo.getUnauthenticatedAttributes(); final ASN1Sequence filteredUnauthenticatedAttributes = filterUnauthenticatedAttributes( unauthenticatedAttributes, timestampToken); final ASN1Sequence asn1Object = getSignerInfoEncoded(signerInfo, filteredUnauthenticatedAttributes); for (int ii = 0; ii < asn1Object.size(); ii++) { final byte[] signerInfoBytes = DSSASN1Utils .getDEREncoded(asn1Object.getObjectAt(ii).toASN1Primitive()); signerByteArrayOutputStream.write(signerInfoBytes); } final byte[] signerInfoBytes = signerByteArrayOutputStream.toByteArray(); if (LOG.isTraceEnabled()) { LOG.trace("SignerInfoBytes: {}", DSSUtils.toHex(signerInfoBytes)); } data.write(signerInfoBytes); final byte[] result = data.toByteArray(); return result; } catch (IOException e) { throw new DSSException(e); } catch (Exception e) { // When error in computing or in format the algorithm just continues. LOG.warn("When error in computing or in format the algorithm just continue...", e); return DSSUtils.EMPTY_BYTE_ARRAY; } }
From source file:eu.europa.esig.dss.cades.validation.CAdESSignature.java
License:Open Source License
/** * This method handles the archive-timestamp-v2 * The value of the messageImprint field within TimeStampToken shall be a * hash of the concatenation of: the encapContentInfo element of the * SignedData sequence; any external content being protected by the * signature, if the eContent element of the encapContentInfo is omitted; * the Certificates and crls elements of the SignedData sequence, when * present; and all data elements in the SignerInfo sequence including all * signed and unsigned attributes./* w w w . j a va2 s . c o m*/ * NOTE 1: An alternative archiveTimestamp attribute, identified by an * object identifier { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) * pkcs-9(9) smime(16) id-aa(2) 27, is defined in prior versions of TS 101 * 733. The archiveTimestamp attribute, defined in versions of TS 101 733 * prior to 1.5.1, is not compatible with the attribute defined in the * present document. The archiveTimestamp attribute, defined in versions * 1.5.1 to 1.6.3 of TS 101 733, is compatible with the present document if * the content is internal to encapContentInfo. Unless the version of TS 101 * 733 employed by the signing party is known by all recipients, use of the * archiveTimestamp attribute defined in prior versions of TS 101 733 is * deprecated. NOTE 2: Counter signatures held as countersignature * attributes do not require independent archive time-stamps as they are * protected by the archive time-stamp against the containing SignedData * structure. NOTE 3: Unless DER is used throughout, it is recommended that * the binary encoding of the ASN.1 structures being time-stamped be * preserved when being archived to ensure that the recalculation of the * data hash is consistent. NOTE 4: The hash is calculated over the * concatenated data elements as received /stored including the Type and * Length encoding. NOTE 5: Whilst it is recommended that unsigned * attributes be DER encoded, it cannot generally be so guaranteed except by * prior arrangement. * * @param timestampToken * @return * @throws DSSException */ private byte[] getArchiveTimestampDataV2(TimestampToken timestampToken) throws DSSException { try { final ByteArrayOutputStream data = new ByteArrayOutputStream(); final ContentInfo contentInfo = cmsSignedData.toASN1Structure(); final SignedData signedData = SignedData.getInstance(contentInfo.getContent()); ContentInfo content = signedData.getEncapContentInfo(); if ((content == null) || (content.getContent() == null)) { /* * Detached signatures have either no encapContentInfo in * signedData, or it exists but has no eContent */ if (getOriginalDocumentStream() != null) { data.write(content.toASN1Primitive().getEncoded()); IOUtils.copy(getOriginalDocumentStream(), data); } else { throw new DSSException("Signature is detached and no original data provided."); } } else { ASN1OctetString octet = (ASN1OctetString) content.getContent(); ContentInfo info2 = new ContentInfo(PKCSObjectIdentifiers.data, octet); final byte[] contentInfoBytes = info2.getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("Content Info: {}", DSSUtils.toHex(contentInfoBytes)); } data.write(contentInfoBytes); } final ASN1Set certificates = signedData.getCertificates(); if (certificates != null) { final byte[] certificatesBytes = new DERTaggedObject(false, 0, new DERSequence(certificates.toArray())).getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("Certificates: {}", DSSUtils.toHex(certificatesBytes)); } data.write(certificatesBytes); } if (signedData.getCRLs() != null) { final byte[] crlBytes = signedData.getCRLs().getEncoded(); if (LOG.isTraceEnabled()) { LOG.trace("CRLs: {}", DSSUtils.toHex(crlBytes)); } data.write(crlBytes); } final SignerInfo signerInfo = signerInformation.toASN1Structure(); final ByteArrayOutputStream signerByteArrayOutputStream = new ByteArrayOutputStream(); final ASN1Set unauthenticatedAttributes = signerInfo.getUnauthenticatedAttributes(); final ASN1Sequence filteredUnauthenticatedAttributes = filterUnauthenticatedAttributes( unauthenticatedAttributes, timestampToken); final ASN1Sequence asn1Object = getSignerInfoEncoded(signerInfo, filteredUnauthenticatedAttributes); for (int ii = 0; ii < asn1Object.size(); ii++) { final byte[] signerInfoBytes = DSSASN1Utils .getDEREncoded(asn1Object.getObjectAt(ii).toASN1Primitive()); signerByteArrayOutputStream.write(signerInfoBytes); } final byte[] signerInfoBytes = signerByteArrayOutputStream.toByteArray(); if (LOG.isTraceEnabled()) { LOG.trace("SignerInfoBytes: {}", DSSUtils.toHex(signerInfoBytes)); } data.write(signerInfoBytes); final byte[] result = data.toByteArray(); return result; } catch (IOException e) { throw new DSSException(e); } catch (Exception e) { // When error in computing or in format the algorithm just // continues. LOG.warn("When error in computing or in format the algorithm just continue...", e); return DSSUtils.EMPTY_BYTE_ARRAY; } }
From source file:it.trento.comune.j4sign.cms.ExternalSignatureCMSSignedDataGenerator.java
License:Open Source License
/** * generate a CMS Signed Data object using the previously passed {@link ExternalSignatureSignerInfoGenerator} * objects; if encapsulate is true a copy of the message will be * included in the signature.//from ww w .j a v a2s. c o m */ public CMSSignedData generate(CMSProcessable content, boolean encapsulate) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, InvalidAlgorithmParameterException, CertStoreException { //DEREncodableVector signerInfos = new DEREncodableVector(); //DEREncodableVector digestAlgs = new DEREncodableVector(); ASN1EncodableVector digestAlgs = new ASN1EncodableVector(); ASN1EncodableVector signerInfos = new ASN1EncodableVector(); ASN1ObjectIdentifier contentTypeOID = new ASN1ObjectIdentifier(CMSSignedDataGenerator.DATA); // // add the SignerInfo objects // Iterator it = signerInfs.iterator(); //raccoglier i certificati dei firmatari //ArrayList certList = new ArrayList(); while (it.hasNext()) { AlgorithmIdentifier digAlgId, encAlgId; ExternalSignatureSignerInfoGenerator externalSigner = (ExternalSignatureSignerInfoGenerator) it.next(); try { digAlgId = makeAlgId(externalSigner.getDigestAlgOID(), externalSigner.getDigestAlgParams()); digestAlgs.add(digAlgId); signerInfos.add(externalSigner.generate()); //certList.add(externalSigner.getCertificate()); } catch (IOException e) { throw new CMSException("encoding error.", e); } catch (CertificateEncodingException e) { throw new CMSException("error creating sid.", e); } } ASN1Set certificates = null; if (certs.size() != 0) { certificates = createBerSetFromList(certs); } /* if (certs.size() != 0) { DEREncodableVector v = new DEREncodableVector(); it = certs.iterator(); while (it.hasNext()) { v.add((DEREncodable) it.next()); } certificates = new DERSet(v); } */ ASN1Set certrevlist = null; if (crls.size() != 0) { certrevlist = createBerSetFromList(crls); } /* if (crls.size() != 0) { DEREncodableVector v = new DEREncodableVector(); it = crls.iterator(); while (it.hasNext()) { v.add((DEREncodable) it.next()); } certrevlist = new DERSet(v); } */ ASN1OctetString octs = null; if (encapsulate) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); try { content.write(bOut); } catch (IOException e) { throw new CMSException("encapsulation error.", e); } octs = new BERConstructedOctetString(bOut.toByteArray()); } ContentInfo encInfo = new ContentInfo(contentTypeOID, octs); SignedData sd = new SignedData(new DERSet(digestAlgs), encInfo, certificates, certrevlist, new DERSet(signerInfos)); ContentInfo contentInfo = new ContentInfo(PKCSObjectIdentifiers.signedData, sd); return new CMSSignedData(content, contentInfo); }
From source file:net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.java
License:Apache License
public CMSSignedData generate(ASN1ObjectIdentifier contentTypeOID, ASN1Encodable content) throws CMSException, IOException { digests.clear();//from w w w. j a v a 2 s. c om SignerInfo signerInfo; if (!_signers.isEmpty()) { signerInfo = ((SignerInformation) _signers.get(0)).toASN1Structure(); } else { SignerInfoGenerator signerInfoGenerator = (SignerInfoGenerator) signerGens.get(0); byte[] signedContent = content.toASN1Primitive().getEncoded("DER"); OutputStream out = signerInfoGenerator.getCalculatingOutputStream(); out.write(signedContent, 2, signedContent.length - 2); // skip the first 2 bytes as specified out.flush(); out.close(); signerInfo = signerInfoGenerator.generate(contentTypeOID); byte[] calculatedDigest = signerInfoGenerator.getCalculatedDigest(); digests.put(signerInfoGenerator.getDigestAlgorithm().getAlgorithm().getId(), calculatedDigest); } ContentInfo encInfo = new ContentInfo(contentTypeOID, content); ASN1Set certificates = new DERSet((ASN1Encodable[]) certs.toArray(new ASN1Encodable[0])); ASN1Encodable signedData = new AuthenticodeSignedData(signerInfo.getDigestAlgorithm(), encInfo, certificates, signerInfo); ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, signedData); return new CMSSignedData( new CMSProcessableByteArray(contentTypeOID, content.toASN1Primitive().getEncoded("DER")), contentInfo); }
From source file:net.jsign.asn1.authenticode.AuthenticodeTimeStampRequest.java
License:Apache License
public AuthenticodeTimeStampRequest(byte[] digest) { contenInfo = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(digest)); }
From source file:org.jmrtd.lds.CardSecurityFile.java
License:Open Source License
private static ContentInfo toContentInfo(String contentTypeOID, Collection<SecurityInfo> securityInfos) { try {/*from w ww .j a v a 2s . com*/ ASN1EncodableVector vector = new ASN1EncodableVector(); for (SecurityInfo si : securityInfos) { vector.add(si.getDERObject()); } ASN1Set derSet = new DLSet(vector); return new ContentInfo(new ASN1ObjectIdentifier(contentTypeOID), new DEROctetString(derSet)); } catch (IOException ioe) { LOGGER.log(Level.SEVERE, "Error creating signedData: " + ioe.getMessage()); throw new IllegalArgumentException("Error DER encoding the security infos"); } }
From source file:org.jmrtd.lds.SODFile.java
License:Open Source License
private static ContentInfo toContentInfo(String contentTypeOID, String digestAlgorithm, Map<Integer, byte[]> dataGroupHashes, String ldsVersion, String unicodeVersion) throws NoSuchAlgorithmException, IOException { DataGroupHash[] dataGroupHashesArray = new DataGroupHash[dataGroupHashes.size()]; int i = 0;/*from w w w. ja v a 2 s .c o m*/ for (int dataGroupNumber : dataGroupHashes.keySet()) { byte[] hashBytes = dataGroupHashes.get(dataGroupNumber); DataGroupHash hash = new DataGroupHash(dataGroupNumber, new DEROctetString(hashBytes)); dataGroupHashesArray[i++] = hash; } AlgorithmIdentifier digestAlgorithmIdentifier = new AlgorithmIdentifier( new ASN1ObjectIdentifier(SignedDataUtil.lookupOIDByMnemonic(digestAlgorithm))); LDSSecurityObject securityObject = null; if (ldsVersion == null) { securityObject = new LDSSecurityObject(digestAlgorithmIdentifier, dataGroupHashesArray); } else { securityObject = new LDSSecurityObject(digestAlgorithmIdentifier, dataGroupHashesArray, new LDSVersionInfo(ldsVersion, unicodeVersion)); } return new ContentInfo(new ASN1ObjectIdentifier(contentTypeOID), new DEROctetString(securityObject)); }
From source file:org.signserver.module.mrtdsodsigner.jmrtd.SODFile.java
License:Open Source License
private static ContentInfo createContentInfo(String digestAlgorithm, Map<Integer, byte[]> dataGroupHashes, String ldsVersion, String unicodeVersion) throws NoSuchAlgorithmException, IOException { DataGroupHash[] dataGroupHashesArray = new DataGroupHash[dataGroupHashes.size()]; int i = 0;/*from ww w . j a v a 2 s . c o m*/ for (int dataGroupNumber : dataGroupHashes.keySet()) { byte[] hashBytes = dataGroupHashes.get(dataGroupNumber); DataGroupHash hash = new DataGroupHash(dataGroupNumber, new DEROctetString(hashBytes)); dataGroupHashesArray[i++] = hash; } AlgorithmIdentifier digestAlgorithmIdentifier = new AlgorithmIdentifier( lookupOIDByMnemonic(digestAlgorithm)); LDSVersionInfo ldsVersionInfo; if (ldsVersion == null) { ldsVersionInfo = null; } else { ldsVersionInfo = new LDSVersionInfo(new DERPrintableString(ldsVersion, true), new DERPrintableString(unicodeVersion, true)); } LDSSecurityObject sObject2 = new LDSSecurityObject(digestAlgorithmIdentifier, dataGroupHashesArray, ldsVersionInfo); return new ContentInfo(ICAO_SOD_OID, new DEROctetString(sObject2)); }