001    package org.apache.fulcrum.jce.crypto;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    
023    /**
024     * Helper class to for HEX conversion.
025     *
026     * The code uses parts from Markus Hahn's Blowfish library found at
027     * http://blowfishj.sourceforge.net/
028     *
029     * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl </a>
030     * @author <a href="mailto:maakus@earthlink.net">Markus Hahn</a>
031     */
032    
033    public final class HexConverter
034    {
035        /**
036         * Table for byte to hex conversion
037         */
038        final private static char[] HEXTAB =
039        {
040            '0', '1', '2', '3', '4', '5', '6', '7',
041            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
042        };
043    
044        /**
045         * Converts a byte array to a hex string.
046         *
047         * @param data the byte array
048         * @return the hex string
049         */
050        public static String toString( byte[] data )
051        {
052            return bytesToHexStr(data, 0, data.length);
053        }
054    
055        /**
056         * Converts a hex string into a byte[]
057         *
058         * @param data the hex string
059         * @return the byte[]
060         */
061    
062        public static byte[] toBytes( String data )
063        {
064            byte[] result = new byte[data.length()/2];
065            hexStrToBytes( data, result, 0, 0, result.length );
066            return result;
067        }
068    
069        /**
070         * Converts a byte array to a hex string.
071         * @param data the byte array
072         * @param nOfs start index where to get the bytes
073         * @param nLen number of bytes to convert
074         * @return the hex string
075         */
076        private static String bytesToHexStr(
077            byte[] data,
078            int nOfs,
079            int nLen)
080        {
081            StringBuffer sbuf;
082    
083            sbuf = new StringBuffer();
084            sbuf.setLength(nLen << 1);
085    
086            int nPos = 0;
087            int nC = nOfs + nLen;
088    
089            while (nOfs < nC)
090            {
091                sbuf.setCharAt(nPos++, HEXTAB[(data[nOfs  ] >> 4) & 0x0f]);
092                sbuf.setCharAt(nPos++, HEXTAB[ data[nOfs++]       & 0x0f]);
093            }
094    
095            return sbuf.toString();
096        }
097    
098        /**
099         * Converts a hex string back into a byte array (invalid codes will be
100         * skipped).
101         * @param sHex hex string
102         * @param data the target array
103         * @param nSrcOfs from which character in the string the conversion should
104         * begin, remember that (nSrcPos modulo 2) should equals 0 normally
105         * @param nDstOfs to store the bytes from which position in the array
106         * @param nLen number of bytes to extract
107         * @return number of extracted bytes
108         */
109        private static int hexStrToBytes(
110            String sHex,
111            byte[] data,
112            int nSrcOfs,
113            int nDstOfs,
114            int nLen)
115        {
116            int nI, nJ, nStrLen, nAvailBytes, nDstOfsBak;
117            byte bActByte;
118            boolean blConvertOK;
119    
120            // check for correct ranges
121    
122            nStrLen = sHex.length();
123    
124            nAvailBytes = (nStrLen - nSrcOfs) >> 1;
125            if (nAvailBytes < nLen)
126            {
127                nLen = nAvailBytes;
128            }
129    
130            int nOutputCapacity = data.length - nDstOfs;
131            if (nLen > nOutputCapacity)
132            {
133                nLen = nOutputCapacity;
134            }
135    
136            // convert now
137    
138            nDstOfsBak = nDstOfs;
139    
140            for (nI = 0; nI < nLen; nI++)
141            {
142                bActByte = 0;
143                blConvertOK = true;
144    
145                for (nJ = 0; nJ < 2; nJ++)
146                {
147                    bActByte <<= 4;
148                    char cActChar = sHex.charAt(nSrcOfs++);
149    
150                    if ((cActChar >= 'a') && (cActChar <= 'f'))
151                    {
152                        bActByte |= (byte) (cActChar - 'a') + 10;
153                    }
154                    else
155                    {
156                        if ((cActChar >= '0') && (cActChar <= '9'))
157                        {
158                            bActByte |= (byte) (cActChar - '0');
159                        }
160                        else
161                        {
162                            blConvertOK = false;
163                        }
164                    }
165                }
166                if (blConvertOK)
167                {
168                    data[nDstOfs++] = bActByte;
169                }
170            }
171    
172            return (nDstOfs - nDstOfsBak);
173        }
174    }