Methods Summary |
---|
public java.lang.Object | clone()Returns a new instance of the same class as the receiver, whose slots
have been filled in with the values in the slots of the receiver.
Classes which wish to support cloning must specify that they implement
the Cloneable interface, since the native implementation checks for this.
// Calling super takes care of primitive type slots
SHAOutputStream result = (SHAOutputStream) super.clone();
result.HConstants = this.HConstants.clone();
result.WArray = this.WArray.clone();
result.MArray = this.MArray.clone();
result.oneByte = this.oneByte.clone();
return result;
|
private void | copyToInternalBuffer(byte[] buffer, int off, int len)Copies a byte array into the receiver's internal buffer, making the
adjustments as necessary and keeping the receiver in a consistent state.
int index;
index = off;
for (int i = bytesToProcess; i < bytesToProcess + len; i++) {
MArray[i] = buffer[index];
index++;
}
bytesToProcess = bytesToProcess + len;
|
public int[] | getHash()Returns an int array (length = 5) with the SHA value of the bytes written
to the receiver.
this.padBuffer();
this.processBuffer();
int[] result = HConstants.clone();
// After the user asks for the hash value, the stream is put back to the
// initial state
reset();
return result;
|
public byte[] | getHashAsBytes()Returns a byte array (length = 20) with the SHA value of the bytes
written to the receiver.
byte[] hash = new byte[HashSizeInBytes];
this.padBuffer();
this.processBuffer();
// We need to return HConstants (modified by the loop) as an array of
// bytes. A memcopy would be the fastest.
for (int i = 0; i < (HashSizeInBytes / 4); ++i) {
hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff);
hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff);
hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff);
hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff);
}
// After the user asks for the hash value, the stream is put back to the
// initial state
reset();
return hash;
|
public byte[] | getHashAsBytes(boolean pad)Returns a byte array (length = 20) with the SHA value of the bytes
written to the receiver.
byte[] hash = new byte[HashSizeInBytes];
if (pad) {
this.padBuffer();
this.processBuffer();
}
// Convert HConstants to an array of bytes
for (int i = 0; i < (HashSizeInBytes / 4); i++) {
hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff);
hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff);
hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff);
hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff);
}
// After the user asks for the hash value, the stream is put back to the
// initial state
reset();
return hash;
|
private void | initialize()Initializes the receiver.
HConstants = new int[HConstantsSize];
MArray = new byte[BlockSizeInBytes];
WArray = new int[WArraySize];
|
private void | padBuffer()Adds extra bytes to the bit stream as required (see the SHA
specification).
long lengthInBits;
MArray[bytesToProcess] = (byte) 0x80;
for (int i = bytesToProcess + 1; i < BlockSizeInBytes; i++) {
MArray[i] = (byte) 0;
}
// Get length now because there might be extra padding (length in bits)
lengthInBits = (bytesToProcess + bytesProcessed) * 8;
// 9 extra bytes are needed: 1 for 1000... and 8 for length (long)
if ((bytesToProcess + 9) > BlockSizeInBytes) {
// Not enough space to append length. We need another block for
// padding
// Padding in this buffer only includes 1000000....
this.processBuffer();
// Now put 0's in all the buffer. memfill would be faster
for (int i = 0; i < BlockSizeInBytes; i++) {
MArray[i] = (byte) 0;
}
}
for (int i = 1; i < 9; i++) {
MArray[BlockSizeInBytes - i] = (byte) (lengthInBits & 0xff);
lengthInBits = lengthInBits >>> 8;
}
|
private void | processBuffer()Core SHA code. Processes the receiver's buffer of bits, computing the
values towards the final SHA
int A; // A variable, from spec
int B; // B variable, from spec
int C; // C variable, from spec
int D; // D variable, from spec
int E; // E variable, from spec
int temp; // TEMP, from spec
int t; // t, for iteration, from spec
for (t = 0; t <= 15; t++) { // step a, page 7 of spec. Here we convert 4
// bytes into 1 word, 16 times
WArray[t] = (MArray[4 * t] & 0xff) << 24
| ((MArray[4 * t + 1] & 0xff) << 16)
| ((MArray[4 * t + 2] & 0xff) << 8)
| (MArray[4 * t + 3] & 0xff);
}
for (t = 16; t <= 79; t++) { // step b, page 7 of spec
temp = (WArray[t - 3] ^ WArray[t - 8] ^ WArray[t - 14] ^ WArray[t - 16]);
temp = (temp << 1) | (temp >>> (32 - 1)); // element , Circular
// Shift Left by 1
WArray[t] = temp;
}
// step c, page 7 of spec
A = HConstants[0];
B = HConstants[1];
C = HConstants[2];
D = HConstants[3];
E = HConstants[4];
// step d, page 8 of spec
for (t = 0; t <= 19; t++) {
temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
temp = temp + E + WArray[t] + K0_19;
temp = temp + ((B & C) | (~B & D));
E = D;
D = C;
C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
B = A;
A = temp;
}
for (t = 20; t <= 39; t++) {
temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
temp = temp + E + WArray[t] + K20_39;
temp = temp + (B ^ C ^ D);
E = D;
D = C;
C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
B = A;
A = temp;
}
for (t = 40; t <= 59; t++) {
temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
temp = temp + E + WArray[t] + K40_59;
temp = temp + ((B & C) | (B & D) | (C & D));
E = D;
D = C;
C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
B = A;
A = temp;
}
for (t = 60; t <= 79; t++) {
temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
temp = temp + E + WArray[t] + K60_79;
temp = temp + (B ^ C ^ D);
E = D;
D = C;
C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
B = A;
A = temp;
}
// step e, page 8 of spec
HConstants[0] = HConstants[0] + A;
HConstants[1] = HConstants[1] + B;
HConstants[2] = HConstants[2] + C;
HConstants[3] = HConstants[3] + D;
HConstants[4] = HConstants[4] + E;
// Update number of bytes actually processed
bytesProcessed = bytesProcessed + BlockSizeInBytes;
bytesToProcess = 0; // No pending bytes in the block
|
public void | reset()Reset this SHAOutputStream to the state it was before any byte was
written to it.
HConstants[0] = H0;
HConstants[1] = H1;
HConstants[2] = H2;
HConstants[3] = H3;
HConstants[4] = H4;
bytesProcessed = 0;
bytesToProcess = 0;
|
public java.lang.String | toString()
return this.getClass().getName() + ':" + toStringBlock(getHashAsBytes());
|
private static java.lang.String | toStringBlock(byte[] block)Converts a block to a String representation.
return toStringBlock(block, 0, block.length);
|
private static java.lang.String | toStringBlock(byte[] block, int off, int len)Converts a block to a String representation.
String hexdigits = "0123456789ABCDEF";
StringBuilder buf = new StringBuilder();
buf.append('[");
for (int i = off; i < off + len; ++i) {
buf.append(hexdigits.charAt((block[i] >>> 4) & 0xf));
buf.append(hexdigits.charAt(block[i] & 0xf));
}
buf.append(']");
return buf.toString();
|
public void | write(byte[] buffer, int off, int len)Writes len bytes from this byte array
buffer starting at offset off to the
SHAOutputStream. The internal buffer used to compute SHA is updated, and
the incremental computation of SHA is also performed.
int spaceLeft;
int start;
int bytesLeft;
spaceLeft = BlockSizeInBytes - bytesToProcess;
if (len < spaceLeft) { // Extra bytes are not enough to fill buffer
this.copyToInternalBuffer(buffer, off, len);
return;
}
// Extra bytes are bigger than space in buffer. Process buffer multiple
// times
this.copyToInternalBuffer(buffer, off, spaceLeft);
bytesLeft = len - spaceLeft;
this.processBuffer();
start = off + spaceLeft;
while (bytesLeft >= BlockSizeInBytes) {
this.copyToInternalBuffer(buffer, start, BlockSizeInBytes);
bytesLeft = bytesLeft - BlockSizeInBytes;
this.processBuffer();
start = start + BlockSizeInBytes;
}
if (bytesLeft > 0) {
// Extra bytes at the end, not enough to fill buffer
this.copyToInternalBuffer(buffer, start, bytesLeft);
}
|
public void | write(int b)Writes the specified byte b to this OutputStream. Only the
low order byte of b is written.
// Not thread-safe because we use a shared one-byte buffer
oneByte[0] = (byte) b;
write(oneByte, 0, 1);
|