Information

0
Story Points

Technologies

Decompiled Java File
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;
            }
         }
      }

   }
}
Page generated: Oct 19, 2017 2:34:14 PM