Red Hat Application Migration Toolkit
package ee.sk.xmlenc.factory;
import ee.sk.digidoc.Base64Util;
import ee.sk.digidoc.DigiDocException;
import ee.sk.digidoc.SignedDoc;
import ee.sk.digidoc.TokenKeyInfo;
import ee.sk.digidoc.factory.PKCS11SignatureFactory;
import ee.sk.digidoc.factory.Pkcs12SignatureFactory;
import ee.sk.digidoc.factory.SAXDigiDocException;
import ee.sk.digidoc.factory.SignatureFactory;
import ee.sk.utils.ConfigManager;
import ee.sk.xmlenc.EncryptedData;
import ee.sk.xmlenc.EncryptedKey;
import ee.sk.xmlenc.EncryptionProperty;
import ee.sk.xmlenc.factory.EncryptedStreamParser;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Provider;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Stack;
import java.util.zip.Inflater;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class EncryptedStreamSAXParser extends DefaultHandler implements EncryptedStreamParser {
private Stack m_tags = new Stack();
private EncryptedData m_doc = null;
private StringBuffer m_sbCollectChars = null;
private TokenKeyInfo m_tki;
private Logger m_logger = null;
private int m_totalDecrypted = 0;
private int m_totalDecompressed = 0;
private int m_totalInput = 0;
private OutputStream m_outStream = null;
private String m_recvName = null;
private String m_pin = null;
private int m_token = 0;
private byte[] m_transpkey = null;
private Cipher m_cipher = null;
private boolean m_bDecrypting = false;
private Inflater m_decompressor = null;
private StringBuffer m_sbParseBuf;
private StringBuffer m_sbB64Buf;
private static final int ENC_BLOCK_SIZE = 256;
private X509Certificate m_decCert = null;
private SecretKey m_transportKey = null;
private int m_nBlockType;
private static int DENC_BLOCK_FIRST = 1;
private static int DENC_BLOCK_MIDDLE = 2;
private static int DENC_BLOCK_LAST = 3;
private SignatureFactory m_sigFac = null;
private byte[] m_lblock = null;
private static final int DECBLOCK_SIZE = 8192;
public EncryptedStreamSAXParser() {
this.m_logger = Logger.getLogger(EncryptedStreamSAXParser.class);
}
public void init() throws DigiDocException {
try {
Provider ex = (Provider)Class.forName(ConfigManager.instance().getProperty("DIGIDOC_SECURITY_PROVIDER")).newInstance();
Security.addProvider(ex);
} catch (Exception var2) {
DigiDocException.handleException(var2, 67);
}
}
public void setRecipientName(String s) {
this.m_recvName = s;
}
public void setOutputStream(OutputStream outs) {
this.m_outStream = outs;
}
public void setPin(String pin) {
this.m_pin = pin;
}
public void setToken(int tok) {
this.m_token = tok;
}
public EncryptedData getCdoc() {
return this.m_doc;
}
public int decryptStreamUsingRecipientName(InputStream dencStream, OutputStream outs, int token, String pin, String recipientName) throws DigiDocException {
EncryptedStreamSAXParser handler = this;
this.setRecipientName(recipientName);
this.setOutputStream(outs);
this.setPin(pin);
this.setToken(token);
try {
this.m_sigFac = ConfigManager.instance().getSignatureFactory();
this.m_decCert = this.m_sigFac.getAuthCertificate(token, pin);
} catch (Exception var11) {
throw new DigiDocException(13, "Error loading decryption cert!", (Throwable)null);
}
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser ex = factory.newSAXParser();
ex.parse(dencStream, handler);
} catch (SAXDigiDocException var9) {
throw var9.getDigiDocException();
} catch (Exception var10) {
DigiDocException.handleException(var10, 75);
}
if(this.m_doc == null) {
throw new DigiDocException(13, "This document is not in EncryptedData format", (Throwable)null);
} else {
return this.m_totalDecrypted;
}
}
public int decryptStreamUsingRecipientSlotIdAndTokenLabel(InputStream dencStream, OutputStream outs, int slot, String label, String pin) throws DigiDocException {
EncryptedStreamSAXParser handler = this;
this.setOutputStream(outs);
this.setPin(pin);
ConfigManager cfg = ConfigManager.instance();
PKCS11SignatureFactory p11SigFac = null;
SignatureFactory sigFac = cfg.getSignatureFactory();
if(sigFac instanceof PKCS11SignatureFactory) {
p11SigFac = (PKCS11SignatureFactory)sigFac;
} else {
p11SigFac = (PKCS11SignatureFactory)cfg.getSignatureFactoryOfType("PKCS11");
}
if(p11SigFac == null) {
this.m_logger.error("No PKCS11 signature factory");
return 0;
} else {
this.m_sigFac = p11SigFac;
TokenKeyInfo tki = p11SigFac.getTokenWithSlotIdAndLabel((long)slot, label);
if(tki == null) {
this.m_logger.error("No token with slot: " + slot + " and label: " + label);
return 0;
} else if(tki != null && !tki.isEncryptKey()) {
this.m_logger.error("Token with slot: " + slot + " and label: " + label + " is not an encryption key!");
return 0;
} else {
this.m_decCert = tki.getCert();
this.m_tki = tki;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decrypt with slot: " + slot + " label: " + label + " token: " + (this.m_tki != null?"OK":"NULL") + " cert: " + (this.m_decCert != null?"OK":"NULL"));
}
if(this.m_decCert == null) {
throw new DigiDocException(13, "Error loading decryption cert!", (Throwable)null);
} else {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser ex = factory.newSAXParser();
ex.parse(dencStream, handler);
} catch (SAXDigiDocException var13) {
throw var13.getDigiDocException();
} catch (Exception var14) {
DigiDocException.handleException(var14, 75);
}
if(this.m_doc == null) {
throw new DigiDocException(13, "This document is not in EncryptedData format", (Throwable)null);
} else {
return this.m_totalDecrypted;
}
}
}
}
}
public int decryptStreamUsingTokenType(InputStream dencStream, OutputStream outs, int token, String pin, String tokenType, String pkcs12Keystore) throws DigiDocException {
EncryptedStreamSAXParser handler = this;
this.setOutputStream(outs);
this.setPin(pin);
this.setToken(token);
if(tokenType != null && (tokenType.equals("PKCS11") || tokenType.equals("PKCS12"))) {
try {
this.m_sigFac = ConfigManager.instance().getSignatureFactoryOfType(tokenType);
if(this.m_sigFac != null && this.m_sigFac instanceof Pkcs12SignatureFactory) {
Pkcs12SignatureFactory factory = (Pkcs12SignatureFactory)this.m_sigFac;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Loading pkcs12 keystore: " + pkcs12Keystore);
}
factory.load(pkcs12Keystore, tokenType, pin);
}
this.m_decCert = this.m_sigFac.getAuthCertificate(token, pin);
} catch (Exception var12) {
this.m_logger.error("Error loading decryption cert: " + var12);
throw new DigiDocException(111, "Error loading decryption cert!", var12);
}
if(this.m_decCert == null) {
throw new DigiDocException(111, "Error loading decryption cert!", (Throwable)null);
} else {
SAXParserFactory factory1 = SAXParserFactory.newInstance();
try {
factory1.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory1.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser ex = factory1.newSAXParser();
ex.parse(dencStream, handler);
} catch (SAXDigiDocException var10) {
throw var10.getDigiDocException();
} catch (Exception var11) {
DigiDocException.handleException(var11, 75);
}
if(this.m_doc == null) {
throw new DigiDocException(13, "This document is not in EncryptedData format", (Throwable)null);
} else {
return this.m_totalDecrypted;
}
}
} else {
throw new DigiDocException(111, "Invalid token type. Must be PKCS11 or PKCS12!", (Throwable)null);
}
}
public int decryptStreamUsingRecipientNameAndKey(InputStream dencStream, OutputStream outs, byte[] deckey, String recipientName) throws DigiDocException {
EncryptedStreamSAXParser handler = this;
this.setRecipientName(recipientName);
this.setOutputStream(outs);
this.m_transpkey = deckey;
this.m_transportKey = new SecretKeySpec(this.m_transpkey, "AES/CBC/NOPadding");
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Transport key: " + (this.m_transportKey == null?"ERROR":"OK") + " len: " + this.m_transpkey.length);
}
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser ex = factory.newSAXParser();
ex.parse(dencStream, handler);
} catch (SAXDigiDocException var8) {
throw var8.getDigiDocException();
} catch (Exception var9) {
DigiDocException.handleException(var9, 75);
}
if(this.m_doc == null) {
throw new DigiDocException(13, "This document is not in EncryptedData format", (Throwable)null);
} else {
return this.m_totalDecrypted;
}
}
public void startDocument() throws SAXException {
this.m_doc = null;
this.m_sbCollectChars = null;
this.m_decompressor = null;
this.m_totalDecrypted = 0;
this.m_totalDecompressed = 0;
this.m_totalInput = 0;
this.m_sbParseBuf = new StringBuffer();
this.m_sbB64Buf = new StringBuffer();
this.m_nBlockType = DENC_BLOCK_FIRST;
}
public void endDocument() throws SAXException {
}
private String findAtributeValue(Attributes attrs, String attName) {
String value = null;
for(int i = 0; i < attrs.getLength(); ++i) {
String key = attrs.getQName(i);
if(key.equals(attName) || key.indexOf(attName) != -1) {
value = attrs.getValue(i);
break;
}
}
return value;
}
private void checkEncryptedData() throws SAXDigiDocException {
if(this.m_doc == null) {
throw new SAXDigiDocException(27, "This document is not in EncryptedData format!");
}
}
private void checkEncryptedKey(EncryptedKey key) throws SAXDigiDocException {
if(key == null) {
throw new SAXDigiDocException(106, "This <EncryptedKey> object does not exist!");
}
}
public void startElement(String namespaceURI, String lName, String qName, Attributes attrs) throws SAXDigiDocException {
String tName = qName;
if(qName.indexOf(":") != -1) {
tName = qName.substring(qName.indexOf(":") + 1);
}
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Start Element: " + tName + " qname: " + qName + " lname: " + lName + " uri: " + namespaceURI);
}
this.m_tags.push(tName);
if(tName.equals("KeyName") || tName.equals("CarriedKeyName") || tName.equals("X509Certificate") || tName.equals("EncryptionProperty")) {
this.m_sbCollectChars = new StringBuffer();
}
if(tName.equals("CipherValue")) {
if(this.m_tags.search("EncryptedKey") != -1) {
this.m_sbCollectChars = new StringBuffer();
} else {
this.m_sbCollectChars = null;
this.m_bDecrypting = true;
}
}
String eprop;
if(tName.equals("EncryptedData")) {
eprop = this.findAtributeValue(attrs, "xmlns");
try {
this.m_doc = new EncryptedData(eprop);
eprop = this.findAtributeValue(attrs, "Id");
if(eprop != null) {
this.m_doc.setId(eprop);
}
eprop = this.findAtributeValue(attrs, "Type");
if(eprop != null) {
this.m_doc.setType(eprop);
}
eprop = this.findAtributeValue(attrs, "MimeType");
if(eprop != null) {
this.m_doc.setMimeType(eprop);
}
if(this.m_doc.getMimeType() != null && this.m_doc.getMimeType().equals("http://www.isi.edu/in-noes/iana/assignments/media-types/application/zip")) {
this.m_decompressor = new Inflater();
}
} catch (DigiDocException var12) {
SAXDigiDocException.handleException(var12);
}
try {
if(this.m_transportKey != null) {
byte[] str = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
this.m_cipher = this.m_doc.getCipher(2, this.m_transportKey, str);
}
} catch (DigiDocException var13) {
this.m_logger.error("Error using key: " + (this.m_transpkey != null?Base64Util.encode(this.m_transpkey):"NULL") + " - " + var13);
SAXDigiDocException.handleException(var13);
}
}
EncryptedKey eprop1;
if(tName.equals("EncryptionMethod")) {
this.checkEncryptedData();
if(this.m_tags.search("EncryptedKey") != -1) {
eprop1 = this.m_doc.getLastEncryptedKey();
this.checkEncryptedKey(eprop1);
try {
eprop1.setEncryptionMethod(this.findAtributeValue(attrs, "Algorithm"));
} catch (DigiDocException var11) {
SAXDigiDocException.handleException(var11);
}
} else {
try {
this.m_doc.setEncryptionMethod(this.findAtributeValue(attrs, "Algorithm"));
} catch (DigiDocException var10) {
SAXDigiDocException.handleException(var10);
}
}
}
String str1;
if(tName.equals("EncryptedKey")) {
this.checkEncryptedData();
eprop1 = new EncryptedKey();
this.m_doc.addEncryptedKey(eprop1);
str1 = this.findAtributeValue(attrs, "Recipient");
if(str1 != null) {
eprop1.setRecipient(str1);
}
str1 = this.findAtributeValue(attrs, "Id");
if(str1 != null) {
eprop1.setId(str1);
}
}
if(tName.equals("EncryptionProperties")) {
this.checkEncryptedData();
eprop = this.findAtributeValue(attrs, "Id");
if(eprop != null) {
this.m_doc.setEncryptionPropertiesId(eprop);
}
}
if(tName.equals("EncryptionProperty")) {
this.checkEncryptedData();
EncryptionProperty eprop2 = new EncryptionProperty();
this.m_doc.addProperty(eprop2);
str1 = this.findAtributeValue(attrs, "Id");
if(str1 != null) {
eprop2.setId(str1);
}
str1 = this.findAtributeValue(attrs, "Target");
if(str1 != null) {
eprop2.setTarget(str1);
}
str1 = this.findAtributeValue(attrs, "Name");
try {
if(str1 != null) {
eprop2.setName(str1);
}
} catch (DigiDocException var9) {
SAXDigiDocException.handleException(var9);
}
}
}
public void endElement(String namespaceURI, String sName, String qName) throws SAXException {
String tName = qName;
if(qName.indexOf(":") != -1) {
tName = qName.substring(qName.indexOf(":") + 1);
}
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("End Element: " + tName);
}
String currTag = (String)this.m_tags.pop();
EncryptedKey eprop;
if(tName.equals("KeyName")) {
this.checkEncryptedData();
eprop = this.m_doc.getLastEncryptedKey();
this.checkEncryptedKey(eprop);
eprop.setKeyName(this.m_sbCollectChars.toString());
this.m_sbCollectChars = null;
}
if(tName.equals("CarriedKeyName")) {
this.checkEncryptedData();
eprop = this.m_doc.getLastEncryptedKey();
this.checkEncryptedKey(eprop);
eprop.setCarriedKeyName(this.m_sbCollectChars.toString());
this.m_sbCollectChars = null;
}
X509Certificate ex;
if(tName.equals("X509Certificate")) {
this.checkEncryptedData();
eprop = this.m_doc.getLastEncryptedKey();
this.checkEncryptedKey(eprop);
try {
ex = SignedDoc.readCertificate(Base64Util.decode(this.m_sbCollectChars.toString().getBytes()));
eprop.setRecipientsCertificate(ex);
} catch (DigiDocException var11) {
SAXDigiDocException.handleException(var11);
}
this.m_sbCollectChars = null;
}
if(tName.equals("CipherValue")) {
this.checkEncryptedData();
if(this.m_tags.search("EncryptedKey") != -1) {
if(this.m_cipher == null) {
eprop = this.m_doc.getLastEncryptedKey();
this.checkEncryptedKey(eprop);
eprop.setTransportKeyData(Base64Util.decode(this.m_sbCollectChars.toString().getBytes()));
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Recipient: " + eprop.getRecipient() + " cert-nr: " + eprop.getRecipientsCertificate().getSerialNumber() + " decrypt-cert: " + this.m_decCert.getSerialNumber());
}
if(this.m_decCert != null && eprop.getRecipientsCertificate() != null && this.m_decCert.getSerialNumber().equals(eprop.getRecipientsCertificate().getSerialNumber())) {
ex = null;
if(this.m_sigFac == null) {
DigiDocException ex1 = new DigiDocException(108, "SignatureFactory not initialized!", (Throwable)null);
SAXDigiDocException.handleException(ex1);
}
try {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decrypting key: " + this.m_recvName + " serial: " + this.m_decCert.getSerialNumber());
}
byte[] ex2;
if(this.m_transpkey != null) {
ex2 = this.m_transpkey;
} else if(this.m_tki != null) {
ex2 = ((PKCS11SignatureFactory)this.m_sigFac).decrypt(eprop.getTransportKeyData(), this.m_tki.getSlot(), this.m_tki.getLabel(), this.m_pin);
} else {
ex2 = this.m_sigFac.decrypt(eprop.getTransportKeyData(), this.m_token, this.m_pin);
}
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Using key: " + this.m_recvName + " decdata: " + Base64Util.encode(ex2));
}
this.m_transportKey = new SecretKeySpec(ex2, "AES/CBC/NOPadding");
byte[] ex3 = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
this.m_cipher = this.m_doc.getCipher(2, this.m_transportKey, ex3);
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Transport key: " + (this.m_transportKey == null?"ERROR":"OK") + " len: " + ex2.length);
}
} catch (DigiDocException var12) {
this.m_logger.error("Error decrypting key1: " + (ex != null?Base64Util.encode((byte[])ex):"NULL") + " - " + var12);
SAXDigiDocException.handleException(var12);
} catch (Exception var13) {
this.m_logger.error("Error decrypting key2: " + (ex != null?Base64Util.encode((byte[])ex):"NULL") + " - " + var13);
DigiDocException ex2 = new DigiDocException(108, var13.getMessage(), var13);
SAXDigiDocException.handleException(ex2);
}
}
}
} else {
this.m_bDecrypting = false;
this.decryptBlock((String)null, DENC_BLOCK_LAST);
if(this.m_logger.isInfoEnabled()) {
this.m_logger.info("Total input: " + this.m_totalInput + " decrypted: " + this.m_totalDecrypted + " decompressed: " + this.m_totalDecompressed);
}
}
this.m_sbCollectChars = null;
}
if(tName.equals("EncryptionProperty")) {
this.checkEncryptedData();
EncryptionProperty eprop1 = this.m_doc.getLastProperty();
try {
if(eprop1 != null && this.m_sbCollectChars != null) {
eprop1.setContent(this.m_sbCollectChars.toString());
}
} catch (DigiDocException var10) {
SAXDigiDocException.handleException(var10);
}
this.m_sbCollectChars = null;
}
}
private void decryptBlock(String data, int nBlockType) throws SAXException {
if(data != null && data.length() > 0) {
this.m_sbParseBuf.append(data);
}
String indata = null;
if(nBlockType == DENC_BLOCK_LAST) {
indata = this.m_sbParseBuf.toString();
} else if(this.m_sbParseBuf.length() > 256) {
indata = this.m_sbParseBuf.substring(0, 256);
this.m_sbParseBuf.delete(0, 256);
}
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("IN " + (data != null?data.length():0) + " input: " + (indata != null?indata.length():0) + " buffered: " + (this.m_sbParseBuf != null?this.m_sbParseBuf.length():0) + " b64left: " + (this.m_sbB64Buf != null?this.m_sbB64Buf.length():0) + " block-type: " + nBlockType);
}
if(this.m_cipher == null) {
DigiDocException ex = new DigiDocException(111, "Cipher has not been initialized! No transport key for selected recipient?", (Throwable)null);
SAXDigiDocException.handleException(ex);
}
if(indata != null) {
this.m_sbB64Buf.append(indata);
this.m_totalInput += indata.length();
DigiDocException de;
try {
byte[] ex1 = null;
de = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
boolean nUsed = false;
byte[] nDecomp;
if(this.m_sbB64Buf.length() > 0) {
int nUsed1 = Base64Util.decodeBlock(this.m_sbB64Buf.toString(), bos, nBlockType == DENC_BLOCK_LAST);
ex1 = bos.toByteArray();
if(nBlockType == DENC_BLOCK_FIRST && ex1 != null && ex1.length > 16) {
nDecomp = new byte[ex1.length - 16];
System.arraycopy(ex1, 16, nDecomp, 0, nDecomp.length);
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Removed IV from: " + ex1.length + " block1, left: " + nDecomp.length);
}
ex1 = nDecomp;
}
bos = null;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decoding: " + this.m_sbB64Buf.length() + " got: " + (ex1 != null?ex1.length:0) + " last: " + (nBlockType == DENC_BLOCK_LAST));
}
if(nUsed1 > 0) {
this.m_sbB64Buf.delete(0, nUsed1);
}
}
byte[] de1 = this.m_cipher.update(ex1);
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decrypted input: " + (indata != null?indata.length():0) + " decoded: " + (ex1 != null?ex1.length:0) + " decrypted: " + (de1 != null?de1.length:0));
}
if(this.m_totalDecrypted == 0 && de1 != null && de1.length > 16) {
nDecomp = new byte[de1.length - 16];
System.arraycopy(de1, 16, nDecomp, 0, de1.length - 16);
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Removing IV data from: " + de1.length + " remaining: " + nDecomp.length);
}
de1 = nDecomp;
}
int nDecomp1;
if(nBlockType == DENC_BLOCK_LAST) {
nDecomp1 = this.m_lblock != null?this.m_lblock.length:0;
int m_decbuf = de1 != null?de1.length:0;
byte[] ddata = new byte[nDecomp1 + m_decbuf];
if(nDecomp1 > 0) {
System.arraycopy(this.m_lblock, 0, ddata, 0, nDecomp1);
}
if(m_decbuf > 0) {
System.arraycopy(de1, 0, ddata, nDecomp1, m_decbuf);
}
de1 = ddata;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Last block: " + (ddata != null?ddata.length:0));
}
this.m_lblock = null;
}
if(de1 != null && ex1 != null && nBlockType == DENC_BLOCK_LAST) {
nDecomp1 = (new Integer(de1[de1.length - 1])).intValue();
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Check padding 1: " + nDecomp1);
}
boolean m_decbuf1 = this.checkPadding(de1, nDecomp1);
if(m_decbuf1) {
de1 = this.removePadding(de1, nDecomp1);
}
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decdata remaining: " + (de1 != null?de1.length:0));
}
if(de1 != null && de1.length > 0) {
nDecomp1 = (new Integer(de1[de1.length - 1])).intValue();
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Check padding 2: " + nDecomp1);
}
if(nDecomp1 > 0 && nDecomp1 <= 16 && de1.length > nDecomp1) {
m_decbuf1 = this.checkPadding(de1, nDecomp1);
if(m_decbuf1) {
de1 = this.removePadding(de1, nDecomp1);
}
}
} else if(this.m_lblock != null) {
nDecomp1 = (new Integer(this.m_lblock[this.m_lblock.length - 1])).intValue();
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Check padding 3: " + nDecomp1);
}
if(nDecomp1 > 0 && nDecomp1 <= 16 && this.m_lblock.length > nDecomp1) {
m_decbuf1 = this.checkPadding(this.m_lblock, nDecomp1);
if(m_decbuf1) {
this.m_lblock = this.removePadding(this.m_lblock, nDecomp1);
}
}
}
}
if(this.m_lblock != null || de1 != null) {
if(this.m_decompressor != null) {
if(nBlockType == DENC_BLOCK_LAST) {
this.m_lblock = de1;
}
boolean nDecomp2 = false;
Object m_decbuf2 = null;
byte[] m_decbuf3;
if(this.m_lblock != null) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decompressing: " + this.m_lblock.length);
}
this.m_decompressor.setInput(this.m_lblock);
m_decbuf3 = new byte[8192];
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decompressing: " + this.m_lblock.length + " into: " + m_decbuf3.length);
}
while((nDecomp1 = this.m_decompressor.inflate(m_decbuf3)) > 0) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decompressed: " + this.m_lblock.length + " into: " + m_decbuf3.length + " got: " + nDecomp1);
}
this.m_outStream.write(m_decbuf3, 0, nDecomp1);
this.m_totalDecompressed += nDecomp1;
}
}
if(nBlockType == DENC_BLOCK_LAST && (!this.m_decompressor.finished() || this.m_decompressor.getRemaining() > 0)) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decompressor finished: " + this.m_decompressor.finished() + " remaining: " + this.m_decompressor.getRemaining());
}
m_decbuf3 = new byte[8192];
while((nDecomp1 = this.m_decompressor.inflate(m_decbuf3)) > 0) {
this.m_outStream.write(m_decbuf3, 0, nDecomp1);
this.m_totalDecompressed += nDecomp1;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Decompressing final: " + nDecomp1);
}
}
}
} else {
if(this.m_lblock != null) {
this.m_outStream.write(this.m_lblock);
}
if(nBlockType == DENC_BLOCK_LAST && de1 != null) {
this.m_outStream.write(de1);
}
}
this.m_totalDecrypted += de1.length;
}
this.m_lblock = de1;
} catch (Exception var11) {
de = new DigiDocException(111, "Error decrypting: " + var11, var11);
SAXDigiDocException.handleException(de);
}
}
}
private boolean checkPadding(byte[] data, int nPadLen) {
boolean bPadOk = true;
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Checking padding: " + nPadLen + " bytes");
}
if(nPadLen >= 0 && nPadLen <= 16 && data != null && data.length >= nPadLen) {
for(int i = data.length - nPadLen; nPadLen > 0 && i < data.length - 1; ++i) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Data at: " + i + " = " + data[i]);
}
if(data[i] != 0 && nPadLen != 16 || nPadLen == 16 && data[i] != 16 && data[i] != 0) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Data at: " + i + " = " + data[i] + " cancel padding");
}
bPadOk = false;
break;
}
}
return bPadOk;
} else {
return false;
}
}
private byte[] removePadding(byte[] data, int nPadLen) {
if(this.m_logger.isDebugEnabled()) {
this.m_logger.debug("Removing padding: " + nPadLen + " bytes");
}
if(nPadLen >= 0 && nPadLen <= 16 && data != null && data.length >= nPadLen) {
byte[] data2 = new byte[data.length - nPadLen];
System.arraycopy(data, 0, data2, 0, data.length - nPadLen);
return data2;
} else {
return data;
}
}
public void characters(char[] buf, int offset, int len) throws SAXException {
String s = new String(buf, offset, len);
if(s != null) {
if(this.m_sbCollectChars != null) {
this.m_sbCollectChars.append(s);
}
if(this.m_bDecrypting) {
this.decryptBlock(s, this.m_nBlockType);
if(this.m_nBlockType == DENC_BLOCK_FIRST) {
this.m_nBlockType = DENC_BLOCK_MIDDLE;
}
}
}
}
}