/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.util;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.Signature;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

Helper functions applicable to packages.
@hide
/** * Helper functions applicable to packages. * @hide */
public final class PackageUtils { private PackageUtils() { /* hide constructor */ }
Computes the SHA256 digests of a list of signatures. Items in the resulting array of hashes correspond to the signatures in the input array.
Params:
  • signatures – The signatures.
Returns:The digest array.
/** * Computes the SHA256 digests of a list of signatures. Items in the * resulting array of hashes correspond to the signatures in the * input array. * @param signatures The signatures. * @return The digest array. */
public static @NonNull String[] computeSignaturesSha256Digests( @NonNull Signature[] signatures) { final int signatureCount = signatures.length; final String[] digests = new String[signatureCount]; for (int i = 0; i < signatureCount; i++) { digests[i] = computeSha256Digest(signatures[i].toByteArray()); } return digests; }
Computes a SHA256 digest of the signatures' SHA256 digests. First, individual hashes for each signature is derived in a hexademical form, then these strings are sorted based the natural ordering, and finally a hash is derived from these strings' bytes.
Params:
  • signatures – The signatures.
Returns:The digest.
/** * Computes a SHA256 digest of the signatures' SHA256 digests. First, * individual hashes for each signature is derived in a hexademical * form, then these strings are sorted based the natural ordering, and * finally a hash is derived from these strings' bytes. * @param signatures The signatures. * @return The digest. */
public static @NonNull String computeSignaturesSha256Digest( @NonNull Signature[] signatures) { // Shortcut for optimization - most apps singed by a single cert if (signatures.length == 1) { return computeSha256Digest(signatures[0].toByteArray()); } // Make sure these are sorted to handle reversed certificates final String[] sha256Digests = computeSignaturesSha256Digests(signatures); return computeSignaturesSha256Digest(sha256Digests); }
Computes a SHA256 digest in of the signatures SHA256 digests. First, the strings are sorted based the natural ordering, and then a hash is derived from these strings' bytes.
Params:
  • sha256Digests – Signature SHA256 hashes in hexademical form.
Returns:The digest.
/** * Computes a SHA256 digest in of the signatures SHA256 digests. First, * the strings are sorted based the natural ordering, and then a hash is * derived from these strings' bytes. * @param sha256Digests Signature SHA256 hashes in hexademical form. * @return The digest. */
public static @NonNull String computeSignaturesSha256Digest( @NonNull String[] sha256Digests) { // Shortcut for optimization - most apps singed by a single cert if (sha256Digests.length == 1) { return sha256Digests[0]; } // Make sure these are sorted to handle reversed certificates Arrays.sort(sha256Digests); final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); for (String sha256Digest : sha256Digests) { try { bytes.write(sha256Digest.getBytes()); } catch (IOException e) { /* ignore - can't happen */ } } return computeSha256Digest(bytes.toByteArray()); }
Computes the SHA256 digest of some data.
Params:
  • data – The data.
Returns:The digest or null if an error occurs.
/** * Computes the SHA256 digest of some data. * @param data The data. * @return The digest or null if an error occurs. */
public static @Nullable byte[] computeSha256DigestBytes(@NonNull byte[] data) { MessageDigest messageDigest; try { messageDigest = MessageDigest.getInstance("SHA256"); } catch (NoSuchAlgorithmException e) { /* can't happen */ return null; } messageDigest.update(data); return messageDigest.digest(); }
Computes the SHA256 digest of some data.
Params:
  • data – The data.
Returns:The digest or null if an error occurs.
/** * Computes the SHA256 digest of some data. * @param data The data. * @return The digest or null if an error occurs. */
public static @Nullable String computeSha256Digest(@NonNull byte[] data) { return ByteStringUtils.toHexString(computeSha256DigestBytes(data)); } }