001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.crypto.digest;
023:
024: import java.io.ByteArrayOutputStream;
025: import java.security.MessageDigest;
026: import java.security.MessageDigestSpi;
027: import java.security.NoSuchAlgorithmException;
028: import java.security.ProviderException;
029: import java.util.Arrays;
030:
031: /** An alternate SHA Interleave algorithm as implemented in the SRP
032: distribution. This version reverses the even and odd byte streams before
033: performing the SHA digest.
034:
035: This product includes software developed by Tom Wu and Eugene
036: Jhong for the SRP Distribution (http://srp.stanford.edu/srp/).
037:
038: @author Scott.Stark@jboss.org
039: @version $Revision: 57203 $
040: */
041: public class SHAReverseInterleave extends MessageDigestSpi {
042: private static final int SHA_HASH_LEN = 20;
043:
044: private ByteArrayOutputStream evenBytes;
045: private ByteArrayOutputStream oddBytes;
046: private int count;
047: private boolean skipLeadingZeros;
048: private MessageDigest sha;
049:
050: /** Creates a new instance of SHAReverseInterleave
051: @exception ProviderException thrown if MessageDigest.getInstance("SHA")
052: throws a NoSuchAlgorithmException.
053: */
054: public SHAReverseInterleave() {
055: try {
056: sha = MessageDigest.getInstance("SHA");
057: } catch (NoSuchAlgorithmException e) {
058: throw new ProviderException(
059: "Failed to obtain SHA MessageDigest");
060: }
061: evenBytes = new ByteArrayOutputStream();
062: oddBytes = new ByteArrayOutputStream();
063: engineReset();
064: }
065:
066: protected int engineGetDigestLength() {
067: return 2 * SHA_HASH_LEN;
068: }
069:
070: /**
071: * Completes the digest computation by performing final
072: * operations such as padding. Once <code>engineDigest</code> has
073: * been called, the engine should be reset (see
074: * {@link #engineReset() engineReset}).
075: * Resetting is the responsibility of the
076: * engine implementor.
077: *
078: * @return the array of bytes for the resulting digest value.
079: */
080: protected byte[] engineDigest() {
081: byte[] E = evenBytes.toByteArray();
082: // If the count is odd, drop the first byte
083: int length = E.length;
084: if (count % 2 == 1)
085: length--;
086: // Reverse the order of the even bytes
087: byte[] tmp = new byte[length];
088: for (int i = 0; i < length; i++) {
089: tmp[i] = E[E.length - i - 1];
090: System.out.println("E[" + i + "] = " + tmp[i]);
091: }
092: E = tmp;
093: byte[] G = sha.digest(E);
094:
095: byte[] F = oddBytes.toByteArray();
096: // Reverse the order of the even bytes
097: tmp = new byte[F.length];
098: for (int i = 0; i < F.length; i++) {
099: tmp[i] = F[F.length - i - 1];
100: System.out.println("F[" + i + "] = " + tmp[i]);
101: }
102: F = tmp;
103: sha.reset();
104: byte[] H = sha.digest(F);
105: length = G.length + H.length;
106: byte[] digest = new byte[length];
107: for (int i = 0; i < G.length; ++i)
108: digest[2 * i] = G[i];
109: for (int i = 0; i < H.length; ++i)
110: digest[2 * i + 1] = H[i];
111: engineReset();
112: return digest;
113: }
114:
115: /**
116: * Resets the digest for further use.
117: */
118: protected void engineReset() {
119: skipLeadingZeros = true;
120: count = 0;
121: evenBytes.reset();
122: oddBytes.reset();
123: sha.reset();
124: }
125:
126: /**
127: * Updates the digest using the specified byte.
128: *
129: * @param input the byte to use for the update.
130: */
131: protected void engineUpdate(byte input) {
132: if (skipLeadingZeros == true && input == 0)
133: return;
134: skipLeadingZeros = false;
135: if (count % 2 == 0)
136: evenBytes.write(input);
137: else
138: oddBytes.write(input);
139: count++;
140: }
141:
142: /**
143: * Updates the digest using the specified array of bytes,
144: * starting at the specified offset.
145: *
146: * @param input the array of bytes to use for the update.
147: * @param offset the offset to start from in the array of bytes.
148: * @param len the input of bytes to use, starting at
149: * <code>offset</code>.
150: */
151: protected void engineUpdate(byte[] input, int offset, int len) {
152: for (int i = offset; i < offset + len; i++)
153: engineUpdate(input[i]);
154: }
155:
156: }
|