pdfencryption.java

来自「源码包含生成 PDF 和 HTML 的类库」· Java 代码 · 共 602 行 · 第 1/2 页

JAVA
602
字号
				for (int j = 0; j < mkey.length; ++j)					digest[j] = (byte) (mkey[j] ^ i);				arcfour.prepareARCFOURKey(digest, 0, mkey.length);				arcfour.encryptARCFOUR(userKey, 0, 16);			}		} else {			arcfour.prepareARCFOURKey(mkey);			arcfour.encryptARCFOUR(pad, userKey);		}	}	// gets keylength and revision and uses revision to choose the initial values	// for permissions	public void setupAllKeys(byte userPassword[], byte ownerPassword[],			int permissions) {		if (ownerPassword == null || ownerPassword.length == 0)			ownerPassword = md5.digest(createDocumentId());		permissions |= (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) ? 0xfffff0c0				: 0xffffffc0;		permissions &= 0xfffffffc;		// PDF reference 3.5.2 Standard Security Handler, Algorithm 3.3-1		// If there is no owner password, use the user password instead.		byte userPad[] = padPassword(userPassword);		byte ownerPad[] = padPassword(ownerPassword);		this.ownerKey = computeOwnerKey(userPad, ownerPad);		documentID = createDocumentId();		setupByUserPad(this.documentID, userPad, this.ownerKey, permissions);	}	public static byte[] createDocumentId() {		MessageDigest md5;		try {			md5 = MessageDigest.getInstance("MD5");		} catch (Exception e) {			throw new ExceptionConverter(e);		}		long time = System.currentTimeMillis();		long mem = Runtime.getRuntime().freeMemory();		String s = time + "+" + mem + "+" + (seq++);		return md5.digest(s.getBytes());	}	/**	 */	public void setupByUserPassword(byte[] documentID, byte userPassword[],			byte ownerKey[], int permissions) {		setupByUserPad(documentID, padPassword(userPassword), ownerKey,				permissions);	}	/**	 */	private void setupByUserPad(byte[] documentID, byte userPad[],			byte ownerKey[], int permissions) {		setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions);		setupUserKey();	}	/**	 */	public void setupByOwnerPassword(byte[] documentID, byte ownerPassword[],			byte userKey[], byte ownerKey[], int permissions) {		setupByOwnerPad(documentID, padPassword(ownerPassword), userKey,				ownerKey, permissions);	}	private void setupByOwnerPad(byte[] documentID, byte ownerPad[],			byte userKey[], byte ownerKey[], int permissions) {		byte userPad[] = computeOwnerKey(ownerKey, ownerPad); // userPad will																// be set in																// this.ownerKey		setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions); // step																				// 3		setupUserKey();	}	public void setupByEncryptionKey(byte[] key, int keylength) {		mkey = new byte[keylength / 8];		System.arraycopy(key, 0, mkey, 0, mkey.length);	}	public void setHashKey(int number, int generation) {		md5.reset(); // added by ujihara		extra[0] = (byte) number;		extra[1] = (byte) (number >> 8);		extra[2] = (byte) (number >> 16);		extra[3] = (byte) generation;		extra[4] = (byte) (generation >> 8);		md5.update(mkey);		md5.update(extra);		if (revision == AES_128)			md5.update(salt);		key = md5.digest();		keySize = mkey.length + 5;		if (keySize > 16)			keySize = 16;	}	public static PdfObject createInfoId(byte id[]) {		ByteBuffer buf = new ByteBuffer(90);		buf.append('[').append('<');		for (int k = 0; k < 16; ++k)			buf.appendHex(id[k]);		buf.append('>').append('<');		id = createDocumentId();		for (int k = 0; k < 16; ++k)			buf.appendHex(id[k]);		buf.append('>').append(']');		return new PdfLiteral(buf.toByteArray());	}	public PdfDictionary getEncryptionDictionary() {		PdfDictionary dic = new PdfDictionary();		if (publicKeyHandler.getRecipientsSize() > 0) {			PdfArray recipients = null;			dic.put(PdfName.FILTER, PdfName.PUBSEC);			dic.put(PdfName.R, new PdfNumber(revision));			try {				recipients = publicKeyHandler.getEncodedRecipients();			} catch (Exception f) {				throw new ExceptionConverter(f);			}			if (revision == STANDARD_ENCRYPTION_40) {				dic.put(PdfName.V, new PdfNumber(1));				dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4);				dic.put(PdfName.RECIPIENTS, recipients);			} else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) {				dic.put(PdfName.V, new PdfNumber(2));				dic.put(PdfName.LENGTH, new PdfNumber(128));				dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4);				dic.put(PdfName.RECIPIENTS, recipients);			} else {				dic.put(PdfName.R, new PdfNumber(AES_128));				dic.put(PdfName.V, new PdfNumber(4));				dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S5);				PdfDictionary stdcf = new PdfDictionary();				stdcf.put(PdfName.RECIPIENTS, recipients);				if (!encryptMetadata)					stdcf.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE);				if (revision == AES_128)					stdcf.put(PdfName.CFM, PdfName.AESV2);				else					stdcf.put(PdfName.CFM, PdfName.V2);				PdfDictionary cf = new PdfDictionary();				cf.put(PdfName.DEFAULTCRYPTFILER, stdcf);				dic.put(PdfName.CF, cf);if (embeddedFilesOnly) {					dic.put(PdfName.EFF, PdfName.DEFAULTCRYPTFILER);					dic.put(PdfName.STRF, PdfName.IDENTITY);					dic.put(PdfName.STMF, PdfName.IDENTITY);				}				else {					dic.put(PdfName.STRF, PdfName.DEFAULTCRYPTFILER);					dic.put(PdfName.STMF, PdfName.DEFAULTCRYPTFILER);				}			}			MessageDigest md = null;			byte[] encodedRecipient = null;			try {				md = MessageDigest.getInstance("SHA-1");				md.update(publicKeyHandler.getSeed());				for (int i = 0; i < publicKeyHandler.getRecipientsSize(); i++) {					encodedRecipient = publicKeyHandler.getEncodedRecipient(i);					md.update(encodedRecipient);				}				if (!encryptMetadata)					md.update(new byte[] { (byte) 255, (byte) 255, (byte) 255,							(byte) 255 });			} catch (Exception f) {				throw new ExceptionConverter(f);			}			byte[] mdResult = md.digest();			setupByEncryptionKey(mdResult, keyLength);		} else {			dic.put(PdfName.FILTER, PdfName.STANDARD);			dic.put(PdfName.O, new PdfLiteral(PdfContentByte					.escapeString(ownerKey)));			dic.put(PdfName.U, new PdfLiteral(PdfContentByte					.escapeString(userKey)));			dic.put(PdfName.P, new PdfNumber(permissions));			dic.put(PdfName.R, new PdfNumber(revision));			if (revision == STANDARD_ENCRYPTION_40) {				dic.put(PdfName.V, new PdfNumber(1));			} else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) {				dic.put(PdfName.V, new PdfNumber(2));				dic.put(PdfName.LENGTH, new PdfNumber(128));			} else {				if (!encryptMetadata)					dic.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE);				dic.put(PdfName.R, new PdfNumber(AES_128));				dic.put(PdfName.V, new PdfNumber(4));				dic.put(PdfName.LENGTH, new PdfNumber(128));				PdfDictionary stdcf = new PdfDictionary();				stdcf.put(PdfName.LENGTH, new PdfNumber(16));				if (embeddedFilesOnly) {					stdcf.put(PdfName.AUTHEVENT, PdfName.EFOPEN);					dic.put(PdfName.EFF, PdfName.STDCF);					dic.put(PdfName.STRF, PdfName.IDENTITY);					dic.put(PdfName.STMF, PdfName.IDENTITY);				}				else {					stdcf.put(PdfName.AUTHEVENT, PdfName.DOCOPEN);					dic.put(PdfName.STRF, PdfName.STDCF);					dic.put(PdfName.STMF, PdfName.STDCF);				}				if (revision == AES_128)					stdcf.put(PdfName.CFM, PdfName.AESV2);				else					stdcf.put(PdfName.CFM, PdfName.V2);				PdfDictionary cf = new PdfDictionary();				cf.put(PdfName.STDCF, stdcf);				dic.put(PdfName.CF, cf);			}		}		return dic;	}	public PdfObject getFileID() {		return createInfoId(documentID);	}	public OutputStreamEncryption getEncryptionStream(OutputStream os) {		return new OutputStreamEncryption(os, key, 0, keySize, revision);	}	public int calculateStreamSize(int n) {		if (revision == AES_128)			return (n & 0x7ffffff0) + 32;		else			return n;	}	public byte[] encryptByteArray(byte[] b) {		try {			ByteArrayOutputStream ba = new ByteArrayOutputStream();			OutputStreamEncryption os2 = getEncryptionStream(ba);			os2.write(b);			os2.finish();			return ba.toByteArray();		} catch (IOException ex) {			throw new ExceptionConverter(ex);		}	}	public StandardDecryption getDecryptor() {		return new StandardDecryption(key, 0, keySize, revision);	}	public byte[] decryptByteArray(byte[] b) {		try {			ByteArrayOutputStream ba = new ByteArrayOutputStream();			StandardDecryption dec = getDecryptor();			byte[] b2 = dec.update(b, 0, b.length);			if (b2 != null)				ba.write(b2);			b2 = dec.finish();			if (b2 != null)				ba.write(b2);			return ba.toByteArray();		} catch (IOException ex) {			throw new ExceptionConverter(ex);		}	}	public void addRecipient(Certificate cert, int permission) {		documentID = createDocumentId();		publicKeyHandler.addRecipient(new PdfPublicKeyRecipient(cert,				permission));	}	public byte[] computeUserPassword(byte[] ownerPassword) {		byte[] userPad = computeOwnerKey(ownerKey, padPassword(ownerPassword));		for (int i = 0; i < userPad.length; i++) {			boolean match = true;			for (int j = 0; j < userPad.length - i; j++) {				if (userPad[i + j] != pad[j]) {					match = false;					break;                }			}			if (!match) continue;			byte[] userPassword = new byte[i];			System.arraycopy(userPad, 0, userPassword, 0, i);			return userPassword;		}		return userPad;	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?