public int engineDigest(byte[] hashvalue, int offset, final int len)
            throws DigestException {
        if (len >= HASH_LENGTH) {
            if (hashvalue.length - offset >= HASH_LENGTH) {
                /* Flush the trailing bytes, adding padding bytes into last
                 * blocks. */
                int i;
                /* Add padding null bytes but replace the last 8 padding bytes
                 * by the little-endian 64-bit digested message bit-length. */
                pad[i = padding] = (byte)0x80; /* required 1st padding byte */
                /* Check if 8 bytes available in pad to store the total
                 * message size */
                switch (i) { /* INVARIANT: i must be in [0..63] */
                case 52: pad[53] = (byte)0x00; /* no break; falls thru */
                case 53: pad[54] = (byte)0x00; /* no break; falls thru */
                case 54: pad[55] = (byte)0x00; /* no break; falls thru */
                case 55: break;
                case 56: pad[57] = (byte)0x00; /* no break; falls thru */
                case 57: pad[58] = (byte)0x00; /* no break; falls thru */
                case 58: pad[59] = (byte)0x00; /* no break; falls thru */
                case 59: pad[60] = (byte)0x00; /* no break; falls thru */
                case 60: pad[61] = (byte)0x00; /* no break; falls thru */
                case 61: pad[62] = (byte)0x00; /* no break; falls thru */
                case 62: pad[63] = (byte)0x00; /* no break; falls thru */
                case 63:
                    computeBlock(pad, 0);
                    /* Clear the 56 first bytes of pad[]. */
                    i = 52;
                    do {
                        pad[i    ] = (byte)0x00;
                        pad[i + 1] = (byte)0x00;
                        pad[i + 2] = (byte)0x00;
                        pad[i + 3] = (byte)0x00;
                    } while ((i -= 4) >= 0);
                    break;
                default:
                    /* Clear the rest of 56 first bytes of pad[]. */
                    switch (i & 3) {
                    case 3: i++;
                            break;
                    case 2: pad[(i += 2) - 1] = (byte)0x00;
                            break;
                    case 1: pad[(i += 3) - 2] = (byte)0x00;
                            pad[ i       - 1] = (byte)0x00;
                            break;
                    case 0: pad[(i += 4) - 3] = (byte)0x00;
                            pad[ i       - 2] = (byte)0x00;
                            pad[ i       - 1] = (byte)0x00;
                    }
                    do {
                        pad[i    ] = (byte)0x00;
                        pad[i + 1] = (byte)0x00;
                        pad[i + 2] = (byte)0x00;
                        pad[i + 3] = (byte)0x00;
                    } while ((i += 4) < 56);
                }
                /* Convert the message size from bytes to big-endian bits. */
                pad[56] = (byte)((i = (int)(bytes >>> 29)) >> 24);
                pad[57] = (byte)(i >>> 16);
                pad[58] = (byte)(i >>> 8);
                pad[59] = (byte)i;
                pad[60] = (byte)((i = (int)bytes << 3) >> 24);
                pad[61] = (byte)(i >>> 16);
                pad[62] = (byte)(i >>> 8);
                pad[63] = (byte)i;
                computeBlock(pad, 0);
                /* Return the computed digest in big-endian byte order. */
                hashvalue[offset     ] = (byte)((i = hA) >>> 24);
                hashvalue[offset +  1] = (byte)(i >>> 16);
                hashvalue[offset +  2] = (byte)(i >>> 8);
                hashvalue[offset +  3] = (byte)i;
                hashvalue[offset +  4] = (byte)((i = hB) >>> 24);
                hashvalue[offset += 5] = (byte)(i >>> 16);
                hashvalue[offset +  1] = (byte)(i >>> 8);
                hashvalue[offset +  2] = (byte)i;
                hashvalue[offset +  3] = (byte)((i = hC) >>> 24);
                hashvalue[offset +  4] = (byte)(i >>> 16);
                hashvalue[offset += 5] = (byte)(i >>> 8);
                hashvalue[offset +  1] = (byte)i;
                hashvalue[offset +  2] = (byte)((i = hD) >>> 24);
                hashvalue[offset +  3] = (byte)(i >>> 16);
                hashvalue[offset +  4] = (byte)(i >>> 8);
                hashvalue[offset += 5] = (byte)i;
                hashvalue[offset +  1] = (byte)((i = hE) >>> 24);
                hashvalue[offset +  2] = (byte)(i >>> 16);
                hashvalue[offset +  3] = (byte)(i >>> 8);
                hashvalue[offset +  4] = (byte)i;
                engineReset(); /* clear the evidence */
                return HASH_LENGTH;
            }
            throw new DigestException(
                "insufficient space in output buffer to store the digest");
        }
        throw new DigestException("partial digests not returned");
    }
