예제 #1
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);
        }
예제 #2
0
        /**
         * Copy all the files in a manifest from input to output.  We set
         * the modification times in the output to a fixed time, so as to
         * reduce variation in the output file and make incremental OTAs
         * more efficient.
         */
        private static void copyFiles(Manifest manifest,
                                      JarFile in_, ZipOutputStream out_, DateTime timestamp)
        {
            byte[] buffer = new byte[4096];
            int    num;

            IDictionary <String, Attributes> entries = manifest.Entries;
            List <String> names = new List <String>(entries.Keys);

            names.Sort();
            foreach (String name in names)
            {
                JarEntry inEntry  = in_.GetJarEntry(name);
                JarEntry outEntry = null;
                if (inEntry.CompressionMethod == CompressionMethod.Stored)
                {
                    // Preserve the STORED method of the input entry.
                    outEntry = new JarEntry(inEntry);
                }
                else
                {
                    // Create a new entry so that the compressed len is recomputed.
                    outEntry = new JarEntry(name);
                    if (inEntry.Size > -1)
                    {
                        outEntry.Size = inEntry.Size;
                    }
                }
                outEntry.DateTime = timestamp;
                out_.PutNextEntry(outEntry);

                Stream data = in_.GetInputStream(inEntry);
                while ((num = data.Read(buffer, 0, buffer.Length)) > 0)
                {
                    out_.Write(buffer, 0, num);
                }
                out_.Flush();
            }
        }
예제 #3
0
 /**
  * Creates a new <code>JarEntry</code> with fields taken from the
  * specified <code>JarEntry</code> object.
  *
  * @param je the <code>JarEntry</code> to copy
  */
 public JarEntry(JarEntry je)
     : this((ZipEntry)je)
 {
     this.attr = je.attr;
 }
예제 #4
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);
            }
        }