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