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;
}
}