public int engineDigest ( byte [ ] hashvalue , int offset , final int len ) throws DigestException { if ( len >= HASH_LENGTH ) { if ( hashvalue . length - offset >= HASH_LENGTH ) { int i ; pad [ i = padding ] = ( byte ) 0x80 ; switch ( i ) { case 52 : pad [ 53 ] = ( byte ) 0x00 ; case 53 : pad [ 54 ] = ( byte ) 0x00 ; case 54 : pad [ 55 ] = ( byte ) 0x00 ; case 55 : break ; case 56 : pad [ 57 ] = ( byte ) 0x00 ; case 57 : pad [ 58 ] = ( byte ) 0x00 ; case 58 : pad [ 59 ] = ( byte ) 0x00 ; case 59 : pad [ 60 ] = ( byte ) 0x00 ; case 60 : pad [ 61 ] = ( byte ) 0x00 ; case 61 : pad [ 62 ] = ( byte ) 0x00 ; case 62 : pad [ 63 ] = ( byte ) 0x00 ; case 63 : computeBlock ( pad , 0 ) ; i = 52 ; do { pad [ i ] = ( byte ) 0x00 ; pad [ i + 1 ] = ( byte ) 0x00 ; pad [ i + 2 ] = ( byte ) 0x00 ; pad [ i + 3 ] = ( byte ) 0x00 ; } while ( ( i -= 4 ) >= 0 ) ; break ; default : switch ( i & 3 ) { case 3 : i ++ ; break ; case 2 : pad [ ( i += 2 ) - 1 ] = ( byte ) 0x00 ; break ; case 1 : pad [ ( i += 3 ) - 2 ] = ( byte ) 0x00 ; pad [ i - 1 ] = ( byte ) 0x00 ; break ; case 0 : pad [ ( i += 4 ) - 3 ] = ( byte ) 0x00 ; pad [ i - 2 ] = ( byte ) 0x00 ; pad [ i - 1 ] = ( byte ) 0x00 ; } do { pad [ i ] = ( byte ) 0x00 ; pad [ i + 1 ] = ( byte ) 0x00 ; pad [ i + 2 ] = ( byte ) 0x00 ; pad [ i + 3 ] = ( byte ) 0x00 ; } while ( ( i += 4 ) < 56 ) ; } pad [ 56 ] = ( byte ) ( ( i = ( int ) ( bytes > > > 29 ) ) > > 24 ) ; pad [ 57 ] = ( byte ) ( i > > > 16 ) ; pad [ 58 ] = ( byte ) ( i > > > 8 ) ; pad [ 59 ] = ( byte ) i ; pad [ 60 ] = ( byte ) ( ( i = ( int ) bytes << 3 ) > > 24 ) ; pad [ 61 ] = ( byte ) ( i > > > 16 ) ; pad [ 62 ] = ( byte ) ( i > > > 8 ) ; pad [ 63 ] = ( byte ) i ; computeBlock ( pad , 0 ) ; hashvalue [ offset ] = ( byte ) ( ( i = hA ) > > > 24 ) ; hashvalue [ offset + 1 ] = ( byte ) ( i > > > 16 ) ; hashvalue [ offset + 2 ] = ( byte ) ( i > > > 8 ) ; hashvalue [ offset + 3 ] = ( byte ) i ; hashvalue [ offset + 4 ] = ( byte ) ( ( i = hB ) > > > 24 ) ; hashvalue [ offset += 5 ] = ( byte ) ( i > > > 16 ) ; hashvalue [ offset + 1 ] = ( byte ) ( i > > > 8 ) ; hashvalue [ offset + 2 ] = ( byte ) i ; hashvalue [ offset + 3 ] = ( byte ) ( ( i = hC ) > > > 24 ) ; hashvalue [ offset + 4 ] = ( byte ) ( i > > > 16 ) ; hashvalue [ offset += 5 ] = ( byte ) ( i > > > 8 ) ; hashvalue [ offset + 1 ] = ( byte ) i ; hashvalue [ offset + 2 ] = ( byte ) ( ( i = hD ) > > > 24 ) ; hashvalue [ offset + 3 ] = ( byte ) ( i > > > 16 ) ; hashvalue [ offset + 4 ] = ( byte ) ( i > > > 8 ) ; hashvalue [ offset += 5 ] = ( byte ) i ; hashvalue [ offset + 1 ] = ( byte ) ( ( i = hE ) > > > 24 ) ; hashvalue [ offset + 2 ] = ( byte ) ( i > > > 16 ) ; hashvalue [ offset + 3 ] = ( byte ) ( i > > > 8 ) ; hashvalue [ offset + 4 ] = ( byte ) i ; engineReset ( ) ; return HASH_LENGTH ; } throw new DigestException ( "insufficient space in output buffer to store the digest" ) ; } throw new DigestException ( "partial digests not returned" ) ; }
Completes the hash computation by performing final operations
such as padding. Once engineDigest has been called, the engine
will be automatically reset (see engineReset).

Overrides the protected abstract method of
java.security.MessageDigestSpi.
@param hashvalue  the output buffer in which to store the digest.
@param offset  offset to start from in the output buffer
@param len  number of bytes within buf allotted for the digest.
Both this default implementation and the SUN provider
do not return partial digests.  The presence of this
parameter is solely for consistency in our API's.
If the value of this parameter is less than the
actual digest length, the method will throw a
DigestException.  This parameter is ignored if its
value is greater than or equal to the actual digest
length.
@return  the length of the digest stored in the output buffer.