SHA1PRNG_SecureRandomImpl.java revision 897538a36c18f4db8f9f68ee566aec0bda842e9f
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.security.provider.crypto;
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.InvalidParameterException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.SecureRandomSpi;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.crypto.RandomBitsSupplier;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.crypto.SHA1Impl;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class extends the SecureRandomSpi class implementing all its abstract methods. <BR>
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <BR>
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * To generate pseudo-random bits, the implementation uses technique described in
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the "Random Number Generator (RNG) algorithms" section, Appendix A,
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * JavaTM Cryptography Architecture, API Specification&Reference <BR>
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <BR>
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The class implements the Serializable interface.
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Serializable, SHA1_Data {
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 283736797212159675L;
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // constants to use in expressions operating on bytes in int and long variables:
48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // END_FLAGS - final bytes in words to append to message;
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             see "ch.5.1 Padding the Message, FIPS 180-2"
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // RIGHT1    - shifts to right for left half of long
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // RIGHT2    - shifts to right for right half of long
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // LEFT      - shifts to left for bytes
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // MASK      - mask to select counter's bytes after shift to right
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] END_FLAGS = { 0x80000000, 0x800000, 0x8000, 0x80 };
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] RIGHT1 = { 0, 40, 48, 56 };
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] RIGHT2 = { 0, 8, 16, 24 };
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] LEFT = { 0, 24, 16, 8 };
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] MASK = { 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF,
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            0x000000FF };
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // HASHBYTES_TO_USE defines # of bytes returned by "computeHash(byte[])"
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // to use to form byte array returning by the "nextBytes(byte[])" method
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Note, that this implementation uses more bytes than it is defined
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // in the above specification.
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int HASHBYTES_TO_USE = 20;
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // value of 16 defined in the "SECURE HASH STANDARD", FIPS PUB 180-2
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int FRAME_LENGTH = 16;
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // miscellaneous constants defined in this implementation:
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // COUNTER_BASE - initial value to set to "counter" before computing "nextBytes(..)";
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                note, that the exact value is not defined in STANDARD
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // HASHCOPY_OFFSET   - offset for copy of current hash in "copies" array
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // EXTRAFRAME_OFFSET - offset for extra frame in "copies" array;
80f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //                     as the extra frame follows the current hash frame,
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                     EXTRAFRAME_OFFSET is equal to length of current hash frame
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // FRAME_OFFSET      - offset for frame in "copies" array
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // MAX_BYTES - maximum # of seed bytes processing which doesn't require extra frame
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             see (1) comments on usage of "seed" array below and
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             (2) comments in "engineNextBytes(byte[])" method
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // UNDEFINED  - three states of engine; initially its state is "UNDEFINED"
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // SET_SEED     call to "engineSetSeed"  sets up "SET_SEED" state,
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // NEXT_BYTES   call to "engineNextByte" sets up "NEXT_BYTES" state
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int COUNTER_BASE = 0;
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int HASHCOPY_OFFSET = 0;
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int EXTRAFRAME_OFFSET = 5;
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int FRAME_OFFSET = 21;
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int MAX_BYTES = 48;
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int UNDEFINED = 0;
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int SET_SEED = 1;
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int NEXT_BYTES = 2;
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static SHA1PRNG_SecureRandomImpl myRandom;
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
109f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // Structure of "seed" array:
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // -  0-79 - words for computing hash
111f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // - 80    - unused
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 81    - # of seed bytes in current seed frame
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 82-86 - 5 words, current seed hash
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int seed[];
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // total length of seed bytes, including all processed
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient long seedLength;
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Structure of "copies" array
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // -  0-4  - 5 words, copy of current seed hash
121f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // -  5-20 - extra 16 words frame;
122f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //           is used if final padding exceeds 512-bit length
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 21-36 - 16 word frame to store a copy of remaining bytes
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int copies[];
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ready "next" bytes; needed because words are returned
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient byte nextBytes[];
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // index of used bytes in "nextBytes" array
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int nextBIndex;
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // variable required according to "SECURE HASH STANDARD"
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient long counter;
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
135f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // contains int value corresponding to engine's current state
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int state;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The "seed" array is used to compute both "current seed hash" and "next bytes".
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // As the "SHA1" algorithm computes a hash of entire seed by splitting it into
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // a number of the 512-bit length frames (512 bits = 64 bytes = 16 words),
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // "current seed hash" is a hash (5 words, 20 bytes) for all previous full frames;
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // remaining bytes are stored in the 0-15 word frame of the "seed" array.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // As for calculating "next bytes",
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // both remaining bytes and "current seed hash" are used,
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // to preserve the latter for following "setSeed(..)" commands,
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the following technique is used:
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - upon getting "nextBytes(byte[])" invoked, single or first in row,
150f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //   which requires computing new hash, that is,
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //   there is no more bytes remaining from previous "next bytes" computation,
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //   remaining bytes are copied into the 21-36 word frame of the "copies" array;
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - upon getting "setSeed(byte[])" invoked, single or first in row,
154f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //   remaining bytes are copied back.
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  Creates object and sets implementation variables to their initial values
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SHA1PRNG_SecureRandomImpl() {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET] = H0;
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 1] = H1;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 2] = H2;
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 3] = H3;
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 4] = H4;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength = 0;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBytes = new byte[DIGEST_LENGTH];
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBIndex = HASHBYTES_TO_USE;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        counter = COUNTER_BASE;
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = UNDEFINED;
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method invokes the SHA1Impl's "updateHash(..)" method
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to update current seed frame and
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to compute new intermediate hash value if the frame is full.
180f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * After that it computes a length of whole seed.
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void updateSeed(byte[] bytes) {
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // on call:   "seed" contains current bytes and current hash;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // on return: "seed" contains new current bytes and possibly new current hash
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //            if after adding, seed bytes overfill its buffer
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SHA1Impl.updateHash(seed, bytes, 0, bytes.length - 1);
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength += bytes.length;
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Changes current seed by supplementing a seed argument to the current seed,
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if this already set;
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the argument is used as first seed otherwise. <BR>
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides "engineSetSeed(byte[])" in class SecureRandomSpi.
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       seed - byte array
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       NullPointerException - if null is passed to the "seed" argument
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void engineSetSeed(byte[] seed) {
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (seed == null) {
208897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("seed == null");
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state == NEXT_BYTES) { // first setSeed after NextBytes; restoring hash
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, HASHCOPY_OFFSET, this.seed, HASH_OFFSET,
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = SET_SEED;
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (seed.length != 0) {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            updateSeed(seed);
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a required number of random bytes. <BR>
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides "engineGenerateSeed (int)" in class SecureRandomSpi. <BR>
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       numBytes - number of bytes to return; should be >= 0.
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       byte array containing bits in order from left to right
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       InvalidParameterException - if numBytes < 0
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected byte[] engineGenerateSeed(int numBytes) {
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] myBytes; // byte[] for bytes returned by "nextBytes()"
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (numBytes < 0) {
239897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NegativeArraySizeException(Integer.toString(numBytes));
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (numBytes == 0) {
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new byte[0];
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (myRandom == null) {
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            myRandom = new SHA1PRNG_SecureRandomImpl();
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            myRandom.engineSetSeed(RandomBitsSupplier
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .getRandomBits(DIGEST_LENGTH));
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myBytes = new byte[numBytes];
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myRandom.engineNextBytes(myBytes);
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return myBytes;
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Writes random bytes into an array supplied.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Bits in a byte are from left to right. <BR>
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * To generate random bytes, the "expansion of source bits" method is used,
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that is,
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the current seed with a 64-bit counter appended is used to compute new bits.
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The counter is incremented by 1 for each 20-byte output. <BR>
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides engineNextBytes in class SecureRandomSpi.
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       bytes - byte array to be filled in with bytes
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       NullPointerException - if null is passed to the "bytes" argument
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void engineNextBytes(byte[] bytes) {
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int i, n;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long bits; // number of bits required by Secure Hash Standard
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nextByteToReturn; // index of ready bytes in "bytes" array
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int lastWord; // index of last word in frame containing bytes
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int extrabytes = 7;// # of bytes to add in order to computer # of 8 byte words
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bytes == null) {
283897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("bytes == null");
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastWord = seed[BYTES_OFFSET] == 0 ? 0
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state == UNDEFINED) {
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // no seed supplied by user, hence it is generated thus randomizing internal state
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            updateSeed(RandomBitsSupplier.getRandomBits(DIGEST_LENGTH));
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = HASHBYTES_TO_USE;
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (state == SET_SEED) {
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, copies, HASHCOPY_OFFSET,
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // possible cases for 64-byte frame:
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //
302f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // seed bytes < 48      - remaining bytes are enough for all, 8 counter bytes,
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        0x80, and 8 seedLength bytes; no extra frame required
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // 48 < seed bytes < 56 - remaining 9 bytes are for 0x80 and 8 counter bytes
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        extra frame contains only seedLength value at the end
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // seed bytes > 55      - extra frame contains both counter's bytes
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        at the beginning and seedLength value at the end;
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        note, that beginning extra bytes are not more than 8,
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        that is, only 2 extra words may be used
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
311f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // no need to set to "0" 3 words after "lastWord" and
312f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // more than two words behind frame
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (i = lastWord + 3; i < FRAME_LENGTH + 2; i++) {
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = 0;
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            bits = seedLength << 3 + 64; // transforming # of bytes into # of bits
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
319f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // putting # of bits into two last words (14,15) of 16 word frame in
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // seed or copies array depending on total length after padding
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] < MAX_BYTES) {
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[14] = (int) (bits >>> 32);
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[15] = (int) (bits & 0xFFFFFFFF);
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 14] = (int) (bits >>> 32);
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 15] = (int) (bits & 0xFFFFFFFF);
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = HASHBYTES_TO_USE; // skipping remaining random bits
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = NEXT_BYTES;
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bytes.length == 0) {
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextByteToReturn = 0;
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
339f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // possibly not all of HASHBYTES_TO_USE bytes were used previous time
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        n = (HASHBYTES_TO_USE - nextBIndex) < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - nextBIndex
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : bytes.length - nextByteToReturn;
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (n > 0) {
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(nextBytes, nextBIndex, bytes, nextByteToReturn, n);
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex += n;
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextByteToReturn += n;
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nextByteToReturn >= bytes.length) {
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return; // return because "bytes[]" are filled in
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        n = seed[BYTES_OFFSET] & 0x03;
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (;;) {
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (n == 0) {
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord] = (int) (counter >>> 32);
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 1] = (int) (counter & 0xFFFFFFFF);
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 2] = END_FLAGS[0];
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord] |= (int) ((counter >>> RIGHT1[n]) & MASK[n]);
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 1] = (int) ((counter >>> RIGHT2[n]) & 0xFFFFFFFF);
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 2] = (int) ((counter << LEFT[n]) | END_FLAGS[n]);
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] > MAX_BYTES) {
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET] = seed[FRAME_LENGTH];
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 1] = seed[FRAME_LENGTH + 1];
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SHA1Impl.computeHash(seed);
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] > MAX_BYTES) {
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(seed, 0, copies, FRAME_OFFSET, FRAME_LENGTH);
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(copies, EXTRAFRAME_OFFSET, seed, 0,
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        FRAME_LENGTH);
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                SHA1Impl.computeHash(seed);
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(copies, FRAME_OFFSET, seed, 0, FRAME_LENGTH);
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            counter++;
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int j = 0;
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (i = 0; i < EXTRAFRAME_OFFSET; i++) {
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int k = seed[HASH_OFFSET + i];
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j] = (byte) (k >>> 24); // getting first  byte from left
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 1] = (byte) (k >>> 16); // getting second byte from left
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 2] = (byte) (k >>> 8); // getting third  byte from left
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 3] = (byte) (k); // getting fourth byte from left
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                j += 4;
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = 0;
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            j = HASHBYTES_TO_USE < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : bytes.length - nextByteToReturn;
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (j > 0) {
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(nextBytes, 0, bytes, nextByteToReturn, j);
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextByteToReturn += j;
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBIndex += j;
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (nextByteToReturn >= bytes.length) {
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream oos) throws IOException {
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int[] intData = null;
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int only_hash = EXTRAFRAME_OFFSET;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int hashes_and_frame = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH;
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int hashes_and_frame_extra = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                * 2;
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeLong(seedLength);
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeLong(counter);
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(state);
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(seed[BYTES_OFFSET]);
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // result may be 0
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state != NEXT_BYTES) {
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
429f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // either the state is UNDEFINED or previous method was "setSeed(..)"
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // so in "seed[]" to serialize are remaining bytes (seed[0-nRemaining]) and
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // current hash (seed[82-86])
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            intData = new int[only_hash + nRemaining];
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, 0, intData, 0, nRemaining);
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, intData, nRemaining,
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // previous method was "nextBytes(..)"
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // so, data to serialize are all the above (two first are in "copies" array)
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // and current words in both frame and extra frame (as if)
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int offset = 0;
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] < MAX_BYTES) { // no extra frame
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData = new int[hashes_and_frame + nRemaining];
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else { // extra frame is used
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData = new int[hashes_and_frame_extra + nRemaining];
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset] = seed[FRAME_LENGTH];
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 1] = seed[FRAME_LENGTH + 1];
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 2] = seed[FRAME_LENGTH + 14];
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 3] = seed[FRAME_LENGTH + 15];
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                offset += 4;
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, 0, intData, offset, FRAME_LENGTH);
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += FRAME_LENGTH;
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, FRAME_LENGTH + EXTRAFRAME_OFFSET, intData,
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    offset, nRemaining);
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += nRemaining;
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, 0, intData, offset, EXTRAFRAME_OFFSET);
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += EXTRAFRAME_OFFSET;
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, intData, offset,
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < intData.length; i++) {
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            oos.writeInt(intData[i]);
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(nextBIndex);
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.write(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void readObject(ObjectInputStream ois) throws IOException,
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ClassNotFoundException {
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBytes = new byte[DIGEST_LENGTH];
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength = ois.readLong();
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        counter = ois.readLong();
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = ois.readInt();
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[BYTES_OFFSET] = ois.readInt();
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state != NEXT_BYTES) {
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < nRemaining; i++) {
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = ois.readInt();
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[HASH_OFFSET + i] = ois.readInt();
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] >= MAX_BYTES) {
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // reading next bytes in seed extra frame
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH] = ois.readInt();
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 1] = ois.readInt();
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 14] = ois.readInt();
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 15] = ois.readInt();
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading next bytes in seed frame
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < FRAME_LENGTH; i++) {
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = ois.readInt();
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
516f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // reading remaining seed bytes
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < nRemaining; i++) {
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[FRAME_LENGTH + EXTRAFRAME_OFFSET + i] = ois.readInt();
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading copy of current hash
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[i] = ois.readInt();
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading current hash
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[HASH_OFFSET + i] = ois.readInt();
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBIndex = ois.readInt();
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ois.read(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
535