Red Hat Application Migration Toolkit
package ee.sk.xmlenc; import ee.sk.digidoc.Base64Util; import ee.sk.digidoc.DataFile; import ee.sk.digidoc.DigiDocException; import ee.sk.digidoc.SignedDoc; import ee.sk.digidoc.factory.Pkcs12SignatureFactory; import ee.sk.digidoc.factory.SignatureFactory; import ee.sk.utils.ConfigManager; import ee.sk.utils.ConvertUtils; import ee.sk.xmlenc.EncryptedKey; import ee.sk.xmlenc.EncryptionProperties; import ee.sk.xmlenc.EncryptionProperty; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.log4j.Logger; public class EncryptedData implements Serializable { private static final long serialVersionUID = 1L; private String m_id; private String m_type; private String m_mimeType; private String m_xmlns; private String m_encryptionMethod; private byte[] m_data; private int m_nDataStatus; private ArrayList m_arrEncryptedKeys; private EncryptionProperties m_encProperties; private static Logger m_logger = Logger.getLogger(EncryptedData.class); private transient SecretKey m_transportKey; public static final String DENC_ENCDATA_TYPE_DDOC = "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd"; public static final String DENC_ENCDATA_MIME_XML = "text/xml"; public static final String DENC_ENCDATA_MIME_ZLIB = "http://www.isi.edu/in-noes/iana/assignments/media-types/application/zip"; public static final String DENC_ENC_METHOD_AES128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc"; public static final String DENC_ENC_METHOD_RSA1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"; public static final String DENC_ENC_METHOD_RSA1_5_BUGGY = "http://www.w3.org/2001/04/xmlenc#rsa-1-5"; public static final String DENC_XMLNS_XMLENC = "http://www.w3.org/2001/04/xmlenc#"; public static final String DENC_XMLNS_XMLENC_ELEMENT = "http://www.w3.org/2001/04/xmlenc#Element"; public static final String DENC_XMLNS_XMLENC_CONTENT = "http://www.w3.org/2001/04/xmlenc#Content"; public static final String DENC_XMLNS_XMLENC_ENCPROP = "http://www.w3.org/2001/04/xmlenc#EncryptionProperties"; public static final String DENC_XMLNS_XMLDSIG = "http://www.w3.org/2000/09/xmldsig#"; public static final int DENC_DATA_STATUS_UNINITIALIZED = 0; public static final int DENC_DATA_STATUS_UNENCRYPTED_AND_NOT_COMPRESSED = 1; public static final int DENC_DATA_STATUS_UNENCRYPTED_AND_COMPRESSED = 2; public static final int DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED = 3; public static final int DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED = 4; /** @deprecated */ public static final int DENC_COMPRESS_ALLWAYS = 0; public static final int DENC_COMPRESS_NEVER = 1; /** @deprecated */ public static final int DENC_COMPRESS_BEST_EFFORT = 2; public static final String ENCPROP_FILENAME = "Filename"; public static final String ENCPROP_ORIG_SIZE = "OriginalSize"; public static final String ENCPROP_ORIG_MIME = "OriginalMimeType"; public static final String ENCPROP_ORIG_FILE = "orig_file"; public static final String ENCPROP_LIB_VER = "LibraryVersion"; public static final String ENCPROP_FORMAT_VER = "DocumentFormat"; public static final String FORMAT_ENCDOC_XML = "ENCDOC-XML"; public static final String VERSION_1_0 = "1.0"; public static final String DIGDOC_ENCRYPT_KEY_ALG = "AES"; public static final String DIGIDOC_ENCRYPTION_ALOGORITHM2 = "AES/CBC/PKCS7Padding"; public static final String DIGIDOC_ENCRYPTION_ALOGORITHM = "AES/CBC/NOPadding"; public static final String DIGIDOC_SECRANDOM_ALGORITHM = "SHA1PRNG"; public static final String DIGIDOC_KEY_ALOGORITHM = "RSA/NONE/PKCS1Padding"; public static final boolean DIGDOC_ENCRYPT_USE_IV = true; public static final String DIGIDOC_SECURITY_PROVIDER_NAME = "BC"; public static final String DIGIDOC_SECURITY_PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider"; public EncryptedData(String id, String type, String mimeType, String xmlns, String encryptionMethod) throws DigiDocException { this.setId(id); this.setType(type); this.setMimeType(mimeType); this.setXmlns(xmlns); this.setEncryptionMethod(encryptionMethod); this.m_data = null; this.m_transportKey = null; this.m_nDataStatus = 0; this.m_arrEncryptedKeys = null; this.m_encProperties = null; this.setPropLibraryNameAndVersion(); this.setPropFormatNameAndVersion(); } public EncryptedData(String xmlns) throws DigiDocException { this.m_id = null; this.m_type = null; this.m_mimeType = null; this.setXmlns(xmlns); this.m_encryptionMethod = null; this.m_data = null; this.m_transportKey = null; this.m_nDataStatus = 0; this.m_arrEncryptedKeys = null; this.m_encProperties = null; } public int getDataStatus() { return this.m_nDataStatus; } public void setDataStatus(int status) { this.m_nDataStatus = status; } public byte[] getData() { return this.m_data; } public void setData(byte[] data) { this.m_data = data; } public SecretKey getTransportKey() { return this.m_transportKey; } public void setTransportKey(SecretKey key) { this.m_transportKey = key; } public String getId() { return this.m_id; } public void setId(String str) { this.m_id = str; } public String getType() { return this.m_type; } public void setType(String str) { this.m_type = str; } public String getMimeType() { return this.m_mimeType; } public void setMimeType(String str) { this.m_mimeType = str; } public String getEncryptionMethod() { return this.m_encryptionMethod; } public void setEncryptionMethod(String str) throws DigiDocException { DigiDocException ex = this.validateEncryptionMethod(str); if(ex != null) { throw ex; } else { this.m_encryptionMethod = str; } } private DigiDocException validateEncryptionMethod(String str) { DigiDocException ex = null; if(str == null || !str.equals("http://www.w3.org/2001/04/xmlenc#aes128-cbc")) { ex = new DigiDocException(103, "EncryptionMethod atribute is required and currently the only supported value is: http://www.w3.org/2001/04/xmlenc#aes128-cbc", (Throwable)null); } return ex; } public String getXmlns() { return this.m_xmlns; } public void setXmlns(String str) throws DigiDocException { DigiDocException ex = this.validateXmlns(str); if(ex != null) { throw ex; } else { this.m_xmlns = str; } } private DigiDocException validateXmlns(String str) { DigiDocException ex = null; if(str == null || !str.equals("http://www.w3.org/2001/04/xmlenc#")) { ex = new DigiDocException(104, "xmlns atribute is required and currently the only supported value is: http://www.w3.org/2001/04/xmlenc#", (Throwable)null); } return ex; } public String getEncryptionPropertiesId() { return this.m_encProperties != null?this.m_encProperties.getId():null; } public void setEncryptionPropertiesId(String id) { if(this.m_encProperties == null) { this.m_encProperties = new EncryptionProperties(id); } else { this.m_encProperties.setId(id); } } public boolean encryptFileData(String sInFile, String sOutFile) { try { boolean ex = true; byte[] inData = SignedDoc.readFile(new File(sInFile)); this.setData(inData); this.setDataStatus(1); this.addProperty("Filename", sInFile); if(sInFile.endsWith(".bdoc") || sInFile.endsWith(".asice")) { this.setMimeType("application/vnd.etsi.asic-e+zip"); } this.addProperty("OriginalSize", (new Long((long)inData.length)).toString()); this.encrypt(1); FileOutputStream fos = new FileOutputStream(sOutFile); fos.write(this.toXML()); fos.close(); return true; } catch (Exception var6) { m_logger.error("Error encrypting from: " + sInFile + " to: " + sOutFile + " - " + var6); var6.printStackTrace(System.err); return false; } } public void addProperty(EncryptionProperty prop) { if(this.m_encProperties == null) { this.m_encProperties = new EncryptionProperties((String)null); } this.m_encProperties.addProperty(prop); } public void addProperty(String name, String content) throws DigiDocException { if(this.m_encProperties == null) { this.m_encProperties = new EncryptionProperties((String)null); } this.m_encProperties.addProperty(new EncryptionProperty(name, content)); } public int getNumProperties() { return this.m_encProperties == null?0:this.m_encProperties.getNumProperties(); } public EncryptionProperty getProperty(int nIdx) { return nIdx < this.getNumProperties()?this.m_encProperties.getProperty(nIdx):null; } public EncryptionProperty findPropertyById(String id) { return this.m_encProperties != null?this.m_encProperties.findPropertyById(id):null; } public EncryptionProperty findPropertyByName(String name) { return this.m_encProperties != null?this.m_encProperties.findPropertyByName(name):null; } public EncryptionProperty getLastProperty() { return this.m_encProperties != null && this.m_encProperties.getNumProperties() > 0?this.m_encProperties.getProperty(this.m_encProperties.getNumProperties() - 1):null; } public String findPropertyContentByName(String name) { EncryptionProperty prop = this.findPropertyByName(name); return prop != null?prop.getContent():null; } public void setPropLibraryNameAndVersion() throws DigiDocException { EncryptionProperty prop = this.findPropertyByName("LibraryVersion"); StringBuffer sb = new StringBuffer(); sb.append("JDigiDoc"); sb.append("|"); sb.append("3.9.0-726"); if(prop == null) { prop = new EncryptionProperty("LibraryVersion", sb.toString()); this.addProperty(prop); } else { prop.setContent(sb.toString()); } } public String getPropLibraryName() { StringBuffer sb = new StringBuffer(); EncryptionProperty prop = this.findPropertyByName("LibraryVersion"); if(prop != null) { String content = prop.getContent(); boolean nIdx1 = false; int nIdx11; if(content != null && (nIdx11 = content.indexOf("|")) != -1) { sb.append(content.substring(0, nIdx11)); } } return sb.toString(); } public String getPropLibraryVersion() { StringBuffer sb = new StringBuffer(); EncryptionProperty prop = this.findPropertyByName("LibraryVersion"); if(prop != null) { String content = prop.getContent(); boolean nIdx1 = false; int nIdx11; if(content != null && (nIdx11 = content.indexOf("|")) != -1) { sb.append(content.substring(nIdx11 + 1)); } } return sb.toString(); } public void setPropFormatNameAndVersion() throws DigiDocException { EncryptionProperty prop = this.findPropertyByName("DocumentFormat"); StringBuffer sb = new StringBuffer(); sb.append("ENCDOC-XML"); sb.append("|"); sb.append("1.0"); if(prop == null) { prop = new EncryptionProperty("DocumentFormat", sb.toString()); this.addProperty(prop); } else { prop.setContent(sb.toString()); } } public String getPropFormatName() { StringBuffer sb = new StringBuffer(); EncryptionProperty prop = this.findPropertyByName("DocumentFormat"); if(prop != null) { String content = prop.getContent(); boolean nIdx1 = false; int nIdx11; if(content != null && (nIdx11 = content.indexOf("|")) != -1) { sb.append(content.substring(0, nIdx11)); } } return sb.toString(); } public String getPropFormatVersion() { StringBuffer sb = new StringBuffer(); EncryptionProperty prop = this.findPropertyByName("DocumentFormat"); if(prop != null) { String content = prop.getContent(); boolean nIdx1 = false; int nIdx11; if(content != null && (nIdx11 = content.indexOf("|")) != -1) { sb.append(content.substring(nIdx11 + 1)); } } return sb.toString(); } public void setPropRegisterDigiDoc(SignedDoc sdoc) throws DigiDocException { for(int i = 0; i < sdoc.countDataFiles(); ++i) { DataFile df = sdoc.getDataFile(i); StringBuffer sb = new StringBuffer(); sb.append(df.getFileName()); sb.append("|"); sb.append((new Long(df.getSize())).toString()); sb.append("|"); sb.append(df.getMimeType()); sb.append("|"); sb.append(df.getId()); this.addProperty(new EncryptionProperty("orig_file", sb.toString())); } } public int getPropOrigFileCount() { int n = 0; for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals("orig_file")) { ++n; } } return n; } public String getPropOrigFileName(int nProp) { String str = null; int n = 0; boolean nIdx1 = false; for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals("orig_file")) { ++n; if(n == nProp) { String content = prop.getContent(); int var8; if(content != null && (var8 = content.indexOf("|")) != -1) { str = content.substring(0, var8); } break; } } } return str; } public String getPropByName(String sName) { for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals(sName)) { return prop.getContent(); } } return null; } public String getPropOrigFileSize(int nProp) { String str = null; int n = 0; boolean nIdx1 = false; boolean nIdx2 = false; for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals("orig_file")) { ++n; if(n == nProp) { String content = prop.getContent(); int var9; int var10; if(content != null && (var9 = content.indexOf("|")) != -1 && (var10 = content.indexOf("|", var9 + 1)) != -1) { str = content.substring(var9 + 1, var10); } break; } } } return str; } public String getPropOrigFileMime(int nProp) { String str = null; int n = 0; boolean nIdx1 = false; boolean nIdx2 = false; boolean nIdx3 = false; for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals("orig_file")) { ++n; if(n == nProp) { String content = prop.getContent(); int var10; int var11; int var12; if(content != null && (var12 = content.indexOf("|")) != -1 && (var10 = content.indexOf("|", var12 + 1)) != -1 && (var11 = content.indexOf("|", var10 + 1)) != -1) { str = content.substring(var10 + 1, var11); } break; } } } return str; } public String getPropOrigFileId(int nProp) { String str = null; int n = 0; boolean nIdx1 = false; for(int i = 0; this.m_encProperties != null && i < this.m_encProperties.getNumProperties(); ++i) { EncryptionProperty prop = this.m_encProperties.getProperty(i); if(prop.getName() != null && prop.getName().equals("orig_file")) { ++n; if(n == nProp) { String content = prop.getContent(); int var8; if(content != null && (var8 = content.lastIndexOf("|")) != -1) { str = content.substring(var8 + 1); } break; } } } return str; } public void addEncryptedKey(EncryptedKey key) { if(this.m_arrEncryptedKeys == null) { this.m_arrEncryptedKeys = new ArrayList(); } this.m_arrEncryptedKeys.add(key); } public int getNumKeys() { return this.m_arrEncryptedKeys == null?0:this.m_arrEncryptedKeys.size(); } public EncryptedKey getEncryptedKey(int nIdx) { return nIdx < this.getNumKeys()?(EncryptedKey)this.m_arrEncryptedKeys.get(nIdx):null; } public EncryptedKey getLastEncryptedKey() { return this.m_arrEncryptedKeys != null && this.m_arrEncryptedKeys.size() > 0?(EncryptedKey)this.m_arrEncryptedKeys.get(this.m_arrEncryptedKeys.size() - 1):null; } public EncryptedKey findKeyById(String id) { for(int i = 0; this.m_arrEncryptedKeys != null && i < this.m_arrEncryptedKeys.size(); ++i) { EncryptedKey key = (EncryptedKey)this.m_arrEncryptedKeys.get(i); if(key.getId() != null && key.getId().equals(id)) { return key; } } return null; } public EncryptedKey findKeyByRecipient(String recv) { for(int i = 0; this.m_arrEncryptedKeys != null && i < this.m_arrEncryptedKeys.size(); ++i) { EncryptedKey key = (EncryptedKey)this.m_arrEncryptedKeys.get(i); if(key.getRecipient() != null && key.getRecipient().equals(recv)) { return key; } } return null; } private void initKey() throws DigiDocException { try { Security.addProvider((Provider)Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance()); } catch (Exception var4) { DigiDocException.handleException(var4, 116); } if(this.m_transportKey != null) { throw new DigiDocException(110, "Transport key allready initialized!", (Throwable)null); } else { try { SecureRandom ex = SecureRandom.getInstance("SHA1PRNG"); KeyGenerator keygen = KeyGenerator.getInstance("AES", "BC"); if(m_logger.isDebugEnabled()) { m_logger.debug("Keygen:" + keygen.getClass().getName() + " algorithm: " + keygen.getAlgorithm()); } keygen.init(128, ex); this.m_transportKey = keygen.generateKey(); if(m_logger.isDebugEnabled()) { m_logger.debug("key0: " + this.m_transportKey.getEncoded().length); } } catch (Exception var3) { DigiDocException.handleException(var3, 107); } if(this.m_transportKey == null) { throw new DigiDocException(107, "Failure to initialize the transport key!", (Throwable)null); } } } public Cipher getCipher(int mode, SecretKey transportKey, byte[] iv) throws DigiDocException { Cipher cip = null; Object ivdata = null; if(this.m_transportKey == null && transportKey == null) { throw new DigiDocException(110, "Transport key has not been initialized!", (Throwable)null); } else { try { byte[] ivdata1; if(mode == 2) { cip = Cipher.getInstance("AES/CBC/NOPadding", "BC"); IvParameterSpec ex = new IvParameterSpec(iv); cip.init(mode, transportKey == null?this.m_transportKey:transportKey, ex); } else { cip = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); cip.init(mode, transportKey == null?this.m_transportKey:transportKey); ivdata1 = cip.getIV(); System.arraycopy(ivdata1, 0, iv, 0, 16); } if(m_logger.isDebugEnabled()) { m_logger.debug("Cipher: " + cip.getAlgorithm() + " provider: " + cip.getProvider().getName()); ivdata1 = cip.getIV(); } } catch (Exception var7) { DigiDocException.handleException(var7, 112); } return cip; } } public void encrypt(int nCompressOption) throws DigiDocException { byte[] ivdata = new byte[16]; if(this.m_transportKey == null) { this.initKey(); } if(this.m_data == null || this.m_nDataStatus != 2 && this.m_nDataStatus != 1) { throw new DigiDocException(115, "Invalid data status for encryption operation!", (Throwable)null); } else { int nTotalInput = this.m_data.length; boolean nTotalCompressed = false; boolean nTotalEncrypted = false; this.compress(nCompressOption); int var16 = this.m_data.length; Cipher cipher = this.getCipher(1, (SecretKey)null, ivdata); try { if(m_logger.isDebugEnabled()) { m_logger.debug("Encrypt - algorithm: " + cipher.getAlgorithm() + " blocksize: " + cipher.getBlockSize()); } int ex = cipher.getBlockSize(); Object cdata = null; int nOrigLen = this.m_data.length; int nLastBlockSize = this.m_data.length % ex; int nInput = nOrigLen - nLastBlockSize + ex; ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write(this.m_data, 0, this.m_data.length - nLastBlockSize); if(m_logger.isDebugEnabled()) { m_logger.debug("Encrypt - body: " + this.m_data.length + " full-data: " + (this.m_data.length - nLastBlockSize) + " left: " + nLastBlockSize); } byte[] var18 = new byte[ex]; int i; if(nLastBlockSize > 0) { System.arraycopy(this.m_data, this.m_data.length - nLastBlockSize, var18, 0, nLastBlockSize); for(i = nLastBlockSize; i < ex; ++i) { var18[i] = 0; } var18[ex - 1] = (new Integer(ex - nLastBlockSize)).byteValue(); } else { for(i = nLastBlockSize; i < ex; ++i) { var18[i] = 0; } var18[ex - 1] = 16; } bos.write(var18); if(m_logger.isDebugEnabled()) { for(i = 0; i < ex; ++i) { m_logger.debug("Byte at: " + i + " = " + var18[i]); } } var18 = cipher.doFinal(bos.toByteArray()); int var17 = var18.length; if(m_logger.isDebugEnabled()) { m_logger.debug("Encrypt - orig: " + nOrigLen + " input: " + nInput + " encrypted: " + var18.length); } this.m_data = new byte[var18.length + 16]; System.arraycopy(ivdata, 0, this.m_data, 0, 16); System.arraycopy(var18, 0, this.m_data, 16, var18.length); this.m_nDataStatus = 3; for(i = 0; i < this.getNumKeys(); ++i) { EncryptedKey ekey = this.getEncryptedKey(i); ekey.encryptKey(this); } if(m_logger.isInfoEnabled()) { m_logger.info("Encrypt total - input: " + nTotalInput + " compressed: " + var16 + " encrypted: " + var17); } } catch (Exception var15) { DigiDocException.handleException(var15, 112); } } } public int getRecvIndex(X509Certificate cert) { if(cert == null) { return -1; } else { for(int i = 0; this.m_arrEncryptedKeys != null && i < this.m_arrEncryptedKeys.size(); ++i) { EncryptedKey key = (EncryptedKey)this.m_arrEncryptedKeys.get(i); if(key.getRecipientsCertificate() != null && key.getRecipientsCertificate().getSerialNumber().equals(cert.getSerialNumber())) { return i; } } return -1; } } public void decrypt(int nKey, int token, String pin) throws DigiDocException { EncryptedKey ekey = this.getEncryptedKey(nKey); try { SignatureFactory ex = ConfigManager.instance().getSignatureFactory(); if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypting key: " + nKey + " with token: " + token); } byte[] decdata = ex.decrypt(ekey.getTransportKeyData(), token, pin); this.decryptWithKey(decdata); } catch (Exception var7) { DigiDocException.handleException(var7, 111); } } public void decryptPkcs12(int nKey, String keystore, String storepass, String storetype) throws DigiDocException { EncryptedKey ekey = this.getEncryptedKey(nKey); try { Pkcs12SignatureFactory ex = new Pkcs12SignatureFactory(); ex.init(); ex.load(keystore, storetype, storepass); if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypting key: " + nKey + " with token: " + nKey); } byte[] decdata = ex.decrypt(ekey.getTransportKeyData(), 0, storepass); this.decryptWithKey(decdata); } catch (Exception var8) { DigiDocException.handleException(var8, 111); } } public void decrypt(String driver, String keystoreFile, int nKey, int token, String pin) throws DigiDocException { EncryptedKey ekey = this.getEncryptedKey(nKey); boolean bOk = true; try { ConfigManager ex = ConfigManager.instance(); SignatureFactory sigFac = ex.getSignatureFactoryOfType(driver); if(sigFac == null) { m_logger.error("No signature factory of type: " + driver); throw new DigiDocException(111, "No signature factory of type: " + driver, (Throwable)null); } if(sigFac.getType().equals("PKCS12")) { Pkcs12SignatureFactory decdata = (Pkcs12SignatureFactory)sigFac; bOk = decdata.load(keystoreFile, "PKCS12", pin); } if(!bOk) { m_logger.error("Failed to load signature token!"); throw new DigiDocException(111, "Failed to load signature token!", (Throwable)null); } if(ekey == null) { m_logger.error("No recipient nr: " + nKey); throw new DigiDocException(111, "No recipient nr: " + nKey, (Throwable)null); } if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypting key: " + nKey + " with token: " + token + " key-data: " + (ekey.getTransportKeyData() != null?ekey.getTransportKeyData().length:0)); } byte[] decdata1 = sigFac.decrypt(ekey.getTransportKeyData(), token, pin); this.decryptWithKey(decdata1); } catch (Exception var11) { DigiDocException.handleException(var11, 111); } } public void decryptWithKey(byte[] deckey) throws DigiDocException { byte[] ivdata = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; if(this.m_data != null && (this.m_nDataStatus == 4 || this.m_nDataStatus == 3)) { if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypting " + this.m_data.length + " using iv " + ivdata.length + " left: " + (this.m_data.length - ivdata.length)); } System.arraycopy(this.m_data, 0, ivdata, 0, ivdata.length); try { this.m_transportKey = new SecretKeySpec(deckey, "AES/CBC/NOPadding"); Cipher ex = this.getCipher(2, this.m_transportKey, ivdata); if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypting: " + this.m_data.length + " bytes"); } this.m_data = ex.doFinal(this.m_data, 16, this.m_data.length - 16); int nPadLen; if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypted data: " + this.m_data.length + " bytes"); for(nPadLen = this.m_data.length - 16; nPadLen < this.m_data.length; ++nPadLen) { m_logger.debug("byte at: " + nPadLen + " = " + this.m_data[nPadLen]); } } nPadLen = (new Integer(this.m_data[this.m_data.length - 1])).intValue(); if(m_logger.isDebugEnabled()) { m_logger.debug("Decrypted: " + this.m_data.length + " bytes, check padding: " + nPadLen); } boolean bPadOk = this.checkPadding(this.m_data, nPadLen); if(bPadOk) { this.m_data = this.removePadding(this.m_data, nPadLen); } nPadLen = (new Integer(this.m_data[this.m_data.length - 1])).intValue(); bPadOk = this.checkPadding(this.m_data, nPadLen); if(bPadOk) { this.m_data = this.removePadding(this.m_data, nPadLen); } if(this.m_nDataStatus == 4) { this.m_nDataStatus = 2; } if(this.m_nDataStatus == 3) { this.m_nDataStatus = 1; } if(this.m_nDataStatus == 2) { this.decompress(); } } catch (Exception var6) { DigiDocException.handleException(var6, 111); } } else { throw new DigiDocException(115, "Invalid data status for decryption operation!", (Throwable)null); } } private boolean checkPadding(byte[] data, int nPadLen) { boolean bPadOk = true; if(m_logger.isDebugEnabled()) { 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(data[i] != 0 && nPadLen != 16) { if(m_logger.isDebugEnabled()) { 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(m_logger.isDebugEnabled()) { m_logger.debug("Removing padding: " + nPadLen + " bytes"); } byte[] data2 = new byte[data.length - nPadLen]; System.arraycopy(data, 0, data2, 0, data.length - nPadLen); return data2; } private void compress(int nCompressOption) throws DigiDocException { if(nCompressOption != 1) { if(this.m_data != null && this.m_nDataStatus == 1) { try { int ex = this.m_data.length; if(m_logger.isDebugEnabled()) { m_logger.debug("Compressing: " + this.m_data.length + " bytes"); } ByteArrayOutputStream bout = new ByteArrayOutputStream(); DeflaterOutputStream gout = new DeflaterOutputStream(bout); gout.write(this.m_data); gout.flush(); gout.close(); bout.close(); byte[] n_data = bout.toByteArray(); int nNewSize = n_data.length; if(nCompressOption == 0 || nCompressOption == 2 && nNewSize < ex) { this.m_nDataStatus = 2; this.m_data = n_data; this.addProperty("OriginalSize", (new Integer(ex)).toString()); if(this.m_mimeType != null) { this.addProperty("OriginalMimeType", this.m_mimeType); } this.m_mimeType = "http://www.isi.edu/in-noes/iana/assignments/media-types/application/zip"; if(m_logger.isDebugEnabled()) { m_logger.debug("Keeping compressed: " + this.m_data.length + " bytes"); } } else if(m_logger.isDebugEnabled()) { m_logger.debug("Discarding compressed: " + this.m_data.length + " bytes"); } } catch (Exception var7) { DigiDocException.handleException(var7, 113); } } else { throw new DigiDocException(115, "Invalid data status for compression operation!", (Throwable)null); } } } private void decompress() throws DigiDocException { if(this.m_data != null && this.m_nDataStatus == 2) { try { if(m_logger.isDebugEnabled()) { m_logger.debug("Decompressing: " + this.m_data.length + " bytes"); } ByteArrayInputStream ex = new ByteArrayInputStream(this.m_data); InflaterInputStream gin = new InflaterInputStream(ex); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] data = new byte[2048]; boolean nRead = false; int nRead1; while((nRead1 = gin.read(data)) > 0) { bos.write(data, 0, nRead1); } gin.close(); ex.close(); bos.close(); this.m_data = bos.toByteArray(); this.m_nDataStatus = 1; if(m_logger.isDebugEnabled()) { m_logger.debug("Decompressed: " + this.m_data.length + " bytes"); } } catch (Exception var6) { DigiDocException.handleException(var6, 114); } } else { throw new DigiDocException(115, "Invalid data status for decompression operation!", (Throwable)null); } } public void encryptStream(InputStream in, OutputStream out, int nCompressOption) throws DigiDocException { byte[] ivdata = new byte[16]; if(this.m_transportKey == null) { this.initKey(); } if(this.m_data == null && this.m_nDataStatus == 0) { Cipher cipher = this.getCipher(1, (SecretKey)null, ivdata); Deflater compressor = null; if(nCompressOption == 0) { compressor = new Deflater(); if(this.m_mimeType != null) { this.addProperty("OriginalMimeType", this.m_mimeType); } this.m_mimeType = "http://www.isi.edu/in-noes/iana/assignments/media-types/application/zip"; } int nCiphBlockSize = cipher.getBlockSize(); short nBlockSize = 2048; int nTotalInput = 0; int nTotalCompressed = 0; int nTotalEncrypted = 0; int nTotalBase64 = 0; int nTotalEncInp = 0; int nB64left = 0; byte[] data1 = new byte[nBlockSize]; byte[] data2 = new byte[nBlockSize * 10]; byte[] b64leftover = new byte[65]; try { if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - algorithm: " + cipher.getAlgorithm() + " blocksize: " + nCiphBlockSize); } for(int ex = 0; ex < this.getNumKeys(); ++ex) { EncryptedKey isReadFromFile = this.getEncryptedKey(ex); isReadFromFile.encryptKey(this); } out.write(this.xmlHeader()); boolean var28 = false; boolean var29 = true; int nLen1; do { int nLen2; if(var29) { nLen1 = in.read(data1); if(nLen1 < 0) { nLen1 = 0; } if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + nLen1); } nTotalInput += nLen1; var28 = nLen1 < nBlockSize; if(nCompressOption == 0) { if(nLen1 > 0) { compressor.setInput(data1, 0, nLen1); } if(var28) { compressor.finish(); nLen2 = compressor.deflate(data2); var29 = compressor.finished(); } else { nLen2 = compressor.deflate(data2); if(nLen2 > 0) { var29 = false; } } nTotalCompressed += nLen2; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + nLen1 + " compressed: " + nLen2 + " needin: " + compressor.needsInput()); } } else { if(nLen1 > 0 && data2.length < nLen1) { data2 = new byte[nLen1]; } if(nLen1 > 0) { System.arraycopy(data1, 0, data2, 0, nLen1); nLen2 = nLen1; } else { nLen2 = 0; } } } else { nLen1 = 0; nLen2 = compressor.deflate(data2); if(var28) { var29 = compressor.finished(); } else { var29 = nLen2 == 0; } nTotalCompressed += nLen2; } byte[] encdata = null; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + nLen1 + " enc-input: " + nLen2); } if(var29 && var28) { ByteArrayOutputStream nUsed = new ByteArrayOutputStream(); if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - last-data: " + nLen2); } encdata = cipher.update(data2, 0, nLen2); if(encdata != null) { nUsed.write(encdata); } nTotalEncInp += nLen2; int nLastBlockSize = nCiphBlockSize - nTotalEncInp % nCiphBlockSize; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - total-data: " + nTotalEncInp + " padding: " + nLastBlockSize); } if(nLastBlockSize == 0) { nLastBlockSize = 16; } byte[] ldata = new byte[nLastBlockSize]; for(int i = 0; i < nLastBlockSize; ++i) { ldata[i] = 0; } ldata[nLastBlockSize - 1] = (new Integer(nLastBlockSize)).byteValue(); encdata = cipher.doFinal(ldata); nUsed.write(encdata); encdata = nUsed.toByteArray(); if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - encrypted: " + (encdata != null?encdata.length:0)); } } else if(nLen2 > 0) { encdata = cipher.update(data2, 0, nLen2); nTotalEncInp += nLen2; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - norm input: " + nLen2 + " encrypted: " + (encdata != null?encdata.length:0)); } } if(encdata != null) { byte[] var30; if(nTotalEncrypted == 0) { var30 = new byte[encdata.length + 16]; System.arraycopy(ivdata, 0, var30, 0, 16); System.arraycopy(encdata, 0, var30, 16, encdata.length); nTotalEncrypted += encdata.length; encdata = var30; } else { nTotalEncrypted += encdata.length; } if(nB64left > 0) { if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + encdata.length + " left: " + nB64left); } var30 = new byte[encdata.length + nB64left]; System.arraycopy(b64leftover, 0, var30, 0, nB64left); System.arraycopy(encdata, 0, var30, nB64left, encdata.length); encdata = var30; } int var31 = Base64Util.encodeToStream(encdata, out, var28 && var29); nB64left = encdata.length - var31; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + encdata.length + " used: " + var31 + " copy: " + nB64left + " pos: " + var31); } if(nB64left > 0) { System.arraycopy(encdata, var31, b64leftover, 0, nB64left); nTotalBase64 += var31 / 3 * 4; if(m_logger.isDebugEnabled()) { m_logger.debug("EncryptStream - input: " + encdata.length + " used: " + var31 + " base64: " + var31 / 3 * 4 + " left: " + nB64left); } } } } while(!var28 || nLen1 == nBlockSize || !var29); this.addProperty("OriginalSize", (new Integer(nTotalInput)).toString()); out.write(this.xmlTrailer()); out.flush(); if(m_logger.isInfoEnabled()) { m_logger.info("EncryptStream total - input: " + nTotalInput + " compressed: " + nTotalCompressed + " encrypted: " + nTotalEncrypted + " base64: " + nTotalBase64); } } catch (Exception var27) { DigiDocException.handleException(var27, 112); } } else { throw new DigiDocException(115, "Invalid data status for encryption operation!", (Throwable)null); } } public byte[] toXML() throws DigiDocException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { bos.write(this.xmlHeader()); byte[] ex = ConvertUtils.str2data(Base64Util.encode(this.m_data, 64)); int nTotalBase64 = ex.length; bos.write(ex); if(m_logger.isInfoEnabled()) { m_logger.info("Encrypt total - base64: " + nTotalBase64); } bos.write(this.xmlTrailer()); } catch (IOException var4) { DigiDocException.handleException(var4, 89); } return bos.toByteArray(); } private byte[] xmlHeader() throws DigiDocException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { bos.write(ConvertUtils.str2data("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>")); bos.write(ConvertUtils.str2data("<denc:EncryptedData xmlns:denc=\"" + this.m_xmlns + "\"")); if(this.m_id != null) { bos.write(ConvertUtils.str2data(" Id=\"" + this.m_id + "\"")); } if(this.m_mimeType != null) { bos.write(ConvertUtils.str2data(" MimeType=\"" + this.m_mimeType + "\"")); } if(this.m_type != null) { bos.write(ConvertUtils.str2data(" Type=\"" + this.m_type + "\"")); } bos.write(ConvertUtils.str2data(">")); bos.write(ConvertUtils.str2data("<denc:EncryptionMethod Algorithm=\"")); bos.write(ConvertUtils.str2data(this.m_encryptionMethod)); bos.write(ConvertUtils.str2data("\"></denc:EncryptionMethod>")); bos.write(ConvertUtils.str2data("<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">")); for(int ex = 0; ex < this.getNumKeys(); ++ex) { EncryptedKey key = this.getEncryptedKey(ex); bos.write(key.toXML()); } bos.write(ConvertUtils.str2data("</ds:KeyInfo>")); bos.write(ConvertUtils.str2data("<denc:CipherData><denc:CipherValue>")); } catch (IOException var4) { DigiDocException.handleException(var4, 89); } return bos.toByteArray(); } private byte[] xmlTrailer() throws DigiDocException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { bos.write(ConvertUtils.str2data("</denc:CipherValue></denc:CipherData>")); if(this.getNumProperties() > 0) { bos.write(ConvertUtils.str2data("<denc:EncryptionProperties")); if(this.getEncryptionPropertiesId() != null) { bos.write(ConvertUtils.str2data(" Id=\"" + this.getEncryptionPropertiesId() + "\"")); } bos.write(ConvertUtils.str2data(">")); for(int ex = 0; ex < this.getNumProperties(); ++ex) { EncryptionProperty prop = this.getProperty(ex); bos.write(prop.toXML()); } bos.write(ConvertUtils.str2data("</denc:EncryptionProperties>")); } bos.write(ConvertUtils.str2data("</denc:EncryptedData>")); } catch (IOException var4) { DigiDocException.handleException(var4, 89); } return bos.toByteArray(); } public ArrayList validate() { ArrayList errs = new ArrayList(); DigiDocException ex = this.validateEncryptionMethod(this.m_encryptionMethod); if(ex != null) { errs.add(ex); } ex = this.validateXmlns(this.m_xmlns); if(ex != null) { errs.add(ex); } if(this.m_encProperties != null) { ArrayList i = this.m_encProperties.validate(); if(!i.isEmpty()) { errs.addAll(i); } } for(int var6 = 0; var6 < this.getNumKeys(); ++var6) { EncryptedKey ekey = this.getEncryptedKey(var6); ArrayList e = ekey.validate(); if(!e.isEmpty()) { errs.addAll(e); } } return errs; } public String toString() { String str = null; try { str = new String(this.toXML()); } catch (Exception var3) { ; } return str; } }