All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ee.sk.utils.ConvertUtils Maven / Gradle / Ivy

/*
 * ConvertUtils.java
 * PROJECT: JDigiDoc
 * DESCRIPTION: Digi Doc functions for creating
 *	and reading signed documents. 
 * AUTHOR:  Veiko Sinivee, S|E|B IT Partner Estonia
 *==================================================
 * Copyright (C) AS Sertifitseerimiskeskus
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * GNU Lesser General Public Licence is available at
 * http://www.gnu.org/copyleft/lesser.html
 *==================================================
 */

package ee.sk.utils;
import java.util.regex.Matcher;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.TimeZone;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import ee.sk.digidoc.DigiDocException;
import ee.sk.digidoc.SignedDoc;
import ee.sk.digidoc.factory.BouncyCastleNotaryFactory;
import ee.sk.digidoc.tsl.MultiLangString;
import java.net.*;
import org.apache.log4j.Logger;
import javax.security.auth.x500.X500Principal;

import java.security.Principal;
import java.security.cert.*;

/**
 * Miscellaneous data conversion utility methods
 * @author  Veiko Sinivee
 * @version 1.0
 */
public class ConvertUtils 
{
    private static final String m_dateFormat = "yyyy.MM.dd'T'HH:mm:ss'Z'";
    private static final String m_dateFormatXAdES = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private static final String m_dateFormatIso8601 = "yyyy.MM.dd'T'HH:mm:ss";
    private static final String m_dateFormatSSS = "yyyy.MM.dd'T'HH:mm:ss.SSS'Z'";
    private static final String m_dateFormatXAdESSSS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
    private static Logger m_logger = Logger.getLogger(ConvertUtils.class);
    public static final String X509_NAME_RFC = "RFC2253"; //"RFC4514";
    /** Invalid SHA1 13+0x00 algortihm prefix - 00 30 21 30 09 06 05 2b 0e 03 02 1a 04 14 0x00 */
    private static final byte[] sha1AlgPrefix13Bad = { 
    	0x30, 0x1f, 0x30, 0x07, 0x06, 
    	0x05, 0x2b, 0x0e, 0x03, 0x02, 
    	0x1a, 0x04, 0x14, 0x00 };
    /** Invalid SHA1 15+0x00 algortihm prefix - 00 30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 0x00 */
    private static final byte[] sha1AlgPrefix15Bad = { 
    	0x30, 0x21, 0x30, 0x09, 0x06, 
        0x05, 0x2b, 0x0e, 0x03, 0x02, 
        0x1a, 0x05, 0x00, 0x04, 0x14, 0x00 };
    /** SHA1 algortihm prefix - 00 30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14  */
    private static final byte[] sha1AlgPrefix1 = { // long
        0x30, 0x21, 0x30, 0x09, 0x06, 
        0x05, 0x2b, 0x0e, 0x03, 0x02, 
        0x1a, 0x05, 0x00, 0x04, 0x14 };
    private static final byte[] sha1AlgPrefix2 = { // short
    	0x30, 0x1f, 0x30, 0x07, 0x06, 
    	0x05, 0x2b, 0x0e, 0x03, 0x02, 
    	0x1a, 0x04, 0x14 };
    /** SHA224 prefix - 00302d300d06096086480165030402040500041c */
    private static final byte[] sha224AlgPrefix1 = { // long
        0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60,
        (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 
        0x04, 0x05, 0x00, 0x04, 0x1c };
    private static final byte[] sha224AlgPrefix2 = { // short
    	0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60,
        (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 
        0x04, 0x04, 0x1c }; 
    /** sha256 alg prefix - 003031300d060960864801650304020105000420 5ad8f86f90558d973aba4ce9be116646efd2c57758e5238b841d50abe788bae9 */
    private static final byte[] sha256AlgPrefix1 = { // long
        0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
    };
    private static final byte[] sha256AlgPrefix2 = { // short
    	0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20
    };
    private static final byte[] sha512AlgPrefix1 =   // long
    { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
    private static final byte[] sha512AlgPrefix2 =    // short
    { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 };

    
    /**
     * Helper method to convert a Date
     * object to xsd:date format
     * @param d input data
     * @param ddoc signed doc
     * @return stringified date (xsd:date)
     * @throws DigiDocException for errors
     */
    public static String date2string(Date d, SignedDoc ddoc)
        throws DigiDocException
    {
        String str = null, sF = null;
        try {
        	if(d != null) {
            sF = (ddoc.getFormat().equals(SignedDoc.FORMAT_BDOC) ||
            	(ddoc.getVersion().equals(SignedDoc.VERSION_1_3)) ? m_dateFormatXAdES : m_dateFormat);
            SimpleDateFormat f = new SimpleDateFormat(sF);
            f.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
            str = f.format(d);
        	}
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_DATE_FORMAT);
        }
        return str;
    }
    
    public static String convX509Name(X500Principal principal)
    {
    	String sName = principal.getName(X509_NAME_RFC);
    	return sName;
    }
    
    public static String getTrace(Throwable ex) 
	{
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		ex.printStackTrace(pw);
		return sw.toString();
	}
    
    /**
     * Adds ASN.1 structure prefix to digest value to be signed
     * @param digest digest value to be signed
     * @return prefixed digest value
     */
    public static byte[] addDigestAsn1Prefix(byte[] digest)
    {
    	byte[] ddata = null;
    	/*if(digest.length == SignedDoc.SHA1_DIGEST_LENGTH) {
      	  ddata = new byte[sha1AlgPrefix.length + digest.length + 1];
      	  System.arraycopy(sha1AlgPrefix, 0, ddata, 0, sha1AlgPrefix.length);
      	  System.arraycopy(digest, 0, ddata, 
      			sha1AlgPrefix.length + 1, digest.length);
      	}*/
    	if(digest.length == SignedDoc.SHA1_DIGEST_LENGTH) {
    	  ddata = new byte[sha1AlgPrefix1.length + digest.length];
    	  System.arraycopy(sha1AlgPrefix1, 0, ddata, 0, sha1AlgPrefix1.length);
    	  System.arraycopy(digest, 0, ddata, 
    			sha1AlgPrefix1.length, digest.length);
    	}
    	if(digest.length == SignedDoc.SHA224_DIGEST_LENGTH) {
        	  ddata = new byte[sha224AlgPrefix1.length + digest.length];
        	  System.arraycopy(sha224AlgPrefix1, 0, ddata, 0, sha224AlgPrefix1.length);
        	  System.arraycopy(digest, 0, ddata, 
        			  sha224AlgPrefix1.length, digest.length);
        }
    	if(digest.length == SignedDoc.SHA256_DIGEST_LENGTH) {
      	  ddata = new byte[sha256AlgPrefix1.length + digest.length];
      	  System.arraycopy(sha256AlgPrefix1, 0, ddata, 0, sha256AlgPrefix1.length);
      	  System.arraycopy(digest, 0, ddata, 
      			sha256AlgPrefix1.length, digest.length);
      	}
    	if(digest.length == SignedDoc.SHA512_DIGEST_LENGTH) {
      	  ddata = new byte[sha512AlgPrefix1.length + digest.length];
      	  System.arraycopy(sha512AlgPrefix1, 0, ddata, 0, sha512AlgPrefix1.length);
      	  System.arraycopy(digest, 0, ddata, 
      			sha512AlgPrefix1.length, digest.length);
      	}
    	return ddata;
    }
    
    public static boolean compareBytes(byte[] srch, byte[] from, int idx1)
    {
    	if(m_logger.isDebugEnabled()) 
          	m_logger.debug("Find: \'" + SignedDoc.bin2hex(srch) + "\' int: \'" + SignedDoc.bin2hex(from) + "\' starting: " + idx1);
      	if(srch != null && from != null && idx1 >= 0 && ((idx1 + srch.length) < from.length)) {
    		for(int i = idx1; i < idx1 + srch.length; i++) {
    			if(m_logger.isDebugEnabled()) 
    	          	m_logger.debug("Pos: " + i +  " " + from[i] + " - " + srch[i-idx1]);
    	      	if(from[i] != srch[i-idx1])
    				return false;
    		}
    		return true;
    	}
    	return false;
    }
    
    public static String findNonceDigType(byte[] digest)
    {
    	if(digest.length == SignedDoc.SHA1_DIGEST_LENGTH + 2) 
    		return SignedDoc.SHA1_DIGEST_TYPE;
    	if(digest.length == SignedDoc.SHA224_DIGEST_LENGTH + 2) 
    		return SignedDoc.SHA224_DIGEST_TYPE;
        if(digest.length == SignedDoc.SHA256_DIGEST_LENGTH + 2) 
    		return SignedDoc.SHA256_DIGEST_TYPE;
      	if(digest.length == SignedDoc.SHA512_DIGEST_LENGTH + 2) 
    		return SignedDoc.SHA512_DIGEST_TYPE;
      	return null;
    }
    
    public static String findDigType(byte[] digest)
    {
    	if((compareBytes(sha1AlgPrefix13Bad, digest, 0) && digest.length == 34) ||
    	   (compareBytes(sha1AlgPrefix15Bad, digest, 0) && digest.length == 36))
        	return SignedDoc.SHA1_DIGEST_TYPE_BAD;
    	if(compareBytes(sha1AlgPrefix1, digest, 0) ||
    		compareBytes(sha1AlgPrefix2, digest, 0))
    		return SignedDoc.SHA1_DIGEST_TYPE;
    	if(compareBytes(sha224AlgPrefix1, digest, 0) ||
    	   compareBytes(sha224AlgPrefix2, digest, 0))
    		return SignedDoc.SHA224_DIGEST_TYPE;
    	if(compareBytes(sha256AlgPrefix1, digest, 0) ||
    	   compareBytes(sha256AlgPrefix2, digest, 0))
    		return SignedDoc.SHA256_DIGEST_TYPE;
    	if(compareBytes(sha512AlgPrefix1, digest, 0) ||
    	   compareBytes(sha512AlgPrefix2, digest, 0))
    		return SignedDoc.SHA512_DIGEST_TYPE;
    	return null;
    }
    
    public static byte[] removePrefix(byte[] digest)
    {
    	int nLen = 0;
    	if(compareBytes(sha1AlgPrefix1, digest, 0))
    		nLen = sha1AlgPrefix1.length;
    	else if(compareBytes(sha1AlgPrefix2, digest, 0))
    		nLen = sha1AlgPrefix2.length;
    	else if(compareBytes(sha224AlgPrefix1, digest, 0))
    		nLen = sha224AlgPrefix1.length;
    	else if(compareBytes(sha224AlgPrefix2, digest, 0))
    		nLen = sha224AlgPrefix2.length;
    	else if(compareBytes(sha256AlgPrefix1, digest, 0))
    		nLen = sha256AlgPrefix1.length;
    	else if(compareBytes(sha256AlgPrefix2, digest, 0))
    		nLen = sha256AlgPrefix2.length;
    	else if(compareBytes(sha512AlgPrefix1, digest, 0))
    		nLen = sha512AlgPrefix1.length;
    	else if(compareBytes(sha512AlgPrefix2, digest, 0))
    		nLen = sha512AlgPrefix2.length;
    	if(nLen > 0) {
    		byte[] ndig = new byte[digest.length - nLen];
    		System.arraycopy(digest, 
                  	digest.length - ndig.length,
                  	ndig, 0, ndig.length);
    		return ndig;
    	}
    	return null;
    }
    
    /*
     * IB-4056 this method was commented out because it requires caller to know
     * the prefix used. If this is not the case error will occur.
     * Use instead byte[] removePrefix(byte[] digest) that determines which prefix
     * is used before removing it.
     */
    /*public static byte[] removePrefixByType(byte[] digest, String digType)
    {
    	int nLen = 0;
    	if(digType.equals(SignedDoc.SHA1_DIGEST_TYPE))
    		nLen = sha1AlgPrefix1.length;
    	else if(digType.equals(SignedDoc.SHA224_DIGEST_TYPE))
    		nLen = sha224AlgPrefix1.length;
    	else if(digType.equals(SignedDoc.SHA256_DIGEST_TYPE))
    		nLen = sha256AlgPrefix1.length;
    	else if(digType.equals(SignedDoc.SHA512_DIGEST_TYPE))
    		nLen = sha512AlgPrefix1.length;
    	if(nLen > 0) {
    		byte[] ndig = new byte[digest.length - nLen];
    		System.arraycopy(digest, 
                  	digest.length - ndig.length,
                  	ndig, 0, ndig.length);
    		return ndig;
    	}
    	return null;
    }*/
    
    /**
     * Helper method to convert a string
     * to a Date object from xsd:date format
     * @param str stringified date (xsd:date
     * @param ddoc signed doc
     * @return Date object
     * @throws DigiDocException for errors
     */
    public static Date string2date(String str, SignedDoc ddoc)
        throws DigiDocException
    {
        Date d = null;
        String sF = null;
        try {
            sF = (ddoc.getFormat().equals(SignedDoc.FORMAT_BDOC) ||
            	 (ddoc.getVersion().equals(SignedDoc.VERSION_1_3) ||
                  ddoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) ? m_dateFormatXAdES : 
                	  (ddoc.getFormat().equals(SignedDoc.FORMAT_SK_XML) ? m_dateFormatIso8601 : m_dateFormat));
            SimpleDateFormat f = new SimpleDateFormat(sF);
            if(!ddoc.getFormat().equals(SignedDoc.FORMAT_SK_XML))
            f.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
            if(str != null && str.length() > 0)
            	d = f.parse(str.trim());
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_DATE_FORMAT);
        }
        return d;
    }
    
    /**
     * Helper method to convert a string
     * to a Date object from xsd:date format
     * @param str stringified date (xsd:date
     * @return Date object
     * @throws DigiDocException for errors
     */
    public static Date str2date(String str)
    {
        Date d = null;
        try {
        	// use default value to get a meaningful error message 
        	SimpleDateFormat f = new SimpleDateFormat(m_dateFormatXAdES);
            // test other possibilities
            if(str != null && str.length() >= 20 && str.charAt(10) == 'T') {
            	if(str.charAt(4) == '-' && str.charAt(7) == '-') {
            		if(str.length() > 20)
            			f = new SimpleDateFormat(m_dateFormatXAdESSSS);
            		else
            			f = new SimpleDateFormat(m_dateFormatXAdES);
            	}
            	if(str.charAt(4) == '.' && str.charAt(7) == '.') {
            		if(str.length() > 20) {
            			if(str.charAt(20) == '-')
            				f = new SimpleDateFormat(m_dateFormatIso8601);
            			else
            				f = new SimpleDateFormat(m_dateFormatSSS);
            		} else
            			f = new SimpleDateFormat(m_dateFormat);
            	}
            	f.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
            	d = f.parse(str.trim());
            }
        } catch(Exception ex) {
            m_logger.error("Error parsing date: " + str + " - " + ex);
        }
        return d;
    }

    /**
     * Helper method to convert a string
     * to a BigInteger object
     * @param str stringified date (xsd:date
     * @return BigInteger object
     * @throws DigiDocException for errors
     */
    public static BigInteger string2bigint(String str)
        throws DigiDocException
    {
        BigInteger b = null;
        try {
        	if(str != null && str.length() > 0)
        		b = new BigInteger(str.trim());
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_NUMBER_FORMAT);
        }
        return b;
    }
   
