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 Projectimport org.apache.harmony.security.fortress.Engine; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 2479f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * Uses a one-way hash function to turn an arbitrary number of bytes into a 2579f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * fixed-length byte sequence. The original arbitrary-length sequence is the 2679f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <i>message</i>, and the fixed-length byte sequence is the <i>digest</i> or 2779f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <i>message digest</i>. 2879f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * 2979f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <h4>Sample Code</h4> 3079f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <p>The basic pattern to digest an {@link java.io.InputStream} looks like this: 3179f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <pre> 3279f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * MessageDigest digester = MessageDigest.getInstance("MD5"); 3379f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * byte[] bytes = new byte[8192]; 3479f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * int byteCount; 3579f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * while ((byteCount = in.read(bytes)) > 0) { 3679f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * digester.update(bytes, 0, byteCount); 3779f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * } 3879f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * byte[] digest = digester.digest(); 3979f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * </pre> 4079f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * 4179f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <p>That is, after creating or resetting a {@code MessageDigest} you should 4279f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * call {@link #update(byte[],int,int)} for each block of input data, and then call {@link #digest} 4379f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * to get the final digest. Note that calling {@code digest} resets the {@code MessageDigest}. 4479f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * Advanced users who want partial digests should clone their {@code MessageDigest} before 4579f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * calling {@code digest}. 4679f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * 4779f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * <p>This class is not thread-safe. 482f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes * 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see MessageDigestSpi 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class MessageDigest extends MessageDigestSpi { 522f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Used to access common engine functionality 540a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom private static final Engine ENGINE = new Engine("MessageDigest"); 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // The provider 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Provider provider; 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // The algorithm. 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String algorithm; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new instance of {@code MessageDigest} with the name of 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the algorithm to use. 65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param algorithm 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of algorithm to use 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected MessageDigest(String algorithm) { 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.algorithm = algorithm; 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new instance of {@code MessageDigest} that utilizes the 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified algorithm. 76f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param algorithm 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the algorithm to use 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new instance of {@code MessageDigest} that utilizes the 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified algorithm 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NoSuchAlgorithmException 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified algorithm is not available 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code algorithm} is {@code null} 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static MessageDigest getInstance(String algorithm) 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws NoSuchAlgorithmException { 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (algorithm == null) { 8986acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("algorithm == null"); 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 916cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null); 926cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom Object spi = sap.spi; 936cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom Provider provider = sap.provider; 940a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom if (spi instanceof MessageDigest) { 950a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom MessageDigest result = (MessageDigest) spi; 960a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom result.algorithm = algorithm; 970a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom result.provider = provider; 980a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom return result; 990a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom } 1006cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom return new MessageDigestImpl((MessageDigestSpi) sap.spi, sap.provider, algorithm); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new instance of {@code MessageDigest} that utilizes the 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified algorithm from the specified provider. 106f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param algorithm 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the algorithm to use 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param provider 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the provider 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new instance of {@code MessageDigest} that utilizes the 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified algorithm from the specified provider 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NoSuchAlgorithmException 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified algorithm is not available 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NoSuchProviderException 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified provider is not available 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code algorithm} is {@code null} 119897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes * @throws IllegalArgumentException if {@code provider == null || provider.isEmpty()} 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static MessageDigest getInstance(String algorithm, String provider) 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws NoSuchAlgorithmException, NoSuchProviderException { 123897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes if (provider == null || provider.isEmpty()) { 124897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException(); 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Provider p = Security.getProvider(provider); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (p == null) { 128897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new NoSuchProviderException(provider); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return getInstance(algorithm, p); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new instance of {@code MessageDigest} that utilizes the 1350a64887ae9127d081fc6e312ba1f06f727453800Kenny Root * specified algorithm from the specified provider. The 1360a64887ae9127d081fc6e312ba1f06f727453800Kenny Root * {@code provider} supplied does not have to be registered. 137f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param algorithm 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the algorithm to use 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param provider 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the provider 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new instance of {@code MessageDigest} that utilizes the 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified algorithm from the specified provider 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NoSuchAlgorithmException 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified algorithm is not available 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code algorithm} is {@code null} 148897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes * @throws IllegalArgumentException if {@code provider == null} 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static MessageDigest getInstance(String algorithm, Provider provider) 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws NoSuchAlgorithmException { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (provider == null) { 153cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes throw new IllegalArgumentException("provider == null"); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (algorithm == null) { 15686acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("algorithm == null"); 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1586cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom Object spi = ENGINE.getInstance(algorithm, provider, null); 1590a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom if (spi instanceof MessageDigest) { 1600a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom MessageDigest result = (MessageDigest) spi; 1610a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom result.algorithm = algorithm; 1620a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom result.provider = provider; 1632f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes return result; 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1650a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom return new MessageDigestImpl((MessageDigestSpi) spi, provider, algorithm); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Puts this {@code MessageDigest} back in an initial state, such that it is 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ready to compute a one way hash value. 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void reset() { 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project engineReset(); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Updates this {@code MessageDigest} using the given {@code byte}. 178f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param arg0 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code byte} to update this {@code MessageDigest} with 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #reset() 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void update(byte arg0) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project engineUpdate(arg0); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Updates this {@code MessageDigest} using the given {@code byte[]}. 189f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param input 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code byte} array 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the index of the first byte in {@code input} to update from 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param len 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of bytes in {@code input} to update from 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset} or {@code len} are not valid in respect to 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code input} 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void update(byte[] input, int offset, int len) { 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (input == null || 2022f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes // offset < 0 || len < 0 || 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // checks for negative values are commented out intentionally 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // see HARMONY-1120 for details 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (long) offset + (long) len > input.length) { 206897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException(); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project engineUpdate(input, offset, len); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Updates this {@code MessageDigest} using the given {@code byte[]}. 213f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param input 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code byte} array 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code input} is {@code null} 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void update(byte[] input) { 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (input == null) { 22186acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("input == null"); 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project engineUpdate(input, 0, input.length); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Computes and returns the final hash value for this {@link MessageDigest}. 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * After the digest is computed the receiver is reset. 229f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the computed one way hash value 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #reset 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public byte[] digest() { 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return engineDigest(); 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Computes and stores the final hash value for this {@link MessageDigest}. 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * After the digest is computed the receiver is reset. 240f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buf 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer to store the result 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the index of the first byte in {@code buf} to store 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param len 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of bytes allocated for the digest 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the number of bytes written to {@code buf} 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws DigestException 24979f07cc86be9abc27d0da7df3245ba4bab809ae6Elliott Hughes * if an error occurs 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset} or {@code len} are not valid in respect to 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code buf} 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #reset() 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int digest(byte[] buf, int offset, int len) throws DigestException { 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buf == null || 2572f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes // offset < 0 || len < 0 || 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // checks for negative values are commented out intentionally 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // see HARMONY-1148 for details 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (long) offset + (long) len > buf.length) { 261897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException(); 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return engineDigest(buf, offset, len); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Performs the final update and then computes and returns the final hash 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * value for this {@link MessageDigest}. After the digest is computed the 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * receiver is reset. 270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param input 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code byte} array 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the computed one way hash value 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #reset() 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public byte[] digest(byte[] input) { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project update(input); 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return digest(); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a string containing a concise, human-readable description of this 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code MessageDigest} including the name of its algorithm. 284f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a printable representation for this {@code MessageDigest} 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2872f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 289f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return "MESSAGE DIGEST " + algorithm; 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether to digest are equal by performing a simply 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * byte-per-byte compare of the two digests. 295f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param digesta 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the first digest to be compared 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param digestb 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the second digest to be compared 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the two hashes are equal, {@code false} otherwise 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static boolean isEqual(byte[] digesta, byte[] digestb) { 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (digesta.length != digestb.length) { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3063e478f0dbd7bb982fb36d96bfec09f14271d9c05Xizhi Zhu (Steven) // Perform a constant time comparison to avoid timing attacks. 3073e478f0dbd7bb982fb36d96bfec09f14271d9c05Xizhi Zhu (Steven) int v = 0; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < digesta.length; i++) { 3093e478f0dbd7bb982fb36d96bfec09f14271d9c05Xizhi Zhu (Steven) v |= (digesta[i] ^ digestb[i]); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3113e478f0dbd7bb982fb36d96bfec09f14271d9c05Xizhi Zhu (Steven) return v == 0; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the name of the algorithm of this {@code MessageDigest}. 316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the name of the algorithm of this {@code MessageDigest} 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final String getAlgorithm() { 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return algorithm; 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the provider associated with this {@code MessageDigest}. 325f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the provider associated with this {@code MessageDigest} 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Provider getProvider() { 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return provider; 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the engine digest length in bytes. If the implementation does not 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement this function or is not an instance of {@code Cloneable}, 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code 0} is returned. 336f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the digest length in bytes, or {@code 0} 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getDigestLength() { 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int l = engineGetDigestLength(); 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (l != 0) { 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return l; 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(this instanceof Cloneable)) { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project MessageDigest md = (MessageDigest) clone(); 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return md.digest().length; 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CloneNotSupportedException e) { 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Updates this {@code MessageDigest} using the given {@code input}. 357f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param input 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code ByteBuffer} 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final void update(ByteBuffer input) { 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project engineUpdate(input); 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 366f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The internal MessageDigest implementation 368f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class MessageDigestImpl extends MessageDigest { 3712f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // MessageDigestSpi implementation 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private MessageDigestSpi spiImpl; 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // MessageDigestImpl ctor 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private MessageDigestImpl(MessageDigestSpi messageDigestSpi, 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Provider provider, String algorithm) { 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(algorithm); 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.provider = provider; 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spiImpl = messageDigestSpi; 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // engineReset() implementation 3842f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void engineReset() { 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spiImpl.engineReset(); 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // engineDigest() implementation 3902f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] engineDigest() { 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return spiImpl.engineDigest(); 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // engineGetDigestLength() implementation 3962f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int engineGetDigestLength() { 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return spiImpl.engineGetDigestLength(); 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // engineUpdate() implementation 4022f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void engineUpdate(byte arg0) { 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spiImpl.engineUpdate(arg0); 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // engineUpdate() implementation 4082f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void engineUpdate(byte[] arg0, int arg1, int arg2) { 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spiImpl.engineUpdate(arg0, arg1, arg2); 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Returns a clone if the spiImpl is cloneable 4142f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes @Override 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object clone() throws CloneNotSupportedException { 416875d3c90f395109a30ed12f8f83ad001d2ae7439Kenny Root MessageDigestSpi spi = (MessageDigestSpi) spiImpl.clone(); 417875d3c90f395109a30ed12f8f83ad001d2ae7439Kenny Root return new MessageDigestImpl(spi, getProvider(), getAlgorithm()); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 421