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