Пример #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);
            }
        }
Пример #2
0
        public static void SignPackage(Stream input, X509Certificate2 certificate, Stream output, bool signWholeFile)
        {
            JarFile         inputJar  = null;
            ZipOutputStream outputJar = null;

            // Assume the certificate is valid for at least an hour.
            DateTime timestamp;

            DateTime.TryParse(certificate.GetEffectiveDateString(), out timestamp);
            timestamp = timestamp.AddHours(1);

            //DateTime timestamp = DateTime.Parse(certificate.GetEffectiveDateString()).AddHours(1);

            inputJar = new JarFile(input);  // Don't verify.

            Stream outputStream = null;

            if (signWholeFile)
            {
                outputStream = new MemoryStream();
            }
            else
            {
                outputStream = output;
            }
            outputJar = new ZipOutputStream(outputStream);
            outputJar.SetComment(null);
            outputJar.SetLevel(9);

            JarEntry je;

            Manifest manifest = addDigestsToManifest(inputJar);

            // Everything else
            copyFiles(manifest, inputJar, outputJar, timestamp);

            // otacert
            if (signWholeFile)
            {
                addOtacert(outputJar, certificate, timestamp, manifest);
            }

            var buffer = new MemoryStream();

            // MANIFEST.MF
            je          = new JarEntry(JarFile.MANIFEST_NAME);
            je.DateTime = timestamp;
            manifest.Write(buffer);
            je.Size = buffer.Length;
            outputJar.PutNextEntry(je);
            buffer.WriteTo(outputJar);

            // CERT.SF
            var signature = new MemoryStream();

            je          = new JarEntry(CERT_SF_NAME);
            je.DateTime = timestamp;
            buffer.SetLength(0);
            writeSignatureFile(manifest, signature);
            signature.WriteTo(buffer);
            je.Size = buffer.Length;
            outputJar.PutNextEntry(je);
            buffer.WriteTo(outputJar);

            // CERT.RSA
            je          = new JarEntry(CERT_RSA_NAME);
            je.DateTime = timestamp;
            buffer.SetLength(0);
            writeSignatureBlock(signature, certificate, buffer);
            je.Size = buffer.Length;
            outputJar.PutNextEntry(je);
            buffer.WriteTo(outputJar);

            outputJar.Close();
            outputJar = null;

            if (signWholeFile)
            {
                signWholeOutputFile(((MemoryStream)outputStream).ToArray(),
                                    output, certificate);
            }
        }