Index: modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java =================================================================== --- modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java (revision 440010) +++ modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java (working copy) @@ -14,11 +14,7 @@ * limitations under the License. */ -/* - * TODO to add writeObject(ObjectOutputStream) and readObject(ObjectInputStream) for optimal serialization - */ - package org.apache.harmony.security.provider.crypto; import java.security.InvalidParameterException; @@ -28,6 +24,9 @@ import org.apache.harmony.security.provider.crypto.SHA1Impl; import java.io.Serializable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; /** @@ -409,4 +408,125 @@ } + private void writeObject(ObjectOutputStream oos) throws IOException { + + int[] intData = null; + + final int only_hash = EXTRAFRAME_OFFSET; + final int hashes_and_frame = EXTRAFRAME_OFFSET*2 + FRAME_LENGTH; + final int hashes_and_frame_extra = EXTRAFRAME_OFFSET*2 + FRAME_LENGTH*2; + + oos.writeLong(seedLength); + oos.writeLong(counter); + oos.writeInt(state); + oos.writeInt(seed[BYTES_OFFSET]); + + int nRemaining = (seed[BYTES_OFFSET] +3) >> 2; // converting bytes in words + // result may be 0 + if ( state != NEXT_BYTES ) { + + // either the state is UNDEFINED or previous method was "setSeed(..)" + // so in "seed[]" to serialize are remaining bytes (seed[0-nRemaining]) and + // current hash (seed[82-86]) + + intData = new int[only_hash + nRemaining]; + + System.arraycopy(seed, 0, intData, 0, nRemaining); + System.arraycopy(seed, HASH_OFFSET, intData, nRemaining, EXTRAFRAME_OFFSET ); + + } else { + // previous method was "nextBytes(..)" + // so, data to serialize are all the above (two first are in "copies" array) + // and current words in both frame and extra frame (as if) + + int offset = 0; + if ( seed[BYTES_OFFSET] < MAX_BYTES ) { // no extra frame + + intData = new int[hashes_and_frame + nRemaining]; + + } else { // extra frame is used + + intData = new int[hashes_and_frame_extra + nRemaining]; + + intData[offset] = seed[FRAME_LENGTH]; + intData[offset +1] = seed[FRAME_LENGTH +1]; + intData[offset +2] = seed[FRAME_LENGTH +14]; + intData[offset +3] = seed[FRAME_LENGTH +15]; + offset += 4; + } + + System.arraycopy(seed, 0, intData, offset, FRAME_LENGTH); + offset += FRAME_LENGTH; + + System.arraycopy(copies, FRAME_LENGTH + EXTRAFRAME_OFFSET, + intData, offset, nRemaining); + offset += nRemaining; + + System.arraycopy(copies, 0, intData, offset, EXTRAFRAME_OFFSET ); + offset += EXTRAFRAME_OFFSET; + + System.arraycopy(seed, HASH_OFFSET, intData, offset, EXTRAFRAME_OFFSET ); + } + for ( int i = 0 ; i < intData.length; i++ ) { + oos.writeInt( intData[i]); + } + + oos.writeInt(nextBIndex); + oos.write(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex ); + } + + + private void readObject(ObjectInputStream ois) throws IOException, + ClassNotFoundException { + + seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET]; + copies = new int[2*FRAME_LENGTH + EXTRAFRAME_OFFSET]; + nextBytes = new byte[DIGEST_LENGTH]; + + seedLength = ois.readLong(); + counter = ois.readLong(); + state = ois.readInt(); + seed[BYTES_OFFSET] = ois.readInt(); + + int nRemaining = (seed[BYTES_OFFSET] +3) >> 2; // converting bytes in words + + if ( state != NEXT_BYTES ) { + + for ( int i = 0 ; i < nRemaining ; i++ ) { + seed[i] = ois.readInt(); + } + for ( int i = 0 ; i < EXTRAFRAME_OFFSET ; i++ ) { + seed[HASH_OFFSET +i] = ois.readInt(); + } + } else { + if ( seed[BYTES_OFFSET] >= MAX_BYTES ) { + + // reading next bytes in seed extra frame + seed[FRAME_LENGTH] = ois.readInt(); + seed[FRAME_LENGTH +1] = ois.readInt(); + seed[FRAME_LENGTH +14] = ois.readInt(); + seed[FRAME_LENGTH +15] = ois.readInt(); + } + // reading next bytes in seed frame + for (int i = 0; i < FRAME_LENGTH; i++ ) { + seed[i] = ois.readInt(); + } + // reading remaining seed bytes + for (int i = 0; i < nRemaining; i++) { + copies[FRAME_LENGTH + EXTRAFRAME_OFFSET +i] = ois.readInt(); + } + // reading copy of current hash + for (int i = 0; i < EXTRAFRAME_OFFSET; i++) { + copies[i] = ois.readInt(); + } + // reading current hash + for (int i = 0; i < EXTRAFRAME_OFFSET; i++) { + seed[HASH_OFFSET + i] = ois.readInt(); + } + } + + nextBIndex = ois.readInt(); + ois.read(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex ); + } + }