diff options
Diffstat (limited to 'src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java')
-rw-r--r-- | src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java new file mode 100644 index 0000000..9ebcee6 --- /dev/null +++ b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/packaging/sign/ManifestDigester.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2012 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 com.motorolamobility.studio.android.certmanager.packaging.sign; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import com.motorola.studio.android.common.log.StudioLogger; + +/** + * This class is a Manifest digester. + * It generates digested hashes for each entry in the manifest file. + */ +public class ManifestDigester +{ + private final Manifest manifest; + + private HashMap<String, ManifestEntry> entries = null; + + /** + * Create a new manifest digester with the given manifest + * @param manifest + */ + public ManifestDigester(final Manifest manifest) + { + this.manifest = manifest; + initialize(); + } + + /** + * Initialize the digester creating internal entries for each manifest entry + */ + private void initialize() + { + Map<String, Attributes> manifestEntries = manifest.getEntries(); + + // initialize internal entries list + entries = new HashMap<String, ManifestEntry>(manifestEntries.size()); + for (String entryName : manifestEntries.keySet()) + { + entries.put(entryName, new ManifestEntry(entryName, manifestEntries.get(entryName))); + } + } + + /** + * Get this Manifest file digested + * @throws IOException if some error occurs during entries encoding + */ + public String getDigestedString() throws IOException + { + StringBuilder builder = new StringBuilder(); + for (ManifestEntry entry : entries.values()) + { + builder.append(entry.toDigestedManifestEntry()); + builder.append(ManifestEntry.MANIFEST_NEW_LINE); + } + return builder.toString(); + } + + public HashMap<String, ManifestEntry> getEntries() + { + return entries; + } + + /** + * Computes the digest for the main manifest attributes + * + * @return the digest of the main manifest attributes or null otherwise + * @throws SignException + * if a processing error occurs when computing the digest + */ + public byte[] getDigestedManifestMainAttributes() throws SignException + { + // create an auxiliary manifest that contain only the main attributes + // of the original manifest + Manifest auxManifest = new Manifest(); + byte[] result; + Attributes auxMainAttributes = auxManifest.getMainAttributes(); + Attributes mainAttributes = manifest.getMainAttributes(); + for (Object attributeKey : mainAttributes.keySet()) + { + String name = attributeKey.toString(); + String value = mainAttributes.getValue(name); + auxMainAttributes.putValue(name, value); + } + + result = getDigestedManifest(auxManifest); + + StudioLogger.info(SignatureFile.class, "Created digest for main manifest attributes"); + + return result; + } + + /** + * Get this Manifest digested + * @return + * @throws SignException + */ + public byte[] getDigestedManifest() throws SignException + { + return getDigestedManifest(manifest); + } + + /** + * Computes the digest for the manifest + * + * @param manifest + * the manifest to be digested + * @return the digest of the entire manifest or null otherwise + * @throws SignException + * if a processing error occurs when computing the digest + */ + public static byte[] getDigestedManifest(Manifest manifest) throws SignException + { + byte[] digestedManifestBytes = null; + ByteArrayOutputStream baos = null; + try + { + MessageDigest messageDigest = MessageDigest.getInstance(ISignConstants.SHA1); + baos = new ByteArrayOutputStream(); + manifest.write(baos); + + messageDigest.reset(); + digestedManifestBytes = messageDigest.digest(baos.toByteArray()); + } + catch (IOException e) + { + StudioLogger.error(SignatureFile.class, + "I/O error encoding manifest digest: " + e.getMessage()); + + throw new SignException("I/O error encoding manifest digest", e); + } + catch (NoSuchAlgorithmException e) + { + StudioLogger.error(SignatureFile.class, "Error getting message digester"); + + throw new SignException("Could digest the manifest"); + } + finally + { + try + { + if (baos != null) + { + baos.close(); + } + } + catch (IOException e) + { + //do nothing + } + } + + if (digestedManifestBytes == null) + { + StudioLogger.error(SignatureFile.class, "Error encoding manifest digest"); + + throw new SignException("Could not encode manifest digest"); + } + + StudioLogger.info(SignatureFile.class, "Created manifest digest"); + + return digestedManifestBytes; + } +}
\ No newline at end of file |