FileDocCategorySizeDatePackage
SHA1_MessageDigestImpl.javaAPI DocAndroid 1.5 API11055Wed May 06 22:41:06 BST 2009org.apache.harmony.security.provider.crypto

SHA1_MessageDigestImpl

public class SHA1_MessageDigestImpl extends MessageDigestSpi implements org.apache.harmony.security.provider.crypto.SHA1_Data, Cloneable
This class extends the MessageDigestSpi class implementing all its abstract methods; it overrides the "Object clone()" and "int engineGetDigestLength()" methods.
The class implements the Cloneable interface.

Fields Summary
private int[]
buffer
private byte[]
oneByte
private int
messageLength
Constructors Summary
public SHA1_MessageDigestImpl()
The constructor creates needed buffers and sets the engine at initial state


        // BYTES_OFFSET +6 is minimal length required by methods in SHA1Impl
        buffer  = new int[BYTES_OFFSET +6];

        oneByte = new byte[1];

        engineReset();
    
Methods Summary
public java.lang.Objectclone()
Returns a "deep" copy of this SHA1MDImpl object.
The method overrides "clone()" in class Object.

return
a clone of this object


        SHA1_MessageDigestImpl cloneObj = (SHA1_MessageDigestImpl) super.clone();

        cloneObj.buffer  = ( int[])buffer.clone();
        cloneObj.oneByte = (byte[])oneByte.clone();

        return cloneObj;
    
protected byte[]engineDigest()
Computes a message digest value.
The method resets the engine.
The method overrides "engineDigest()" in class MessageDigestSpi.

return
byte array containing message digest value


        byte[] hash = new byte[DIGEST_LENGTH];

        processDigest(hash, 0);
        return hash;
    
protected intengineDigest(byte[] buf, int offset, int len)
Computes message digest value. Upon return, the value is stored in "buf" buffer beginning "offset" byte.
The method resets the engine.
The method overrides "engineDigest(byte[],int,int) in class MessageDigestSpi.

param
buf byte array to store a message digest returned
param
offset a position in the array for first byte of the message digest
param
len number of bytes within buffer allotted for the message digest; as this implementation doesn't provide partial digests, len should be >= 20, DigestException is thrown otherwise
return
the length of the message digest stored in the "buf" buffer; in this implementation the length=20
throws
IllegalArgumentException if null is passed to the "buf" argument
if offset + len > buf.length
if offset > buf.length or len > buf.length
throws
DigestException if len < 20
throws
ArrayIndexOutOfBoundsException if offset < 0

 

        if ( buf == null ) {
            throw new IllegalArgumentException(Messages.getString("security.162"));  //$NON-NLS-1$
        }
        if ( offset > buf.length || len > buf.length || (len + offset) > buf.length ) {
            throw new IllegalArgumentException(
               Messages.getString("security.163")); //$NON-NLS-1$
        }
        if ( len < DIGEST_LENGTH ) {
            throw new DigestException(Messages.getString("security.164")); //$NON-NLS-1$
        }
        if ( offset < 0 ) {
            throw new ArrayIndexOutOfBoundsException(Messages.getString("security.165", offset)); //$NON-NLS-1$
        }

        processDigest(buf, offset);

        return DIGEST_LENGTH;
    
protected intengineGetDigestLength()
Returns a message digest length.
The method overrides "engineGetDigestLength()" in class MessageDigestSpi.

return
total length of current message digest as an int value

 
        return DIGEST_LENGTH; 
    
protected voidengineReset()
Resets the engine.
The method overrides "engineReset()" in class MessageDigestSpi.


        messageLength = 0;

        buffer[BYTES_OFFSET] = 0;
        buffer[HASH_OFFSET   ] = H0;
        buffer[HASH_OFFSET +1] = H1;
        buffer[HASH_OFFSET +2] = H2;
        buffer[HASH_OFFSET +3] = H3;
        buffer[HASH_OFFSET +4] = H4;
    