    /**
     * Helper method to convert a String
     * to UTF-8
     * @param data input data
     * @param codepage codepage of input bytes
     * @return UTF-8 string
     * @throws DigiDocException for errors
     */
    public static byte[] data2utf8(byte[] data, String codepage)
        throws DigiDocException
    {
        byte[] bdata = null;
        try {
            String str = new String(data, codepage);
            bdata = str.getBytes("UTF-8");
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_UTF8_CONVERT);
        }
        return bdata;
    }
    
    /**
     * Converts to UTF-8 byte array
     * @param str input data
     * @return byte array of string in desired codepage
     * @throws DigiDocException for errors
     */
    public static byte[] str2data(String str)
        throws DigiDocException
    {
        return str2data(str, "UTF-8");
    }

    /**
     * Helper method to convert a String
     * to byte array of any codepage
     * @param data input data
     * @param codepage codepage of output bytes
     * @return byte array of string in desired codepage
     * @throws DigiDocException for errors
     */
    public static byte[] str2data(String str, String codepage)
        throws DigiDocException
    {
        byte[] bdata = null;
        try {
            bdata = str.getBytes(codepage);
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_UTF8_CONVERT);
        }
        return bdata;
    }
    
    /**
     * Helper method to convert a String
     * to UTF-8
     * @param data input data
     * @param codepage codepage of input bytes
     * @return UTF-8 string
     * @throws DigiDocException for errors
     */
    public static String data2str(byte[] data, String codepage)
        throws DigiDocException
    {
        String str = null;
        try {
            str = new String(data, codepage);
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_UTF8_CONVERT);
        }
        return str;
    }
    
    /**
     * Helper method to convert an UTF-8
     * String to non-utf8 string
     * @param UTF-8 input data
     * @return normal string
     * @throws DigiDocException for errors
     */
    public static String utf82str(String data)
        throws DigiDocException
    {
        String str = null;
        try {
            byte[] bdata = data.getBytes();
            str = new String(bdata, "UTF-8");
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_UTF8_CONVERT);
        }
        return str;
    }
    
    /**
     * Checks if the certificate identified by this CN is
     * a known OCSP responders cert
     * @param cn certificates common name
     * @return true if this is a known OCSP cert
     */
    public static boolean isKnownOCSPCert(String cn)
    {
    	int nOcsps = ConfigManager.instance().getIntProperty("DIGIDOC_OCSP_COUNT", 0);
    	//if(m_logger.isDebugEnabled())
    	//	m_logger.debug("OCSPs: " + nOcsps);
    	for(int i = 0; i < nOcsps; i++) {
    		String s = ConfigManager.instance().getProperty("DIGIDOC_OCSP" + (i+1) + "_CN");
    		//if(m_logger.isDebugEnabled())
        	//	m_logger.debug("DIGIDOC_OCSP" + (i+1) + "_CN" + "=>" + s);
    		if(s != null && s.equals(cn))
    			return true;
    	}
    	return false;
    }
    
    public static void addKnownOCSPCert(String cn)
    {
    	int nOcsps = ConfigManager.instance().getIntProperty("DIGIDOC_OCSP_COUNT", 0);
    	//if(m_logger.isDebugEnabled())
    	//	m_logger.debug("OCSPs: " + nOcsps);
    	nOcsps++;
    	String key = "DIGIDOC_OCSP" + nOcsps + "_CN";
    	ConfigManager.instance().setStringProperty(key, cn);
    	ConfigManager.instance().setStringProperty("DIGIDOC_OCSP_COUNT", new Integer(nOcsps).toString());
    	//if(m_logger.isDebugEnabled())
    	//	m_logger.debug(key + "=>" + cn + " count: " + nOcsps);
    }
    
    /**
     * Checks if the certificate identified by this CN is
     * a known TSA cert
     * @param cn certificates common name
     * @return true if this is a known TSA cert
     */
    public static boolean isKnownTSACert(String cn)
    {
    	int nTsas = ConfigManager.instance().getIntProperty("DIGIDOC_TSA_COUNT", 0);
    	for(int i = 0; i < nTsas; i++) {
    		String s = ConfigManager.instance().getProperty("DIGIDOC_TSA" + (i+1) + "_CN");
    		if(s != null && s.equals(cn))
    			return true;
    	}
    	return false;
    }
    
    public static void addKnownTSACert(String cn)
    {
    	int nOcsps = ConfigManager.instance().getIntProperty("DIGIDOC_TSA_COUNT", 0);
    	//if(m_logger.isDebugEnabled())
    	//	m_logger.debug("OCSPs: " + nOcsps);
    	nOcsps++;
    	String key = "DIGIDOC_TSA" + nOcsps + "_CN";
    	ConfigManager.instance().setStringProperty(key, cn);
    	ConfigManager.instance().setStringProperty("DIGIDOC_TSA_COUNT", new Integer(nOcsps).toString());
    	//if(m_logger.isDebugEnabled())
    	//	m_logger.debug(key + "=>" + cn + " count: " + nOcsps);
    }
    
    /**
     * return CN part of DN
     * @return CN part of DN or null
     */
    public static String getCommonName(String dn) {
        String name = null;
        if(m_logger.isDebugEnabled())
        		m_logger.debug("DN: " + dn);
        if(dn != null) {
        	int idx1 = dn.indexOf("CN=");
        	if(idx1 != -1) {
            	idx1 += 2;
            	while(idx1 < dn.length() && 
            		!Character.isLetter(dn.charAt(idx1)))
                	idx1++;
            	int idx2 = idx1;
            	while(idx2 < dn.length() && 
            		dn.charAt(idx2) != '\"' && 
            		dn.charAt(idx2) != '\\' && 
            		(dn.charAt(idx2) != ',' /*|| dn.charAt(idx2-1) != '\\'*/) && 
            		dn.charAt(idx2) != '/')
                	idx2++;
            	name = dn.substring(idx1, idx2);            
        	}
        }
        return name;
    }
    
    
    /**
     * return CN part of DN
     * @return CN part of DN or null
     */
    /*public static String getDnPart(X509Certificate cert, String attr) {
        String value = null;
        if(cert != null) {
        	Principal pr = cert.getSubjectDN();
        	pr.ge
        }
        return value;
    }*/
    
    /**
     * return CN part of DN
     * @return CN part of DN or null
     */
    public static String getDnPart(String dn, String attr) {
        String name = null;
        if(dn != null) {
        	int idx1 = dn.indexOf(attr+ "=");
        	if(idx1 != -1) {
            	idx1 += attr.length() + 1;
            	/*while(idx1 < dn.length() && 
            		!Character.isLetter(dn.charAt(idx1)))
                	idx1++;*/
            	int idx2 = idx1;
            	while(idx2 < dn.length() && 
            		dn.charAt(idx2) != ',' && 
            		dn.charAt(idx2) != '/' && 
            		dn.charAt(idx2) != ' ')
                	idx2++;
            	name = dn.substring(idx1, idx2);            
        	}
        }
        return name;
    }
    
    
    public static byte[] getBytesFromFile(File file ) throws IOException {
        InputStream is = new FileInputStream(file);
    
        // Get the size of the file
        long length = file.length();
    
        if (length > Integer.MAX_VALUE) {
            // File is too large
        }
    
        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];
    
        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
    
        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }
    
        // Close the input stream and return bytes
        is.close();
        return bytes;
    }
    
   
    	     
    
    /** 
     * Converts a hex string to byte array
     * @param hexString input data
     * @return byte array
     */
    public static byte[] hex2bin(String hexString)
    {
    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
    	try {
    		for(int i = 0; (hexString != null) && 
    			(i < hexString.length()); i += 2) {
				String tmp = hexString.substring(i, i+2);  
    			Integer x = new Integer(Integer.parseInt(tmp, 16));
    			bos.write(x.byteValue());    			
    		}
    	} catch(Exception ex) {
    		m_logger.error("Error converting hex string: " + ex);
    	}
    	return bos.toByteArray();
    }
    
    /**
     * Converts a byte array to hex string
     * @param arr byte array input data
     * @return hex string
     */
    public static String bin2hex(byte[] arr)
    {
    	StringBuffer sb = new StringBuffer();
    	for(int i = 0; i < arr.length; i++) {
    		String str = Integer.toHexString((int)arr[i]);
    		if(str.length() == 2)
    			sb.append(str);
    		if(str.length() < 2) {
    			sb.append("0");
    			sb.append(str);
    		}
    		if(str.length() > 2)
    			sb.append(str.substring(str.length()-2));
    	}
    	return sb.toString();
    }
    
    private static final String hexChars = "0123456789ABCDEF";
    
    public static boolean isHexDigit(char c) {
    	char c2 = Character.toUpperCase(c);
    	for(int i = 0; i < hexChars.length(); i++)
    		if(hexChars.charAt(i) == c2)
    			return true;
    	return false;
    }
    
    public static String uriDecode(String s1)
    {
    	if(s1 == null || s1.length() == 0) 
    		return s1;
    	try {
    	  String s = s1;
    	  s = replaceStr(s, '+', "%2B");
    	  s = URLDecoder.decode(s, "UTF-8");
		  if(m_logger.isDebugEnabled())
			  m_logger.debug("URI: " + s1 + " decoded: " + s);
		  return s;
		} catch(Exception ex) {
			m_logger.error("Error decoding bytes: " + ex);
		}
		return null;
    }
    
    private static String replaceStr(String src, char c1, String rep)
    {
    	StringBuffer sb = new StringBuffer();
    	for(int i = 0; (src != null) && (i < src.length()); i++) {
    		char c2 = src.charAt(i);
    		if(c2 == c1)
    			sb.append(rep);
    		else
    			sb.append(c2);
    	}
    	return sb.toString();
    }
    
    /*
     Not converting:
    (From RFC 2396 "URI Generic Syntax")
    reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
    mark     = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
     */
    public static String uriEncode(String s1)
    {
    	try {
    		String s = s1;
    		//s = replaceStr(s, '[', "%5B");
    		//s = replaceStr(s, ']', "%5D");
    	  	if(m_logger.isDebugEnabled())
  			  m_logger.debug("Before uri-enc: " + s);
    	  s = URLEncoder.encode(s, "UTF-8");
  		  s = replaceStr(s, '+', "%20");
  		  // restore mark chars that got converted
  		  s = s.replaceAll("%21", "!");
  		  s = s.replaceAll("%40", "@");
  		  s = s.replaceAll("%27", "\'");
		  s = s.replaceAll("%24", Matcher.quoteReplacement("$"));
  		  s = s.replaceAll("%7E", "~");
  		  s = s.replaceAll("%26", Matcher.quoteReplacement("&"));
		  s = s.replaceAll("%28", "(");
  		  s = s.replaceAll("%29", ")");
  		  s = s.replaceAll("%3D", "=");
  		  s = s.replaceAll("%2B", "+");
  		  s = s.replaceAll("%2C", ",");
          s = s.replaceAll("%3B", ";");
          s = s.replaceAll("%2F", "/");
          s = s.replaceAll("%3F", "?");
          s = s.replaceAll("%3A", ":");
  		  if(m_logger.isDebugEnabled())
			  m_logger.debug("URI: " + s1 + " encoded: " + s);
		  return s;
		} catch(Exception ex) {
			m_logger.error("Error encoding bytes: " + ex);
		}
		return null;
    }
    
    
    /*
    Not converting:
    (From RFC  RFC 3986 "URI Generic Syntax")
    unreserved    = ALPHA / DIGIT / “-” / “.” / “_” / “~”
    gen-delims = “:” / “/” / “?” / “#” / “[” / “]” / “@”
    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    */
   public static String uriEncodePath(String s1)
   {
   	try {
   		String s = s1;
   		//s = replaceStr(s, '[', "%5B");
   		//s = replaceStr(s, ']', "%5D");
   	  	if(m_logger.isDebugEnabled())
 			  m_logger.debug("Before uri-path-enc: " + s);
   	  	s = URLEncoder.encode(s, "UTF-8");
 		s = replaceStr(s, '+', "%20");
 		s = s.replaceAll("%7E", "~");
 		// the following chars are not restored for compatibility with CPP and Digidoc4j
// 		s = s.replaceAll("%26", Matcher.quoteReplacement("&"));
// 		s = s.replaceAll("%21", "!");
//		  s = s.replaceAll("%40", "@");
//		  s = s.replaceAll("%27", "\'");
//		  s = s.replaceAll("%24", Matcher.quoteReplacement("$"));
//		  s = s.replaceAll("%28", "(");
//		  s = s.replaceAll("%29", ")");
//		  s = s.replaceAll("%3D", "=");
//		  s = s.replaceAll("%2B", "+");
//		  s = s.replaceAll("%2C", ",");
//	      s = s.replaceAll("%3B", ";");
//	      s = s.replaceAll("%2F", "/");
//	      s = s.replaceAll("%3F", "?");
          
		if(m_logger.isDebugEnabled())
		  m_logger.debug("URI path: " + s1 + " encoded: " + s);
		return s;
	} catch(Exception ex) {
		m_logger.error("Error encoding path: " + ex);
	}
	return null;
   }
 
    public static String escapeXmlSymbols(String s1)
    {
    	if(s1 == null || s1.length() == 0) 
    		return s1;
    	StringBuffer sb = new StringBuffer();
    	try {
    	  for(int i = 0; i < s1.length(); i++) {
    		char c1 = s1.charAt(i);
    		if(c1 == '&') {
    			sb.append("&");
    		} else if(c1 == '<') {
        		sb.append("<");
    		} else if(c1 == '>') {
        		sb.append(">");
    		} else if(c1 == '\r') {
        		sb.append("
");
    		} else if(c1 == '\'') {
        		sb.append("'");
    		} else if(c1 == '\"') {
        		sb.append(""");
        	} else
    		  sb.append(c1);
    	  }
    	} catch(Exception ex) {
			m_logger.error("Error converting bytes: " + ex);
		}
		return sb.toString();
    }
    
    public static String escapeTextNode(String s1)
    {
    	if(s1 == null || s1.length() == 0) 
    		return s1;
    	StringBuffer sb = new StringBuffer();
    	try {
    	  for(int i = 0; i < s1.length(); i++) {
    		char c1 = s1.charAt(i);
    		if(c1 == '&') {
    			sb.append("&");
    		} else if(c1 == '<') {
        		sb.append("<");
    		} else if(c1 == '>') {
        		sb.append(">");
    		} else if(c1 == '\r') {
        		sb.append("
");
    		} else
    			sb.append(c1);
    	  }
    	} catch(Exception ex) {
			m_logger.error("Error converting bytes: " + ex);
		}
		return sb.toString();
    }
 
    public static String unescapeXmlSymbols(String s1)
    {
    	String s2 = s1.replaceAll("<", "<");
    	s2 = s2.replaceAll(">", ">");
    	s2 = s2.replaceAll(">", ">");
    	s2 = s2.replaceAll("
", "\r");
    	s2 = s2.replaceAll("'", "'");
    	s2 = s2.replaceAll(""", "\"");
    	s2 = s2.replaceAll("&", "&");
    	s2 = s2.replaceAll("
", "\n");
    	return s2;
    }
    
    /**
     * Returns a string representation of an int element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @return stringified element representation
     */
    public static String intElemToString(String name, int value)
    {
        StringBuffer sb = new StringBuffer();
        if(value != 0) {
        	sb.append("(");
        	sb.append(name);
        	sb.append("=");
        	sb.append(value);
        	sb.append(")");
        }
        return sb.toString();
    }
    
    /**
     * Returns a string representation of an long element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @return stringified element representation
     */
    public static String longElemToString(String name, long value)
    {
        StringBuffer sb = new StringBuffer();
        if(value != 0) {
        	sb.append("(");
        	sb.append(name);
        	sb.append("=");
        	sb.append(value);
        	sb.append(")");
        }
        return sb.toString();
    }
    
    /**
     * Returns a string representation of an double element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @return stringified element representation
     */
    public static String doubleElemToString(String name, double value)
    {
        StringBuffer sb = new StringBuffer();
        if(value != 0) {
        	sb.append("(");
        	sb.append(name);
        	sb.append("=");
        	sb.append(value);
        	sb.append(")");
        }
        return sb.toString();
    }

    /**
     * Returns a string representation of a boolean element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @param bShowFalse show also false values or not
     * @return stringified element representation
     */
    public static String booleanElemToString(String name, boolean value, boolean bShowFalse)
    {
        StringBuffer sb = new StringBuffer();
        if(value || (!value && bShowFalse)) {
        	sb.append("(");
        	sb.append(name);
        	sb.append("=");
        	sb.append(value);
        	sb.append(")");
        }
        return sb.toString();
    }    
    
    /**
     * Returns a string representation of a string element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @return stringified element representation
     */
    public static String stringElemToString(String name, String value)
    {
        StringBuffer sb = new StringBuffer();
        if(value != null) {
            sb.append("(");
            sb.append(name);
            sb.append("=");
            sb.append(value);
            sb.append(")");
        }
        return sb.toString();
    }

    /**
     * Returns a string representation of a date element
     * with it's value for debug & log purposes
     * @param name element name
     * @param value elements value
     * @return stringified element representation
     */
    public static String dateElemToString(String name, Date value)
    {
        StringBuffer sb = new StringBuffer();
        if(value != null) {            
            sb.append("(");
            sb.append(name);
            sb.append("=");
            Calendar cal = Calendar.getInstance();
            cal.setTime(value);
            sb.append(cal.get(Calendar.DAY_OF_MONTH));
            sb.append(".");
            sb.append(cal.get(Calendar.MONTH)+1);
            sb.append(".");
            sb.append(cal.get(Calendar.YEAR));
            sb.append(")");
        }
        return sb.toString();
    }
    
    /**
     * Converts a List of MultiLangStrings to array
     * @param l List object
     * @return array of MultiLangString objects
     */
    public static MultiLangString[] list2mls(List l) {
		MultiLangString[] arr = null;
		if(l != null && l.size() > 0) {
			arr = new MultiLangString[l.size()];
			for(int i = 0; i < l.size(); i++)
				arr[i] = (MultiLangString)l.get(i);
		}
		return arr;
	}
    
    /**
     * Converts a List of Datew to array
     * @param l List object
     * @return array of Date objects
     */
    public static Date[] list2dates(List l) {
		Date[] arr = null;
		if(l != null && l.size() > 0) {
			arr = new Date[l.size()];
			for(int i = 0; i < l.size(); i++)
				arr[i] = (Date)l.get(i);
		}
		return arr;
	}
    
    /**
     * Converts a List of String to array
     * @param l List object
     * @return array of String objects
     */
    public static String[] list2strings(List l) {
		String[] arr = null;
		if(l != null && l.size() > 0) {
			arr = new String[l.size()];
			for(int i = 0; i < l.size(); i++)
				arr[i] = (String)l.get(i);
		}
		return arr;
	}
	
    public static List addObject(List l, Object o) {
    	if(l == null) 
    		l = new ArrayList();
    	l.add(o);
    	return l;
    }
    
    /**
     * Returns a MultiLangString from List
     * @param l List object
     * @param n index
     * @return MultiLangString object or null
     */
    public static MultiLangString getListObj(List l, int n) {
		if(l != null && n >= 0 && n < l.size()) 
			return (MultiLangString)l.get(n);
		else
			return null;
	}
    
    /**
     * Returns a String from List
     * @param l List object
     * @param n index
     * @return String object or null
     */
    public static String getListString(List l, int n) {
		if(l != null && n >= 0 && n < l.size()) 
			return (String)l.get(n);
		else
			return null;
	}
 
    /**
     * Checks if cert has certain key-usage bit set
     * @param cert certificate
     * @param nKu key-usage flag nr
     * @return true if set
     */
    public static boolean checkCertKeyUsage(X509Certificate cert, int nKu)
    {
    	if(cert != null) {
			boolean keyUsages[] = cert.getKeyUsage();
			if(keyUsages != null && nKu >= 0 && keyUsages.length > nKu && keyUsages[nKu] == true)
				return true;
		}
		return false;
    }
    
    /**
     * Checks if cert has non-repud bit set
     * @param cert certificate
     * @return true if set
     */
    public static boolean isSignatureCert(X509Certificate cert)
	{
		return checkCertKeyUsage(cert, 1);
	}
    
    /**
     * Checks if cert has data-encryption bit set
     * @param cert certificate
     * @return true if set
     */
	public static boolean isEncryptCert(X509Certificate cert)
	{
		return checkCertKeyUsage(cert, 2);
	}

    /**
     * Checks if cert has cert-signing (CA) bit set
     * @param cert certificate
     * @return true if set
     */
	public static boolean isCACert(X509Certificate cert)
	{
		return checkCertKeyUsage(cert, 5);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy