001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.util.crypto.digests; 019 020 import org.apache.geronimo.util.crypto.ExtendedDigest; 021 022 /** 023 * base implementation of MD4 family style digest as outlined in 024 * "Handbook of Applied Cryptography", pages 344 - 347. 025 */ 026 public abstract class GeneralDigest 027 implements ExtendedDigest 028 { 029 private static final int BYTE_LENGTH = 64; 030 private byte[] xBuf; 031 private int xBufOff; 032 033 private long byteCount; 034 035 /** 036 * Standard constructor 037 */ 038 protected GeneralDigest() 039 { 040 xBuf = new byte[4]; 041 xBufOff = 0; 042 } 043 044 /** 045 * Copy constructor. We are using copy constructors in place 046 * of the Object.clone() interface as this interface is not 047 * supported by J2ME. 048 */ 049 protected GeneralDigest(GeneralDigest t) 050 { 051 xBuf = new byte[t.xBuf.length]; 052 System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); 053 054 xBufOff = t.xBufOff; 055 byteCount = t.byteCount; 056 } 057 058 public void update( 059 byte in) 060 { 061 xBuf[xBufOff++] = in; 062 063 if (xBufOff == xBuf.length) 064 { 065 processWord(xBuf, 0); 066 xBufOff = 0; 067 } 068 069 byteCount++; 070 } 071 072 public void update( 073 byte[] in, 074 int inOff, 075 int len) 076 { 077 // 078 // fill the current word 079 // 080 while ((xBufOff != 0) && (len > 0)) 081 { 082 update(in[inOff]); 083 084 inOff++; 085 len--; 086 } 087 088 // 089 // process whole words. 090 // 091 while (len > xBuf.length) 092 { 093 processWord(in, inOff); 094 095 inOff += xBuf.length; 096 len -= xBuf.length; 097 byteCount += xBuf.length; 098 } 099 100 // 101 // load in the remainder. 102 // 103 while (len > 0) 104 { 105 update(in[inOff]); 106 107 inOff++; 108 len--; 109 } 110 } 111 112 public void finish() 113 { 114 long bitLength = (byteCount << 3); 115 116 // 117 // add the pad bytes. 118 // 119 update((byte)128); 120 121 while (xBufOff != 0) 122 { 123 update((byte)0); 124 } 125 126 processLength(bitLength); 127 128 processBlock(); 129 } 130 131 public void reset() 132 { 133 byteCount = 0; 134 135 xBufOff = 0; 136 for (int i = 0; i < xBuf.length; i++) 137 { 138 xBuf[i] = 0; 139 } 140 } 141 142 public int getByteLength() 143 { 144 return BYTE_LENGTH; 145 } 146 147 protected abstract void processWord(byte[] in, int inOff); 148 149 protected abstract void processLength(long bitLength); 150 151 protected abstract void processBlock(); 152 }