protected voidengineUpdate(byte input)
Supplements a byte to current message.
The method overrides "engineUpdate(byte)" in class MessageDigestSpi.

param
input byte to add to current message


        oneByte[0] = input;
        SHA1Impl.updateHash( buffer, oneByte, 0, 0 );
        messageLength++;
    
protected voidengineUpdate(byte[] input, int offset, int len)
Updates current message.
The method overrides "engineUpdate(byte[],int,int)" in class MessageDigestSpi.
The method silently returns if "len" <= 0.

param
input a byte array
param
offset a number of first byte in the "input" array to use for updating
param
len a number of bytes to use
throws
NullPointerException if null is passed to the "buf" argument
throws
IllegalArgumentException if offset > buf.length or len > buf.length or (len + offset) > buf.length
throws
ArrayIndexOutOfBoundsException offset < 0


        if ( input == null ) {
            throw new IllegalArgumentException(Messages.getString("security.166"));  //$NON-NLS-1$
        }
        if ( len <= 0 ) {
            return;
        }
        if ( offset < 0 ) {
            throw new ArrayIndexOutOfBoundsException(Messages.getString("security.165", offset)); //$NON-NLS-1$
        }
        if ( offset > input.length || len > input.length || (len + offset) > input.length ) {
            throw new IllegalArgumentException(
               Messages.getString("security.167")); //$NON-NLS-1$
        }

        SHA1Impl.updateHash(buffer, input, offset, offset + len -1 );
        messageLength += len;
    
private voidprocessDigest(byte[] digest, int offset)
The method performs final actions and invokes the "computeHash(int[])" method. In case if there is no enough words in current frame after processing its data, extra frame is prepared and the "computeHash(int[])" method is invoked second time.
After processing, the method resets engine's state

param
digest - byte array
param
offset - offset in digest


        int i, j;         // implementation variables
        int lastWord;     //

        long nBits = messageLength <<3 ;  // length has to be calculated before padding

        engineUpdate( (byte) 0x80 );      // beginning byte in padding

        i = 0;                     // i contains number of beginning word for following loop

        lastWord = (buffer[BYTES_OFFSET] + 3)>>2 ;  // computing of # of full words by shifting
                                                    // # of bytes

        // possible cases:
        //
        // - buffer[BYTES_OFFSET] == 0 - buffer frame is empty, 
        //                         padding byte was 64th in previous frame
        //                         current frame should contain only message's length
        //
        // - lastWord < 14 - two last, these are 14 & 15, words in 16 word frame are free;
        //                   no extra frame needed
        // - lastWord = 14 - only one last, namely 15-th, word in frame doesn't contain bytes;
        //                   extra frame is needed
        // - lastWord > 14 - last word in frame is not full; 
        //                   extra frame is needed

        if ( buffer[BYTES_OFFSET] != 0 ) {

            if ( lastWord < 15 ) {
                i = lastWord;
            } else {
                if ( lastWord == 15 ) {
                    buffer[15] = 0;       // last word in frame is set to "0"
                }
                SHA1Impl.computeHash(buffer);
                i = 0;
            }
        }
        Arrays.fill(buffer, i, 14, 0);

        buffer[14] = (int)( nBits >>>32 );
        buffer[15] = (int)( nBits & 0xFFFFFFFF );
        SHA1Impl.computeHash(buffer);

        // converting 5-word frame into 20 bytes
        j = offset;
        for ( i = HASH_OFFSET; i < HASH_OFFSET +5; i++ ) {
            int k = buffer[i];
            digest[j  ] = (byte) ( k >>>24 );   // getting first  byte from left
            digest[j+1] = (byte) ( k >>>16 );   // getting second byte from left
            digest[j+2] = (byte) ( k >>> 8 );   // getting third  byte from left
            digest[j+3] = (byte) ( k       );   // getting fourth byte from left
            j += 4;
        }

        engineReset();