class PdfPublicKeySecurityHandler {

    static final int SEED_LENGTH = 20;

    private final List<PdfPublicKeyRecipient> recipients;

    private byte[] seed = new byte[SEED_LENGTH];

    public PdfPublicKeySecurityHandler() {
        KeyGenerator key;
        try {
            key = KeyGenerator.getInstance("AES");
            key.init(192, new SecureRandom());
            SecretKey sk = key.generateKey();
            System.arraycopy(sk.getEncoded(), 0, seed, 0, SEED_LENGTH); // create the
            // 20 bytes
            // seed
        } catch (NoSuchAlgorithmException e) {
            seed = SecureRandom.getSeed(SEED_LENGTH);
        }

        recipients = new ArrayList<>();
    }

    public void addRecipient(PdfPublicKeyRecipient recipient) {
        recipients.add(recipient);
    }

    protected byte[] getSeed() {
        return seed.clone();
    }

    /*
     * public PdfPublicKeyRecipient[] getRecipients() { recipients.toArray();
     * return (PdfPublicKeyRecipient[])recipients.toArray(); }
     */

    public int getRecipientsSize() {
        return recipients.size();
    }

    public byte[] getEncodedRecipient(int index) throws IOException,
            GeneralSecurityException {
        // Certificate certificate = recipient.getX509();
        PdfPublicKeyRecipient recipient = recipients
                .get(index);
        byte[] cms = recipient.getCms();

        if (cms != null) {
            return cms;
        }

        Certificate certificate = recipient.getCertificate();
        int permission = recipient.getPermission();

        permission |= 0xfffff0c0;
        permission &= 0xfffffffc;
        permission += 1;

        byte[] pkcs7input = new byte[24];

        byte one = (byte) (permission);
        byte two = (byte) (permission >> 8);
        byte three = (byte) (permission >> 16);
        byte four = (byte) (permission >> 24);

        System.arraycopy(seed, 0, pkcs7input, 0, 20); // put this seed in the pkcs7
        // input

        pkcs7input[20] = four;
        pkcs7input[21] = three;
        pkcs7input[22] = two;
        pkcs7input[23] = one;

        ASN1Primitive obj = createDERForRecipient(pkcs7input,
                (X509Certificate) certificate);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        final ASN1OutputStream derOutputStream = ASN1OutputStream.create(baos, ASN1Encoding.DER);

        derOutputStream.writeObject(obj);

        cms = baos.toByteArray();

        recipient.setCms(cms);

        return cms;
    }

    public PdfArray getEncodedRecipients() throws IOException {
        PdfArray encodedRecipients = new PdfArray();
        byte[] cms;
        for (int i = 0; i < recipients.size(); i++) {
            try {
                cms = getEncodedRecipient(i);
                encodedRecipients.add(new PdfLiteral(PdfContentByte.escapeString(cms)));
            } catch (GeneralSecurityException | IOException e) {
                encodedRecipients = null;
                break;
            }
        }
        return encodedRecipients;
    }

    private ASN1Primitive createDERForRecipient(byte[] in, X509Certificate cert)
            throws IOException, GeneralSecurityException {

        String s = "1.2.840.113549.3.2";

        AlgorithmParameterGenerator algorithmparametergenerator = AlgorithmParameterGenerator
                .getInstance(s);
        AlgorithmParameters algorithmparameters = algorithmparametergenerator
                .generateParameters();
        ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(
                algorithmparameters.getEncoded("ASN.1"));
        ASN1InputStream asn1inputstream = new ASN1InputStream(bytearrayinputstream);
        ASN1Primitive derobject = asn1inputstream.readObject();
        KeyGenerator keygenerator = KeyGenerator.getInstance(s);
        keygenerator.init(128);
        SecretKey secretkey = keygenerator.generateKey();
        Cipher cipher = Cipher.getInstance(s);
        cipher.init(1, secretkey, algorithmparameters);
        byte[] abyte1 = cipher.doFinal(in);
        DEROctetString deroctetstring = new DEROctetString(abyte1);
        KeyTransRecipientInfo keytransrecipientinfo = computeRecipientInfo(cert,
                secretkey.getEncoded());
        DERSet derset = new DERSet(new RecipientInfo(keytransrecipientinfo));
        AlgorithmIdentifier algorithmidentifier = new AlgorithmIdentifier(
                new ASN1ObjectIdentifier(s), derobject);
        EncryptedContentInfo encryptedcontentinfo = new EncryptedContentInfo(
                PKCSObjectIdentifiers.data, algorithmidentifier, deroctetstring);
        ASN1Set set = null;
        EnvelopedData env = new EnvelopedData(null, derset, encryptedcontentinfo,
                set);
        ContentInfo contentinfo = new ContentInfo(
                PKCSObjectIdentifiers.envelopedData, env);
        // OJO... Modificacion de
        // Felix--------------------------------------------------
        // return contentinfo.getDERObject();
        return contentinfo.toASN1Primitive();
        // ******************************************************************************
    }

    private KeyTransRecipientInfo computeRecipientInfo(
            X509Certificate x509certificate, byte[] abyte0)
            throws GeneralSecurityException, IOException {<FILL_FUNCTION_BODY>}
}

        ASN1InputStream asn1inputstream = new ASN1InputStream(
                new ByteArrayInputStream(x509certificate.getTBSCertificate()));
        TBSCertificate tbsCertificate = TBSCertificate.getInstance(asn1inputstream.readObject());
        AlgorithmIdentifier algorithmidentifier = tbsCertificate.getSubjectPublicKeyInfo().getAlgorithm();
        IssuerAndSerialNumber issuerandserialnumber = new IssuerAndSerialNumber(
                tbsCertificate.getIssuer(), tbsCertificate.getSerialNumber().getValue());
        Cipher cipher = Cipher.getInstance(algorithmidentifier.getAlgorithm().getId());
        cipher.init(1, x509certificate);
        DEROctetString deroctetstring = new DEROctetString(cipher.doFinal(abyte0));
        RecipientIdentifier recipId = new RecipientIdentifier(issuerandserialnumber);
        return new KeyTransRecipientInfo(recipId, algorithmidentifier, deroctetstring);
    
<no_super_class>