1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.security;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code MessageDigestSpi} is the Service Provider Interface (SPI) definition
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for {@link MessageDigest}. Examples of digest algorithms are MD5 and SHA. A
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * digest is a secure one way hash function for a stream of bytes. It acts like
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a fingerprint for a stream of bytes.
27f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see MessageDigest
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class MessageDigestSpi {
31f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the engine digest length in bytes. If the implementation does not
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implement this function {@code 0} is returned.
35f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the digest length in bytes, or {@code 0}.
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected int engineGetDigestLength() {
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return 0;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
41f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Updates this {@code MessageDigestSpi} using the given {@code byte}.
44f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code byte} to update this {@code MessageDigestSpi} with.
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #engineReset()
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected abstract void engineUpdate(byte input);
50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Updates this {@code MessageDigestSpi} using the given {@code byte[]}.
53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code byte} array.
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the index of the first byte in {@code input} to update from.
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param len
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of bytes in {@code input} to update from.
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset} or {@code len} are not valid in respect to
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code input}.
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected abstract void engineUpdate(byte[] input, int offset, int len);
65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Updates this {@code MessageDigestSpi} using the given {@code input}.
68f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code ByteBuffer}.
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void engineUpdate(ByteBuffer input) {
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!input.hasRemaining()) {
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] tmp;
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input.hasArray()) {
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            tmp = input.array();
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int offset = input.arrayOffset();
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int position = input.position();
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int limit = input.limit();
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engineUpdate(tmp, offset+position, limit - position);
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            input.position(limit);
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            tmp = new byte[input.limit() - input.position()];
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            input.get(tmp);
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engineUpdate(tmp, 0, tmp.length);
88f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        }
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
90f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Computes and returns the final hash value for this
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link MessageDigestSpi}. After the digest is computed the receiver is
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reset.
95f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the computed one way hash value.
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #engineReset()
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected abstract byte[] engineDigest();
100f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Computes and stores the final hash value for this
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link MessageDigestSpi}. After the digest is computed the receiver is
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reset.
105f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buf
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the buffer to store the result in.
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the index of the first byte in {@code buf} to store in.
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param len
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of bytes allocated for the digest.
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes written to {@code buf}.
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws DigestException
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occures.
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset} or {@code len} are not valid in respect to
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code buf}.
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #engineReset()
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
120897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    protected int engineDigest(byte[] buf, int offset, int len) throws DigestException {
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (len < engineGetDigestLength()) {
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engineReset();
123897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new DigestException("The value of len parameter is less than the actual digest length");
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (offset < 0) {
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engineReset();
127897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new DigestException("offset < 0");
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (offset + len > buf.length) {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engineReset();
131897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new DigestException("offset + len > buf.length");
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
133171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes        byte[] tmp = engineDigest();
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (len < tmp.length) {
135897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new DigestException("The value of len parameter is less than the actual digest length");
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.arraycopy(tmp, 0, buf, offset, tmp.length);
138f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        return tmp.length;
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
140f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Puts this {@code MessageDigestSpi} back in an initial state, such that it
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is ready to compute a one way hash value.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected abstract void engineReset();
146f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
1472f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object clone() throws CloneNotSupportedException {
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.clone();
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
152