1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership. 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License. You may obtain a copy of the License at 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.luni.util; 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.OutputStream; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class implements the Secure Hash Algorithm, SHA-1. The specification can 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be found at http://csrc.ncsl.nist.gov/fips/fip180-1.txt 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class SHAOutputStream extends OutputStream implements Cloneable { 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Constants as in the specification */ 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // K in iterations 0..19, from spec 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int K0_19 = 0x5a827999; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // K in iterations 20..39, from spec 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int K20_39 = 0x6ed9eba1; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // K in iterations 40..59, from spec 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int K40_59 = 0x8f1bbcdc; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // K in iterations 60..79, from spec 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int K60_79 = 0xca62c1d6; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // H0, from spec 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int H0 = 0x67452301; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // H1, from spec 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int H1 = 0xefcdab89; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // H2, from spec 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int H2 = 0x98badcfe; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // H3, from spec 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int H3 = 0x10325476; 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // H4, from spec 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int H4 = 0xc3d2e1f0; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int HConstantsSize = 5; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int HashSizeInBytes = 20; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 16 words 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int BlockSizeInBytes = 16 * 4; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 80 words 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int WArraySize = 80; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 5-word Array. Starts with well-known constants, ends with SHA 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int[] HConstants; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 80-word Array. 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int[] WArray; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 16-word Array. Input bit stream M is divided in chunks of MArray 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] MArray; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Number of bytes of input already processed towards SHA result 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private long bytesProcessed; 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Number of bytes in WArray not processed yet 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int bytesToProcess; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Optimization, for write 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] oneByte = new byte[1]; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs a new SHAOutputStream. 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public SHAOutputStream() { 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initialize(); 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project reset(); 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs a new MD5OutputStream with the given initial state. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param state The initial state of the output stream. This is what will be 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returned by getHash() if write() is never called. 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IllegalArgumentException if state.length is less than 16. 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public SHAOutputStream(byte[] state) { 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (state.length < HashSizeInBytes) { 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException(); 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < 4; i++) { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[i] = 0; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int j = 0; j < 4; j++) { 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[i] += (state[4 * i + j] & 0xFF) << 8 * (3 - j); 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a new instance of the same class as the receiver, whose slots 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have been filled in with the values in the slots of the receiver. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Classes which wish to support cloning must specify that they implement 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the Cloneable interface, since the native implementation checks for this. 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return a complete copy of this object 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws CloneNotSupportedException if the component does not implement 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interface Cloneable 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Object clone() throws CloneNotSupportedException { 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Calling super takes care of primitive type slots 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SHAOutputStream result = (SHAOutputStream) super.clone(); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.HConstants = this.HConstants.clone(); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.WArray = this.WArray.clone(); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.MArray = this.MArray.clone(); 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result.oneByte = this.oneByte.clone(); 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copies a byte array into the receiver's internal buffer, making the 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * adjustments as necessary and keeping the receiver in a consistent state. 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param buffer byte array representation of the bytes 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param off offset into the source buffer where to start the copying 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param len how many bytes in the source byte array to copy 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void copyToInternalBuffer(byte[] buffer, int off, int len) { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int index; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project index = off; 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = bytesToProcess; i < bytesToProcess + len; i++) { 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray[i] = buffer[index]; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project index++; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesToProcess = bytesToProcess + len; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns an int array (length = 5) with the SHA value of the bytes written 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the receiver. 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return The 5 ints that form the SHA value of the bytes written to 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the receiver 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int[] getHash() { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.padBuffer(); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int[] result = HConstants.clone(); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // After the user asks for the hash value, the stream is put back to the 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // initial state 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project reset(); 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a byte array (length = 20) with the SHA value of the bytes 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * written to the receiver. 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return The bytes that form the SHA value of the bytes written to 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the receiver 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] getHashAsBytes() { 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] hash = new byte[HashSizeInBytes]; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.padBuffer(); 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We need to return HConstants (modified by the loop) as an array of 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // bytes. A memcopy would be the fastest. 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < (HashSizeInBytes / 4); ++i) { 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff); 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // After the user asks for the hash value, the stream is put back to the 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // initial state 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project reset(); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hash; 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a byte array (length = 20) with the SHA value of the bytes 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * written to the receiver. 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return The bytes that form the SHA value of the bytes written to 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the receiver 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] getHashAsBytes(boolean pad) { 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] hash = new byte[HashSizeInBytes]; 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pad) { 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.padBuffer(); 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Convert HConstants to an array of bytes 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < (HashSizeInBytes / 4); i++) { 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff); 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff); 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // After the user asks for the hash value, the stream is put back to the 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // initial state 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project reset(); 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return hash; 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initializes the receiver. 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void initialize() { 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants = new int[HConstantsSize]; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray = new byte[BlockSizeInBytes]; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project WArray = new int[WArraySize]; 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Adds extra bytes to the bit stream as required (see the SHA 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specification). 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void padBuffer() { 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long lengthInBits; 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray[bytesToProcess] = (byte) 0x80; 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = bytesToProcess + 1; i < BlockSizeInBytes; i++) { 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray[i] = (byte) 0; 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Get length now because there might be extra padding (length in bits) 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lengthInBits = (bytesToProcess + bytesProcessed) * 8; 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 9 extra bytes are needed: 1 for 1000... and 8 for length (long) 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((bytesToProcess + 9) > BlockSizeInBytes) { 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Not enough space to append length. We need another block for 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // padding 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Padding in this buffer only includes 1000000.... 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Now put 0's in all the buffer. memfill would be faster 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < BlockSizeInBytes; i++) { 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray[i] = (byte) 0; 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < 9; i++) { 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MArray[BlockSizeInBytes - i] = (byte) (lengthInBits & 0xff); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lengthInBits = lengthInBits >>> 8; 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Core SHA code. Processes the receiver's buffer of bits, computing the 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values towards the final SHA 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void processBuffer() { 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int A; // A variable, from spec 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int B; // B variable, from spec 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int C; // C variable, from spec 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int D; // D variable, from spec 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int E; // E variable, from spec 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int temp; // TEMP, from spec 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int t; // t, for iteration, from spec 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 0; t <= 15; t++) { // step a, page 7 of spec. Here we convert 4 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // bytes into 1 word, 16 times 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project WArray[t] = (MArray[4 * t] & 0xff) << 24 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project | ((MArray[4 * t + 1] & 0xff) << 16) 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project | ((MArray[4 * t + 2] & 0xff) << 8) 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project | (MArray[4 * t + 3] & 0xff); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 16; t <= 79; t++) { // step b, page 7 of spec 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (WArray[t - 3] ^ WArray[t - 8] ^ WArray[t - 14] ^ WArray[t - 16]); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (temp << 1) | (temp >>> (32 - 1)); // element , Circular 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Shift Left by 1 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project WArray[t] = temp; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // step c, page 7 of spec 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A = HConstants[0]; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B = HConstants[1]; 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C = HConstants[2]; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project D = HConstants[3]; 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project E = HConstants[4]; 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // step d, page 8 of spec 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 0; t <= 19; t++) { 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + E + WArray[t] + K0_19; 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + ((B & C) | (~B & D)); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project E = D; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project D = C; 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B = A; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A = temp; 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 20; t <= 39; t++) { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + E + WArray[t] + K20_39; 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + (B ^ C ^ D); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project E = D; 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project D = C; 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B = A; 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A = temp; 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 40; t <= 59; t++) { 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + E + WArray[t] + K40_59; 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + ((B & C) | (B & D) | (C & D)); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project E = D; 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project D = C; 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B = A; 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A = temp; 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (t = 60; t <= 79; t++) { 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + E + WArray[t] + K60_79; 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temp = temp + (B ^ C ^ D); 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project E = D; 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project D = C; 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B = A; 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A = temp; 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // step e, page 8 of spec 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[0] = HConstants[0] + A; 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[1] = HConstants[1] + B; 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[2] = HConstants[2] + C; 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[3] = HConstants[3] + D; 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[4] = HConstants[4] + E; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Update number of bytes actually processed 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesProcessed = bytesProcessed + BlockSizeInBytes; 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesToProcess = 0; // No pending bytes in the block 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reset this SHAOutputStream to the state it was before any byte was 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * written to it. 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void reset() { 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[0] = H0; 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[1] = H1; 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[2] = H2; 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[3] = H3; 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project HConstants[4] = H4; 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesProcessed = 0; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesToProcess = 0; 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return this.getClass().getName() + ':' + toStringBlock(getHashAsBytes()); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Converts a block to a String representation. 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param block 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * byte array representation of the bytes 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static String toStringBlock(byte[] block) { 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return toStringBlock(block, 0, block.length); 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Converts a block to a String representation. 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param block 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * byte array representation of the bytes 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param off 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * offset into the block where to start the conversion 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param len 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * how many bytes in the byte array to convert to a printable 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * representation 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static String toStringBlock(byte[] block, int off, int len) { 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String hexdigits = "0123456789ABCDEF"; 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuilder buf = new StringBuilder(); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append('['); 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = off; i < off + len; ++i) { 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(hexdigits.charAt((block[i] >>> 4) & 0xf)); 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(hexdigits.charAt(block[i] & 0xf)); 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(']'); 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return buf.toString(); 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Writes <code>len</code> <code>bytes</code> from this byte array 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <code>buffer</code> starting at offset <code>off</code> to the 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * SHAOutputStream. The internal buffer used to compute SHA is updated, and 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the incremental computation of SHA is also performed. 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param buffer 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the buffer to be written 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param off 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * offset in buffer to get bytes 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param len 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * number of bytes in buffer to write 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void write(byte[] buffer, int off, int len) { 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int spaceLeft; 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int start; 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int bytesLeft; 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spaceLeft = BlockSizeInBytes - bytesToProcess; 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len < spaceLeft) { // Extra bytes are not enough to fill buffer 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.copyToInternalBuffer(buffer, off, len); 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Extra bytes are bigger than space in buffer. Process buffer multiple 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // times 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.copyToInternalBuffer(buffer, off, spaceLeft); 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesLeft = len - spaceLeft; 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = off + spaceLeft; 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (bytesLeft >= BlockSizeInBytes) { 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.copyToInternalBuffer(buffer, start, BlockSizeInBytes); 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytesLeft = bytesLeft - BlockSizeInBytes; 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.processBuffer(); 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = start + BlockSizeInBytes; 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (bytesLeft > 0) { 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Extra bytes at the end, not enough to fill buffer 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.copyToInternalBuffer(buffer, start, bytesLeft); 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Writes the specified byte <code>b</code> to this OutputStream. Only the 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * low order byte of <code>b</code> is written. 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param b 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the byte to be written 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void write(int b) { 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Not thread-safe because we use a shared one-byte buffer 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oneByte[0] = (byte) b; 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project write(oneByte, 0, 1); 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 464