Exemple #1
0
        /** Write a .SF file with a digest of the specified manifest. */
        private static void writeSignatureFile(Manifest manifest, Stream out_)
        {
            Manifest   sf   = new Manifest();
            Attributes main = sf.MainAttributes;

            main.Add("Signature-Version", "1.0");
            main.Add("Created-By", "1.0 (Android SignApk)");

            DigestOutputStream digestStream = new DigestOutputStream("SHA1");
            StreamWriter       print        = new StreamWriter(digestStream, new UTF8Encoding());

            // Digest of the entire manifest
            manifest.Write(digestStream);
            print.Flush();
            main.Add("SHA1-Digest-Manifest", Convert.ToBase64String(digestStream.Hash));

            IDictionary <String, Attributes> entries = manifest.Entries;

            foreach (var entry in entries)
            {
                // Digest of the manifest stanza for this entry.
                print.Write("Name: " + entry.Key + "\r\n");
                foreach (var att in entry.Value)
                {
                    print.Write(att.Key + ": " + att.Value + "\r\n");
                }
                print.Write("\r\n");
                print.Flush();

                Attributes sfAttr = new Attributes();
                sfAttr.Add("SHA1-Digest", Convert.ToBase64String(digestStream.Hash));
                sf.Entries.Add(entry.Key, sfAttr);
            }

            sf.Write(out_);

            // A bug in the java.util.jar implementation of Android platforms
            // up to version 1.6 will cause a spurious IOException to be thrown
            // if the length of the signature file is a multiple of 1024 bytes.
            // As a workaround, add an extra CRLF in this case.
            if ((out_.Length % 1024) == 0)
            {
                var b = Encoding.UTF8.GetBytes("\r\n");
                out_.Write(b, 0, b.Length);
            }
        }
Exemple #2
0
        /**
         * Add a copy of the public key to the archive; this should
         * exactly match one of the files in_
         * /system/etc/security/otacerts.zip on the device.  (The same
         * cert can be extracted from the CERT.RSA file but this is much
         * easier to get at.)
         */
        private static void addOtacert(ZipOutputStream outputJar,
                                       X509Certificate2 certificate,
                                       DateTime timestamp,
                                       Manifest manifest)
        {
            HashAlgorithm md = HashAlgorithm.Create("SHA1");

            byte[] b = certificate.Export(X509ContentType.Cert);

            JarEntry je = new JarEntry(OTACERT_NAME);

            je.DateTime = timestamp;
            je.Size     = b.Length;
            outputJar.PutNextEntry(je);
            outputJar.Write(b, 0, b.Length);

            Attributes attr = new Attributes();

            attr.Add("SHA1-Digest", Convert.ToBase64String(md.ComputeHash(b)));
            manifest.Entries.Add(OTACERT_NAME, attr);
        }
Exemple #3
0
        /** Add the SHA1 of every file to the manifest, creating it if necessary. */
        private static Manifest addDigestsToManifest(JarFile jar)
        {
            Manifest   input  = jar.Manifest;
            Manifest   output = new Manifest();
            Attributes main   = output.MainAttributes;

            if (input != null)
            {
                main.AddAll(input.MainAttributes);
            }
            else
            {
                main.Add("Manifest-Version", "1.0");
                main.Add("Created-By", "1.0 (Android SignApk)");
            }

            byte[] buffer = new byte[4096];
            int    num;

            IEnumerable <JarEntry> jes;

            if (input == null)
            {
                jes = jar.OrderBy(j => j.Name);
            }
            else
            {
                var entries       = jar.ToDictionary(j => j.Name);
                var sortedEntries = new List <JarEntry>();
                foreach (var entry in input.Entries)
                {
                    sortedEntries.Add(entries[entry.Key]);
                }
                jes = sortedEntries;
            }

            foreach (JarEntry entry in jes)
            {
                HashAlgorithm md   = HashAlgorithm.Create("SHA1");
                String        name = entry.Name;
                if (!entry.IsDirectory && !name.Equals(JarFile.MANIFEST_NAME) &&
                    !name.Equals(CERT_SF_NAME) && !name.Equals(CERT_RSA_NAME) &&
                    !name.Equals(OTACERT_NAME) &&
                    (stripPattern == null ||
                     !stripPattern.IsMatch(name)))
                {
                    Stream data = jar.GetInputStream(entry);
                    while ((num = data.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        md.TransformBlock(buffer, 0, num, null, 0);
                    }
                    md.TransformFinalBlock(buffer, 0, 0);

                    Attributes attr = null;
                    if (input != null)
                    {
                        attr = input.GetAttributes(name);
                    }
                    attr = attr != null ? new Attributes(attr) : new Attributes();
                    attr.Add("SHA1-Digest", Convert.ToBase64String(md.Hash));
                    output.Entries.Add(name, attr);
                }
            }

            return(output);
        }