com.itextpdf.kernel.crypto.securityhandler.SecurityHandler Maven / Gradle / Ivy
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package com.itextpdf.kernel.crypto.securityhandler;
import com.itextpdf.bouncycastleconnector.BouncyCastleFactoryCreator;
import com.itextpdf.commons.bouncycastle.IBouncyCastleFactory;
import com.itextpdf.kernel.crypto.IDecryptor;
import com.itextpdf.kernel.crypto.OutputStreamEncryption;
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
import com.itextpdf.kernel.exceptions.PdfException;
import com.itextpdf.kernel.logs.KernelLogMessageConstant;
import java.security.MessageDigest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class SecurityHandler {
private static final IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.getFactory();
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityHandler.class);
/**
* The global encryption key
*/
protected byte[] mkey = new byte[0];
/**
* The encryption key for a particular object/generation.
* It is recalculated with {@link #setHashKeyForNextObject(int, int)} for every object individually based in its
* object/generation.
*/
protected byte[] nextObjectKey;
/**
* The encryption key length for a particular object/generation
* It is recalculated with {@link #setHashKeyForNextObject(int, int)} for every object individually based in its
* object/generation.
*/
protected int nextObjectKeySize;
protected MessageDigest md5;
/**
* Work area to prepare the object/generation bytes
*/
protected byte[] extra = new byte[5];
protected SecurityHandler() {
safeInitMessageDigest();
}
/**
* Note: For most of the supported security handlers algorithm to calculate encryption key for particular object
* is the same.
*
* @param objNumber number of particular object for encryption
* @param objGeneration generation of particular object for encryption
*/
public void setHashKeyForNextObject(int objNumber, int objGeneration) {
// added by ujihara
md5.reset();
extra[0] = (byte) objNumber;
extra[1] = (byte) (objNumber >> 8);
extra[2] = (byte) (objNumber >> 16);
extra[3] = (byte) objGeneration;
extra[4] = (byte) (objGeneration >> 8);
md5.update(mkey);
md5.update(extra);
nextObjectKey = md5.digest();
nextObjectKeySize = mkey.length + 5;
if (nextObjectKeySize > 16) {
nextObjectKeySize = 16;
}
}
public abstract OutputStreamEncryption getEncryptionStream(java.io.OutputStream os);
public abstract IDecryptor getDecryptor();
private void safeInitMessageDigest() {
try {
md5 = MessageDigest.getInstance("MD5");
if (FACTORY.isInApprovedOnlyMode()) {
LOGGER.warn(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT);
}
} catch (Exception e) {
throw new PdfException(KernelExceptionMessageConstant.PDF_ENCRYPTION, e);
}
}
}