/** * This will get the character set for the font. * * @return The character set value. */ public String getCharSet() { String retval = null; COSString name = (COSString) dic.getDictionaryObject(COSName.CHAR_SET); if (name != null) { retval = name.getString(); } return retval; }
/** * A string representing the preferred font family. * * @return The font family. */ public String getFontFamily() { String retval = null; COSString name = (COSString) dic.getDictionaryObject(COSName.FONT_FAMILY); if (name != null) { retval = name.getString(); } return retval; }
/** * This will draw a string at the current location on the screen. * * @param text The text to draw. * @throws IOException If an io exception occurs. */ public void drawString(String text) throws IOException { if (!inTextMode) { throw new IOException("Error: must call beginText() before drawString"); } COSString string = new COSString(text); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); string.writePDF(buffer); appendRawCommands(new String(buffer.toByteArray(), "ISO-8859-1")); appendRawCommands(SPACE); appendRawCommands(SHOW_TEXT); }
private String getTrailerID(COSArray ids) { if (ids != null) { StringBuilder builder = new StringBuilder(); for (COSBase id : ids) { builder.append(((COSString) id).getASCII()).append(' '); } // need to discard last whitespace return builder.toString().substring(0, builder.length() - 2); } else { return null; } }
/** * Prepare the document for encryption. * * @param doc The document that will be encrypted. * @throws CryptographyException If there is an error while encrypting. */ public void prepareDocumentForEncryption(PDDocument doc) throws CryptographyException { try { Security.addProvider(new BouncyCastleProvider()); PDEncryptionDictionary dictionary = doc.getEncryptionDictionary(); if (dictionary == null) { dictionary = new PDEncryptionDictionary(); } dictionary.setFilter(FILTER); dictionary.setLength(this.keyLength); dictionary.setVersion(2); dictionary.setSubFilter(SUBFILTER); byte[][] recipientsField = new byte[policy.getRecipientsNumber()][]; // create the 20 bytes seed byte[] seed = new byte[20]; KeyGenerator key = KeyGenerator.getInstance("AES"); key.init(192, new SecureRandom()); SecretKey sk = key.generateKey(); System.arraycopy(sk.getEncoded(), 0, seed, 0, 20); // create the 20 bytes seed Iterator it = policy.getRecipientsIterator(); int i = 0; while (it.hasNext()) { PublicKeyRecipient recipient = (PublicKeyRecipient) it.next(); X509Certificate certificate = recipient.getX509(); int permission = recipient.getPermission().getPermissionBytesForPublicKey(); 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; DERObject obj = createDERForRecipient(pkcs7input, certificate); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DEROutputStream k = new DEROutputStream(baos); k.writeObject(obj); recipientsField[i] = baos.toByteArray(); i++; } dictionary.setRecipients(recipientsField); int sha1InputLength = seed.length; for (int j = 0; j < dictionary.getRecipientsLength(); j++) { COSString string = dictionary.getRecipientStringAt(j); sha1InputLength += string.getBytes().length; } byte[] sha1Input = new byte[sha1InputLength]; System.arraycopy(seed, 0, sha1Input, 0, 20); int sha1InputOffset = 20; for (int j = 0; j < dictionary.getRecipientsLength(); j++) { COSString string = dictionary.getRecipientStringAt(j); System.arraycopy( string.getBytes(), 0, sha1Input, sha1InputOffset, string.getBytes().length); sha1InputOffset += string.getBytes().length; } MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] mdResult = md.digest(sha1Input); this.encryptionKey = new byte[this.keyLength / 8]; System.arraycopy(mdResult, 0, this.encryptionKey, 0, this.keyLength / 8); doc.setEncryptionDictionary(dictionary); doc.getDocument().setEncryptionDictionary(dictionary.encryptionDictionary); } catch (NoSuchAlgorithmException ex) { throw new CryptographyException(ex); } catch (NoSuchProviderException ex) { throw new CryptographyException(ex); } catch (Exception e) { e.printStackTrace(); throw new CryptographyException(e); } }
/** * Prepares everything to decrypt the document. * * <p>If {@link #decryptDocument(PDDocument, DecryptionMaterial)} is used, this method is called * from there. Only if decryption of single objects is needed this should be called instead. * * @param encDictionary encryption dictionary, can be retrieved via {@link * PDDocument#getEncryptionDictionary()} * @param documentIDArray document id which is returned via {@link COSDocument#getDocumentID()} * (not used by this handler) * @param decryptionMaterial Information used to decrypt the document. * @throws IOException If there is an error accessing data. * @throws CryptographyException If there is an error with decryption. */ public void prepareForDecryption( PDEncryptionDictionary encDictionary, COSArray documentIDArray, DecryptionMaterial decryptionMaterial) throws CryptographyException, IOException { if (encDictionary.getLength() != 0) { this.keyLength = encDictionary.getLength(); } if (!(decryptionMaterial instanceof PublicKeyDecryptionMaterial)) { throw new CryptographyException( "Provided decryption material is not compatible with the document"); } PublicKeyDecryptionMaterial material = (PublicKeyDecryptionMaterial) decryptionMaterial; try { boolean foundRecipient = false; // the decrypted content of the enveloped data that match // the certificate in the decryption material provided byte[] envelopedData = null; // the bytes of each recipient in the recipients array byte[][] recipientFieldsBytes = new byte[encDictionary.getRecipientsLength()][]; int recipientFieldsLength = 0; for (int i = 0; i < encDictionary.getRecipientsLength(); i++) { COSString recipientFieldString = encDictionary.getRecipientStringAt(i); byte[] recipientBytes = recipientFieldString.getBytes(); CMSEnvelopedData data = new CMSEnvelopedData(recipientBytes); Iterator recipCertificatesIt = data.getRecipientInfos().getRecipients().iterator(); while (recipCertificatesIt.hasNext()) { RecipientInformation ri = (RecipientInformation) recipCertificatesIt.next(); // Impl: if a matching certificate was previously found it is an error, // here we just don't care about it if (ri.getRID().match(material.getCertificate()) && !foundRecipient) { foundRecipient = true; envelopedData = ri.getContent(material.getPrivateKey(), "BC"); } } recipientFieldsBytes[i] = recipientBytes; recipientFieldsLength += recipientBytes.length; } if (!foundRecipient || envelopedData == null) { throw new CryptographyException("The certificate matches no recipient entry"); } if (envelopedData.length != 24) { throw new CryptographyException("The enveloped data does not contain 24 bytes"); } // now envelopedData contains: // - the 20 bytes seed // - the 4 bytes of permission for the current user byte[] accessBytes = new byte[4]; System.arraycopy(envelopedData, 20, accessBytes, 0, 4); currentAccessPermission = new AccessPermission(accessBytes); currentAccessPermission.setReadOnly(); // what we will put in the SHA1 = the seed + each byte contained in the recipients array byte[] sha1Input = new byte[recipientFieldsLength + 20]; // put the seed in the sha1 input System.arraycopy(envelopedData, 0, sha1Input, 0, 20); // put each bytes of the recipients array in the sha1 input int sha1InputOffset = 20; for (int i = 0; i < recipientFieldsBytes.length; i++) { System.arraycopy( recipientFieldsBytes[i], 0, sha1Input, sha1InputOffset, recipientFieldsBytes[i].length); sha1InputOffset += recipientFieldsBytes[i].length; } MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] mdResult = md.digest(sha1Input); // we have the encryption key ... encryptionKey = new byte[this.keyLength / 8]; System.arraycopy(mdResult, 0, encryptionKey, 0, this.keyLength / 8); } catch (CMSException e) { throw new CryptographyException(e); } catch (KeyStoreException e) { throw new CryptographyException(e); } catch (NoSuchProviderException e) { throw new CryptographyException(e); } catch (NoSuchAlgorithmException e) { throw new CryptographyException(e); } }