001/* 002 * $Id: PdfEncryption.java 4789 2011-03-28 20:40:57Z psoares33 $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf; 045 046import com.itextpdf.text.pdf.crypto.ARCFOUREncryption; 047import com.itextpdf.text.error_messages.MessageLocalization; 048 049import java.io.IOException; 050import java.io.OutputStream; 051import java.io.ByteArrayOutputStream; 052import java.security.MessageDigest; 053import java.security.cert.Certificate; 054 055import com.itextpdf.text.ExceptionConverter; 056import com.itextpdf.text.exceptions.BadPasswordException; 057import com.itextpdf.text.pdf.crypto.AESCipherCBCnoPad; 058import com.itextpdf.text.pdf.crypto.IVGenerator; 059import java.security.DigestException; 060 061/** 062 * 063 * @author Paulo Soares 064 * @author Kazuya Ujihara 065 */ 066public class PdfEncryption { 067 068 public static final int STANDARD_ENCRYPTION_40 = 2; 069 070 public static final int STANDARD_ENCRYPTION_128 = 3; 071 072 public static final int AES_128 = 4; 073 074 public static final int AES_256 = 5; 075 076 private static final byte[] pad = { (byte) 0x28, (byte) 0xBF, (byte) 0x4E, 077 (byte) 0x5E, (byte) 0x4E, (byte) 0x75, (byte) 0x8A, (byte) 0x41, 078 (byte) 0x64, (byte) 0x00, (byte) 0x4E, (byte) 0x56, (byte) 0xFF, 079 (byte) 0xFA, (byte) 0x01, (byte) 0x08, (byte) 0x2E, (byte) 0x2E, 080 (byte) 0x00, (byte) 0xB6, (byte) 0xD0, (byte) 0x68, (byte) 0x3E, 081 (byte) 0x80, (byte) 0x2F, (byte) 0x0C, (byte) 0xA9, (byte) 0xFE, 082 (byte) 0x64, (byte) 0x53, (byte) 0x69, (byte) 0x7A }; 083 084 private static final byte[] salt = { (byte) 0x73, (byte) 0x41, (byte) 0x6c, 085 (byte) 0x54 }; 086 087 private static final byte[] metadataPad = { (byte) 255, (byte) 255, 088 (byte) 255, (byte) 255 }; 089 090 /** The encryption key for a particular object/generation */ 091 byte key[]; 092 093 /** The encryption key length for a particular object/generation */ 094 int keySize; 095 096 /** The global encryption key */ 097 byte mkey[] = new byte[0]; 098 099 /** Work area to prepare the object/generation bytes */ 100 byte extra[] = new byte[5]; 101 102 /** The message digest algorithm MD5 */ 103 MessageDigest md5; 104 105 /** The encryption key for the owner */ 106 byte ownerKey[] = new byte[32]; 107 108 /** The encryption key for the user */ 109 byte userKey[] = new byte[32]; 110 111 byte[] oeKey; 112 byte[] ueKey; 113 byte[] perms; 114 115 /** The public key security handler for certificate encryption */ 116 protected PdfPublicKeySecurityHandler publicKeyHandler = null; 117 118 int permissions; 119 120 byte documentID[]; 121 122 static long seq = System.currentTimeMillis(); 123 124 private int revision; 125 126 private ARCFOUREncryption arcfour = new ARCFOUREncryption(); 127 128 /** The generic key length. It may be 40 or 128. */ 129 private int keyLength; 130 131 private boolean encryptMetadata; 132 133 /** 134 * Indicates if the encryption is only necessary for embedded files. 135 * @since 2.1.3 136 */ 137 private boolean embeddedFilesOnly; 138 139 private int cryptoMode; 140 141 public PdfEncryption() { 142 try { 143 md5 = MessageDigest.getInstance("MD5"); 144 } catch (Exception e) { 145 throw new ExceptionConverter(e); 146 } 147 publicKeyHandler = new PdfPublicKeySecurityHandler(); 148 } 149 150 public PdfEncryption(PdfEncryption enc) { 151 this(); 152 if (enc.key != null) 153 key = (byte[]) enc.key.clone(); 154 keySize = enc.keySize; 155 mkey = (byte[]) enc.mkey.clone(); 156 ownerKey = (byte[]) enc.ownerKey.clone(); 157 userKey = (byte[]) enc.userKey.clone(); 158 permissions = enc.permissions; 159 if (enc.documentID != null) 160 documentID = (byte[]) enc.documentID.clone(); 161 revision = enc.revision; 162 keyLength = enc.keyLength; 163 encryptMetadata = enc.encryptMetadata; 164 embeddedFilesOnly = enc.embeddedFilesOnly; 165 publicKeyHandler = enc.publicKeyHandler; 166 } 167 168 public void setCryptoMode(int mode, int kl) { 169 cryptoMode = mode; 170 encryptMetadata = (mode & PdfWriter.DO_NOT_ENCRYPT_METADATA) != PdfWriter.DO_NOT_ENCRYPT_METADATA; 171 embeddedFilesOnly = (mode & PdfWriter.EMBEDDED_FILES_ONLY) == PdfWriter.EMBEDDED_FILES_ONLY; 172 mode &= PdfWriter.ENCRYPTION_MASK; 173 switch (mode) { 174 case PdfWriter.STANDARD_ENCRYPTION_40: 175 encryptMetadata = true; 176 embeddedFilesOnly = false; 177 keyLength = 40; 178 revision = STANDARD_ENCRYPTION_40; 179 break; 180 case PdfWriter.STANDARD_ENCRYPTION_128: 181 embeddedFilesOnly = false; 182 if (kl > 0) 183 keyLength = kl; 184 else 185 keyLength = 128; 186 revision = STANDARD_ENCRYPTION_128; 187 break; 188 case PdfWriter.ENCRYPTION_AES_128: 189 keyLength = 128; 190 revision = AES_128; 191 break; 192 case PdfWriter.ENCRYPTION_AES_256: 193 keyLength = 256; 194 keySize = 32; 195 revision = AES_256; 196 break; 197 default: 198 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("no.valid.encryption.mode")); 199 } 200 } 201 202 public int getCryptoMode() { 203 return cryptoMode; 204 } 205 206 public boolean isMetadataEncrypted() { 207 return encryptMetadata; 208 } 209 210 public int getPermissions() { 211 return permissions; 212 } 213 214 /** 215 * Indicates if only the embedded files have to be encrypted. 216 * @return if true only the embedded files will be encrypted 217 * @since 2.1.3 218 */ 219 public boolean isEmbeddedFilesOnly() { 220 return embeddedFilesOnly; 221 } 222 223 /** 224 */ 225 private byte[] padPassword(byte userPassword[]) { 226 byte userPad[] = new byte[32]; 227 if (userPassword == null) { 228 System.arraycopy(pad, 0, userPad, 0, 32); 229 } else { 230 System.arraycopy(userPassword, 0, userPad, 0, Math.min( 231 userPassword.length, 32)); 232 if (userPassword.length < 32) 233 System.arraycopy(pad, 0, userPad, userPassword.length, 234 32 - userPassword.length); 235 } 236 237 return userPad; 238 } 239 240 /** 241 */ 242 private byte[] computeOwnerKey(byte userPad[], byte ownerPad[]) { 243 byte ownerKey[] = new byte[32]; 244 byte digest[] = md5.digest(ownerPad); 245 if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) { 246 byte mkey[] = new byte[keyLength / 8]; 247 // only use for the input as many bit as the key consists of 248 for (int k = 0; k < 50; ++k) { 249 md5.update(digest, 0, mkey.length); 250 System.arraycopy(md5.digest(), 0, digest, 0, mkey.length); 251 } 252 System.arraycopy(userPad, 0, ownerKey, 0, 32); 253 for (int i = 0; i < 20; ++i) { 254 for (int j = 0; j < mkey.length; ++j) 255 mkey[j] = (byte) (digest[j] ^ i); 256 arcfour.prepareARCFOURKey(mkey); 257 arcfour.encryptARCFOUR(ownerKey); 258 } 259 } else { 260 arcfour.prepareARCFOURKey(digest, 0, 5); 261 arcfour.encryptARCFOUR(userPad, ownerKey); 262 } 263 return ownerKey; 264 } 265 266 /** 267 * 268 * ownerKey, documentID must be setup 269 */ 270 private void setupGlobalEncryptionKey(byte[] documentID, byte userPad[], 271 byte ownerKey[], int permissions) { 272 this.documentID = documentID; 273 this.ownerKey = ownerKey; 274 this.permissions = permissions; 275 // use variable keylength 276 mkey = new byte[keyLength / 8]; 277 278 // fixed by ujihara in order to follow PDF reference 279 md5.reset(); 280 md5.update(userPad); 281 md5.update(ownerKey); 282 283 byte ext[] = new byte[4]; 284 ext[0] = (byte) permissions; 285 ext[1] = (byte) (permissions >> 8); 286 ext[2] = (byte) (permissions >> 16); 287 ext[3] = (byte) (permissions >> 24); 288 md5.update(ext, 0, 4); 289 if (documentID != null) 290 md5.update(documentID); 291 if (!encryptMetadata) 292 md5.update(metadataPad); 293 294 byte digest[] = new byte[mkey.length]; 295 System.arraycopy(md5.digest(), 0, digest, 0, mkey.length); 296 297 // only use the really needed bits as input for the hash 298 if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) { 299 for (int k = 0; k < 50; ++k) 300 System.arraycopy(md5.digest(digest), 0, digest, 0, mkey.length); 301 } 302 303 System.arraycopy(digest, 0, mkey, 0, mkey.length); 304 } 305 306 /** 307 * 308 * mkey must be setup 309 */ 310 // use the revision to choose the setup method 311 private void setupUserKey() { 312 if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) { 313 md5.update(pad); 314 byte digest[] = md5.digest(documentID); 315 System.arraycopy(digest, 0, userKey, 0, 16); 316 for (int k = 16; k < 32; ++k) 317 userKey[k] = 0; 318 for (int i = 0; i < 20; ++i) { 319 for (int j = 0; j < mkey.length; ++j) 320 digest[j] = (byte) (mkey[j] ^ i); 321 arcfour.prepareARCFOURKey(digest, 0, mkey.length); 322 arcfour.encryptARCFOUR(userKey, 0, 16); 323 } 324 } else { 325 arcfour.prepareARCFOURKey(mkey); 326 arcfour.encryptARCFOUR(pad, userKey); 327 } 328 } 329 330 // gets keylength and revision and uses revision to choose the initial values 331 // for permissions 332 public void setupAllKeys(byte userPassword[], byte ownerPassword[], 333 int permissions) { 334 if (ownerPassword == null || ownerPassword.length == 0) 335 ownerPassword = md5.digest(createDocumentId()); 336 permissions |= (revision == STANDARD_ENCRYPTION_128 || revision == AES_128 || revision == AES_256) ? 0xfffff0c0 337 : 0xffffffc0; 338 permissions &= 0xfffffffc; 339 this.permissions = permissions; 340 if (revision == AES_256) { 341 try { 342 if (userPassword == null) 343 userPassword = new byte[0]; 344 documentID = createDocumentId(); 345 byte[] uvs = IVGenerator.getIV(8); 346 byte[] uks = IVGenerator.getIV(8); 347 key = IVGenerator.getIV(32); 348 // Algorithm 3.8.1 349 MessageDigest md = MessageDigest.getInstance("SHA-256"); 350 md.update(userPassword, 0, Math.min(userPassword.length, 127)); 351 md.update(uvs); 352 userKey = new byte[48]; 353 md.digest(userKey, 0, 32); 354 System.arraycopy(uvs, 0, userKey, 32, 8); 355 System.arraycopy(uks, 0, userKey, 40, 8); 356 // Algorithm 3.8.2 357 md.update(userPassword, 0, Math.min(userPassword.length, 127)); 358 md.update(uks); 359 AESCipherCBCnoPad ac = new AESCipherCBCnoPad(true, md.digest()); 360 ueKey = ac.processBlock(key, 0, key.length); 361 // Algorithm 3.9.1 362 byte[] ovs = IVGenerator.getIV(8); 363 byte[] oks = IVGenerator.getIV(8); 364 md.update(ownerPassword, 0, Math.min(ownerPassword.length, 127)); 365 md.update(ovs); 366 md.update(userKey); 367 ownerKey = new byte[48]; 368 md.digest(ownerKey, 0, 32); 369 System.arraycopy(ovs, 0, ownerKey, 32, 8); 370 System.arraycopy(oks, 0, ownerKey, 40, 8); 371 // Algorithm 3.9.2 372 md.update(ownerPassword, 0, Math.min(ownerPassword.length, 127)); 373 md.update(oks); 374 md.update(userKey); 375 ac = new AESCipherCBCnoPad(true, md.digest()); 376 oeKey = ac.processBlock(key, 0, key.length); 377 // Algorithm 3.10 378 byte[] permsp = IVGenerator.getIV(16); 379 permsp[0] = (byte)permissions; 380 permsp[1] = (byte)(permissions >> 8); 381 permsp[2] = (byte)(permissions >> 16); 382 permsp[3] = (byte)(permissions >> 24); 383 permsp[4] = (byte)(255); 384 permsp[5] = (byte)(255); 385 permsp[6] = (byte)(255); 386 permsp[7] = (byte)(255); 387 permsp[8] = encryptMetadata ? (byte)'T' : (byte)'F'; 388 permsp[9] = (byte)'a'; 389 permsp[10] = (byte)'d'; 390 permsp[11] = (byte)'b'; 391 ac = new AESCipherCBCnoPad(true, key); 392 perms = ac.processBlock(permsp, 0, permsp.length); 393 } 394 catch (Exception ex) { 395 throw new ExceptionConverter(ex); 396 } 397 } 398 else { 399 // PDF reference 3.5.2 Standard Security Handler, Algorithm 3.3-1 400 // If there is no owner password, use the user password instead. 401 byte userPad[] = padPassword(userPassword); 402 byte ownerPad[] = padPassword(ownerPassword); 403 404 this.ownerKey = computeOwnerKey(userPad, ownerPad); 405 documentID = createDocumentId(); 406 setupByUserPad(this.documentID, userPad, this.ownerKey, permissions); 407 } 408 } 409 410 private static final int VALIDATION_SALT_OFFSET = 32; 411 private static final int KEY_SALT_OFFSET = 40; 412 private static final int SALT_LENGHT = 8; 413 private static final int OU_LENGHT = 48; 414 415 public boolean readKey(PdfDictionary enc, byte[] password) throws BadPasswordException { 416 try { 417 if (password == null) 418 password = new byte[0]; 419 byte[] oValue = com.itextpdf.text.DocWriter.getISOBytes(enc.get(PdfName.O).toString()); 420 byte[] uValue = com.itextpdf.text.DocWriter.getISOBytes(enc.get(PdfName.U).toString()); 421 byte[] oeValue = com.itextpdf.text.DocWriter.getISOBytes(enc.get(PdfName.OE).toString()); 422 byte[] ueValue = com.itextpdf.text.DocWriter.getISOBytes(enc.get(PdfName.UE).toString()); 423 byte[] perms = com.itextpdf.text.DocWriter.getISOBytes(enc.get(PdfName.PERMS).toString()); 424 boolean isUserPass = false; 425 MessageDigest md = MessageDigest.getInstance("SHA-256"); 426 md.update(password, 0, Math.min(password.length, 127)); 427 md.update(oValue, VALIDATION_SALT_OFFSET, SALT_LENGHT); 428 md.update(uValue, 0, OU_LENGHT); 429 byte[] hash = md.digest(); 430 boolean isOwnerPass = compareArray(hash, oValue, 32); 431 if (isOwnerPass) { 432 md.update(password, 0, Math.min(password.length, 127)); 433 md.update(oValue, KEY_SALT_OFFSET, SALT_LENGHT); 434 md.update(uValue, 0, OU_LENGHT); 435 hash = md.digest(); 436 AESCipherCBCnoPad ac = new AESCipherCBCnoPad(false, hash); 437 key = ac.processBlock(oeValue, 0, oeValue.length); 438 } 439 else { 440 md.update(password, 0, Math.min(password.length, 127)); 441 md.update(uValue, VALIDATION_SALT_OFFSET, SALT_LENGHT); 442 hash = md.digest(); 443 isUserPass = compareArray(hash, uValue, 32); 444 if (!isUserPass) 445 throw new BadPasswordException(MessageLocalization.getComposedMessage("bad.user.password")); 446 md.update(password, 0, Math.min(password.length, 127)); 447 md.update(uValue, KEY_SALT_OFFSET, SALT_LENGHT); 448 hash = md.digest(); 449 AESCipherCBCnoPad ac = new AESCipherCBCnoPad(false, hash); 450 key = ac.processBlock(ueValue, 0, ueValue.length); 451 } 452 AESCipherCBCnoPad ac = new AESCipherCBCnoPad(false, key); 453 byte[] decPerms = ac.processBlock(perms, 0, perms.length); 454 if (decPerms[9] != (byte)'a' || decPerms[10] != (byte)'d' || decPerms[11] != (byte)'b') 455 throw new BadPasswordException(MessageLocalization.getComposedMessage("bad.user.password")); 456 permissions = (decPerms[0] & 0xff) | ((decPerms[1] & 0xff) << 8) 457 | ((decPerms[2] & 0xff) << 16) | ((decPerms[2] & 0xff) << 24); 458 encryptMetadata = decPerms[8] == (byte)'T'; 459 return isOwnerPass; 460 } 461 catch (BadPasswordException ex) { 462 throw ex; 463 } 464 catch (Exception ex) { 465 throw new ExceptionConverter(ex); 466 } 467 } 468 469 private static boolean compareArray(byte[] a, byte[] b, int len) { 470 for (int k = 0; k < len; ++k) { 471 if (a[k] != b[k]) { 472 return false; 473 } 474 } 475 return true; 476 } 477 478 public static byte[] createDocumentId() { 479 MessageDigest md5; 480 try { 481 md5 = MessageDigest.getInstance("MD5"); 482 } catch (Exception e) { 483 throw new ExceptionConverter(e); 484 } 485 long time = System.currentTimeMillis(); 486 long mem = Runtime.getRuntime().freeMemory(); 487 String s = time + "+" + mem + "+" + (seq++); 488 return md5.digest(s.getBytes()); 489 } 490 491 /** 492 */ 493 public void setupByUserPassword(byte[] documentID, byte userPassword[], 494 byte ownerKey[], int permissions) { 495 setupByUserPad(documentID, padPassword(userPassword), ownerKey, 496 permissions); 497 } 498 499 /** 500 */ 501 private void setupByUserPad(byte[] documentID, byte userPad[], 502 byte ownerKey[], int permissions) { 503 setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions); 504 setupUserKey(); 505 } 506 507 /** 508 */ 509 public void setupByOwnerPassword(byte[] documentID, byte ownerPassword[], 510 byte userKey[], byte ownerKey[], int permissions) { 511 setupByOwnerPad(documentID, padPassword(ownerPassword), userKey, 512 ownerKey, permissions); 513 } 514 515 private void setupByOwnerPad(byte[] documentID, byte ownerPad[], 516 byte userKey[], byte ownerKey[], int permissions) { 517 byte userPad[] = computeOwnerKey(ownerKey, ownerPad); // userPad will 518 // be set in 519 // this.ownerKey 520 setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions); // step 521 // 3 522 setupUserKey(); 523 } 524 525 public void setupByEncryptionKey(byte[] key, int keylength) { 526 mkey = new byte[keylength / 8]; 527 System.arraycopy(key, 0, mkey, 0, mkey.length); 528 } 529 530 public void setHashKey(int number, int generation) { 531 if (revision == AES_256) 532 return; 533 md5.reset(); // added by ujihara 534 extra[0] = (byte) number; 535 extra[1] = (byte) (number >> 8); 536 extra[2] = (byte) (number >> 16); 537 extra[3] = (byte) generation; 538 extra[4] = (byte) (generation >> 8); 539 md5.update(mkey); 540 md5.update(extra); 541 if (revision == AES_128) 542 md5.update(salt); 543 key = md5.digest(); 544 keySize = mkey.length + 5; 545 if (keySize > 16) 546 keySize = 16; 547 } 548 549 public static PdfObject createInfoId(byte id[]) { 550 ByteBuffer buf = new ByteBuffer(90); 551 buf.append('[').append('<'); 552 for (int k = 0; k < 16; ++k) 553 buf.appendHex(id[k]); 554 buf.append('>').append('<'); 555 id = createDocumentId(); 556 for (int k = 0; k < 16; ++k) 557 buf.appendHex(id[k]); 558 buf.append('>').append(']'); 559 return new PdfLiteral(buf.toByteArray()); 560 } 561 562 public PdfDictionary getEncryptionDictionary() { 563 PdfDictionary dic = new PdfDictionary(); 564 565 if (publicKeyHandler.getRecipientsSize() > 0) { 566 PdfArray recipients = null; 567 568 dic.put(PdfName.FILTER, PdfName.PUBSEC); 569 dic.put(PdfName.R, new PdfNumber(revision)); 570 571 try { 572 recipients = publicKeyHandler.getEncodedRecipients(); 573 } catch (Exception f) { 574 throw new ExceptionConverter(f); 575 } 576 577 if (revision == STANDARD_ENCRYPTION_40) { 578 dic.put(PdfName.V, new PdfNumber(1)); 579 dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4); 580 dic.put(PdfName.RECIPIENTS, recipients); 581 } else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) { 582 dic.put(PdfName.V, new PdfNumber(2)); 583 dic.put(PdfName.LENGTH, new PdfNumber(128)); 584 dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4); 585 dic.put(PdfName.RECIPIENTS, recipients); 586 } else { 587 dic.put(PdfName.R, new PdfNumber(AES_128)); 588 dic.put(PdfName.V, new PdfNumber(4)); 589 dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S5); 590 591 PdfDictionary stdcf = new PdfDictionary(); 592 stdcf.put(PdfName.RECIPIENTS, recipients); 593 if (!encryptMetadata) 594 stdcf.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE); 595 596 if (revision == AES_128) 597 stdcf.put(PdfName.CFM, PdfName.AESV2); 598 else 599 stdcf.put(PdfName.CFM, PdfName.V2); 600 PdfDictionary cf = new PdfDictionary(); 601 cf.put(PdfName.DEFAULTCRYPTFILTER, stdcf); 602 dic.put(PdfName.CF, cf); 603 if (embeddedFilesOnly) { 604 dic.put(PdfName.EFF, PdfName.DEFAULTCRYPTFILTER); 605 dic.put(PdfName.STRF, PdfName.IDENTITY); 606 dic.put(PdfName.STMF, PdfName.IDENTITY); 607 } 608 else { 609 dic.put(PdfName.STRF, PdfName.DEFAULTCRYPTFILTER); 610 dic.put(PdfName.STMF, PdfName.DEFAULTCRYPTFILTER); 611 } 612 } 613 614 MessageDigest md = null; 615 byte[] encodedRecipient = null; 616 617 try { 618 md = MessageDigest.getInstance("SHA-1"); 619 md.update(publicKeyHandler.getSeed()); 620 for (int i = 0; i < publicKeyHandler.getRecipientsSize(); i++) { 621 encodedRecipient = publicKeyHandler.getEncodedRecipient(i); 622 md.update(encodedRecipient); 623 } 624 if (!encryptMetadata) 625 md.update(new byte[] { (byte) 255, (byte) 255, (byte) 255, 626 (byte) 255 }); 627 } catch (Exception f) { 628 throw new ExceptionConverter(f); 629 } 630 631 byte[] mdResult = md.digest(); 632 633 setupByEncryptionKey(mdResult, keyLength); 634 } else { 635 dic.put(PdfName.FILTER, PdfName.STANDARD); 636 dic.put(PdfName.O, new PdfLiteral(PdfContentByte 637 .escapeString(ownerKey))); 638 dic.put(PdfName.U, new PdfLiteral(PdfContentByte 639 .escapeString(userKey))); 640 dic.put(PdfName.P, new PdfNumber(permissions)); 641 dic.put(PdfName.R, new PdfNumber(revision)); 642 643 if (revision == STANDARD_ENCRYPTION_40) { 644 dic.put(PdfName.V, new PdfNumber(1)); 645 } else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) { 646 dic.put(PdfName.V, new PdfNumber(2)); 647 dic.put(PdfName.LENGTH, new PdfNumber(128)); 648 649 } 650 else if (revision == AES_256) { 651 if (!encryptMetadata) 652 dic.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE); 653 dic.put(PdfName.OE, new PdfLiteral(PdfContentByte 654 .escapeString(oeKey))); 655 dic.put(PdfName.UE, new PdfLiteral(PdfContentByte 656 .escapeString(ueKey))); 657 dic.put(PdfName.PERMS, new PdfLiteral(PdfContentByte 658 .escapeString(perms))); 659 dic.put(PdfName.V, new PdfNumber(revision)); 660 dic.put(PdfName.LENGTH, new PdfNumber(256)); 661 PdfDictionary stdcf = new PdfDictionary(); 662 stdcf.put(PdfName.LENGTH, new PdfNumber(32)); 663 if (embeddedFilesOnly) { 664 stdcf.put(PdfName.AUTHEVENT, PdfName.EFOPEN); 665 dic.put(PdfName.EFF, PdfName.STDCF); 666 dic.put(PdfName.STRF, PdfName.IDENTITY); 667 dic.put(PdfName.STMF, PdfName.IDENTITY); 668 } 669 else { 670 stdcf.put(PdfName.AUTHEVENT, PdfName.DOCOPEN); 671 dic.put(PdfName.STRF, PdfName.STDCF); 672 dic.put(PdfName.STMF, PdfName.STDCF); 673 } 674 stdcf.put(PdfName.CFM, PdfName.AESV3); 675 PdfDictionary cf = new PdfDictionary(); 676 cf.put(PdfName.STDCF, stdcf); 677 dic.put(PdfName.CF, cf); 678 } 679 else { 680 if (!encryptMetadata) 681 dic.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE); 682 dic.put(PdfName.R, new PdfNumber(AES_128)); 683 dic.put(PdfName.V, new PdfNumber(4)); 684 dic.put(PdfName.LENGTH, new PdfNumber(128)); 685 PdfDictionary stdcf = new PdfDictionary(); 686 stdcf.put(PdfName.LENGTH, new PdfNumber(16)); 687 if (embeddedFilesOnly) { 688 stdcf.put(PdfName.AUTHEVENT, PdfName.EFOPEN); 689 dic.put(PdfName.EFF, PdfName.STDCF); 690 dic.put(PdfName.STRF, PdfName.IDENTITY); 691 dic.put(PdfName.STMF, PdfName.IDENTITY); 692 } 693 else { 694 stdcf.put(PdfName.AUTHEVENT, PdfName.DOCOPEN); 695 dic.put(PdfName.STRF, PdfName.STDCF); 696 dic.put(PdfName.STMF, PdfName.STDCF); 697 } 698 if (revision == AES_128) 699 stdcf.put(PdfName.CFM, PdfName.AESV2); 700 else 701 stdcf.put(PdfName.CFM, PdfName.V2); 702 PdfDictionary cf = new PdfDictionary(); 703 cf.put(PdfName.STDCF, stdcf); 704 dic.put(PdfName.CF, cf); 705 } 706 } 707 708 return dic; 709 } 710 711 public PdfObject getFileID() { 712 return createInfoId(documentID); 713 } 714 715 public OutputStreamEncryption getEncryptionStream(OutputStream os) { 716 return new OutputStreamEncryption(os, key, 0, keySize, revision); 717 } 718 719 public int calculateStreamSize(int n) { 720 if (revision == AES_128 || revision == AES_256) 721 return (n & 0x7ffffff0) + 32; 722 else 723 return n; 724 } 725 726 public byte[] encryptByteArray(byte[] b) { 727 try { 728 ByteArrayOutputStream ba = new ByteArrayOutputStream(); 729 OutputStreamEncryption os2 = getEncryptionStream(ba); 730 os2.write(b); 731 os2.finish(); 732 return ba.toByteArray(); 733 } catch (IOException ex) { 734 throw new ExceptionConverter(ex); 735 } 736 } 737 738 public StandardDecryption getDecryptor() { 739 return new StandardDecryption(key, 0, keySize, revision); 740 } 741 742 public byte[] decryptByteArray(byte[] b) { 743 try { 744 ByteArrayOutputStream ba = new ByteArrayOutputStream(); 745 StandardDecryption dec = getDecryptor(); 746 byte[] b2 = dec.update(b, 0, b.length); 747 if (b2 != null) 748 ba.write(b2); 749 b2 = dec.finish(); 750 if (b2 != null) 751 ba.write(b2); 752 return ba.toByteArray(); 753 } catch (IOException ex) { 754 throw new ExceptionConverter(ex); 755 } 756 } 757 758 public void addRecipient(Certificate cert, int permission) { 759 documentID = createDocumentId(); 760 publicKeyHandler.addRecipient(new PdfPublicKeyRecipient(cert, 761 permission)); 762 } 763 764 public byte[] computeUserPassword(byte[] ownerPassword) { 765 byte[] userPad = computeOwnerKey(ownerKey, padPassword(ownerPassword)); 766 for (int i = 0; i < userPad.length; i++) { 767 boolean match = true; 768 for (int j = 0; j < userPad.length - i; j++) { 769 if (userPad[i + j] != pad[j]) { 770 match = false; 771 break; 772 } 773 } 774 if (!match) continue; 775 byte[] userPassword = new byte[i]; 776 System.arraycopy(userPad, 0, userPassword, 0, i); 777 return userPassword; 778 } 779 return userPad; 780 } 781}