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