diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java
new file mode 100644
index 0000000..afa6650
--- /dev/null
+++ b/tools/signapk/SignApk.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2008 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.android.signapk;
+
+import sun.misc.BASE64Encoder;
+import sun.security.pkcs.ContentInfo;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.X500Name;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.security.AlgorithmParameters;
+import java.security.DigestOutputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.Key;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Command line tool to sign JAR files (including APKs and OTA updates) in
+ * a way compatible with the mincrypt verifier, using SHA1 and RSA keys.
+ */
+class SignApk {
+    private static X509Certificate readPublicKey(File file)
+            throws IOException, GeneralSecurityException {
+        FileInputStream input = new FileInputStream(file);
+        try {
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) cf.generateCertificate(input);
+        } finally {
+            input.close();
+        }
+    }
+
+    /**
+     * Reads the password from stdin and returns it as a string.
+     *
+     * @param keyFile The file containing the private key.  Used to prompt the user.
+     */
+    private static String readPassword(File keyFile) {
+        // TODO: use Console.readPassword() when it's available.
+        System.out.print("Enter password for " + keyFile + " (password will not be hidden): ");
+        System.out.flush();
+        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+        try {
+            return stdin.readLine();
+        } catch (IOException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Decrypt an encrypted PKCS 8 format private key.
+     *
+     * Based on ghstark's post on Aug 6, 2006 at
+     * http://forums.sun.com/thread.jspa?threadID=758133&messageID=4330949
+     *
+     * @param encryptedPrivateKey The raw data of the private key
+     * @param keyFile The file containing the private key
+     */
+    private static KeySpec decryptPrivateKey(byte[] encryptedPrivateKey, File keyFile) 
+            throws GeneralSecurityException {
+        EncryptedPrivateKeyInfo epkInfo;
+        try {
+            epkInfo = new EncryptedPrivateKeyInfo(encryptedPrivateKey);
+        } catch (IOException ex) {
+            // Probably not an encrypted key.
+            return null;
+        }
+
+        char[] password = readPassword(keyFile).toCharArray();
+
+        SecretKeyFactory skFactory = SecretKeyFactory.getInstance(epkInfo.getAlgName());
+        Key key = skFactory.generateSecret(new PBEKeySpec(password));
+
+        Cipher cipher = Cipher.getInstance(epkInfo.getAlgName());
+        cipher.init(Cipher.DECRYPT_MODE, key, epkInfo.getAlgParameters());
+
+        try {
+            return epkInfo.getKeySpec(cipher);
+        } catch (InvalidKeySpecException ex) {
+            System.err.println("signapk: Password for " + keyFile + " may be bad.");
+            throw ex;
+        }
+    }
+
+    /** Read a PKCS 8 format private key. */
+    private static PrivateKey readPrivateKey(File file)
+            throws IOException, GeneralSecurityException {
+        DataInputStream input = new DataInputStream(new FileInputStream(file));
+        try {
+            byte[] bytes = new byte[(int) file.length()];
+            input.read(bytes);
+
+            KeySpec spec = decryptPrivateKey(bytes, file);
+            if (spec == null) {
+                spec = new PKCS8EncodedKeySpec(bytes);
+            }
+
+            try {
+                return KeyFactory.getInstance("RSA").generatePrivate(spec);
+            } catch (InvalidKeySpecException ex) {
+                return KeyFactory.getInstance("DSA").generatePrivate(spec);
+            }
+        } finally {
+            input.close();
+        }
+    }
+
+    /** Add the SHA1 of every file to the manifest, creating it if necessary. */
+    private static Manifest addDigestsToManifest(JarFile jar)
+            throws IOException, GeneralSecurityException {
+        Manifest input = jar.getManifest();
+        Manifest output = new Manifest();
+        Attributes main = output.getMainAttributes();
+        if (input != null) {
+            main.putAll(input.getMainAttributes());
+        } else {
+            main.putValue("Manifest-Version", "1.0");
+            main.putValue("Created-By", "1.0 (Android SignApk)");
+        }
+
+        BASE64Encoder base64 = new BASE64Encoder();
+        MessageDigest md = MessageDigest.getInstance("SHA1");
+        byte[] buffer = new byte[4096];
+        int num;
+
+        for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
+            JarEntry entry = e.nextElement();
+            String name = entry.getName();
+            if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME)) {
+                InputStream data = jar.getInputStream(entry);
+                while ((num = data.read(buffer)) > 0) {
+                    md.update(buffer, 0, num);
+                }
+
+                Attributes attr = null;
+                if (input != null) attr = input.getAttributes(name);
+                attr = attr != null ? new Attributes(attr) : new Attributes();
+                attr.putValue("SHA1-Digest", base64.encode(md.digest()));
+                output.getEntries().put(name, attr);
+            }
+        }
+
+        return output;
+    }
+
+    /** Write to another stream and also feed it to the Signature object. */
+    private static class SignatureOutputStream extends FilterOutputStream {
+        private Signature mSignature;
+
+        public SignatureOutputStream(OutputStream out, Signature sig) {
+            super(out);
+            mSignature = sig;
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            try {
+                mSignature.update((byte) b);
+            } catch (SignatureException e) {
+                throw new IOException("SignatureException: " + e);
+            }
+            super.write(b);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            try {
+                mSignature.update(b, off, len);
+            } catch (SignatureException e) {
+                throw new IOException("SignatureException: " + e);
+            }
+            super.write(b, off, len);
+        }
+    }
+
+    /** Write a .SF file with a digest the specified manifest. */
+    private static void writeSignatureFile(Manifest manifest, OutputStream out)
+            throws IOException, GeneralSecurityException {
+        Manifest sf = new Manifest();
+        Attributes main = sf.getMainAttributes();
+        main.putValue("Signature-Version", "1.0");
+        main.putValue("Created-By", "1.0 (Android SignApk)");
+
+        BASE64Encoder base64 = new BASE64Encoder();
+        MessageDigest md = MessageDigest.getInstance("SHA1");
+        PrintStream print = new PrintStream(
+                new DigestOutputStream(new ByteArrayOutputStream(), md),
+                true, "UTF-8");
+
+        // Digest of the entire manifest
+        manifest.write(print);
+        print.flush();
+        main.putValue("SHA1-Digest-Manifest", base64.encode(md.digest()));
+
+        Map<String, Attributes> entries = manifest.getEntries();
+        for (Map.Entry<String, Attributes> entry : entries.entrySet()) {
+            // Digest of the manifest stanza for this entry.
+            print.print("Name: " + entry.getKey() + "\r\n");
+            for (Map.Entry<Object, Object> att : entry.getValue().entrySet()) {
+                print.print(att.getKey() + ": " + att.getValue() + "\r\n");
+            }
+            print.print("\r\n");
+            print.flush();
+
+            Attributes sfAttr = new Attributes();
+            sfAttr.putValue("SHA1-Digest", base64.encode(md.digest()));
+            sf.getEntries().put(entry.getKey(), sfAttr);
+        }
+
+        sf.write(out);
+    }
+
+    /** Write a .RSA file with a digital signature. */
+    private static void writeSignatureBlock(
+            Signature signature, X509Certificate publicKey, OutputStream out)
+            throws IOException, GeneralSecurityException {
+        SignerInfo signerInfo = new SignerInfo(
+                new X500Name(publicKey.getIssuerX500Principal().getName()),
+                publicKey.getSerialNumber(),
+                AlgorithmId.get("SHA1"),
+                AlgorithmId.get("RSA"),
+                signature.sign());
+
+        PKCS7 pkcs7 = new PKCS7(
+                new AlgorithmId[] { AlgorithmId.get("SHA1") },
+                new ContentInfo(ContentInfo.DATA_OID, null),
+                new X509Certificate[] { publicKey },
+                new SignerInfo[] { signerInfo });
+
+        pkcs7.encodeSignedData(out);
+    }
+
+    /** Copy all the files in a manifest from input to output. */
+    private static void copyFiles(Manifest manifest,
+            JarFile in, JarOutputStream out) throws IOException {
+        byte[] buffer = new byte[4096];
+        int num;
+
+        Map<String, Attributes> entries = manifest.getEntries();
+        for (String name : entries.keySet()) {
+            JarEntry inEntry = in.getJarEntry(name);
+            if (inEntry.getMethod() == JarEntry.STORED) {
+                // Preserve the STORED method of the input entry.
+                out.putNextEntry(new JarEntry(inEntry));
+            } else {
+                // Create a new entry so that the compressed len is recomputed.
+                out.putNextEntry(new JarEntry(name));
+            }
+
+            InputStream data = in.getInputStream(inEntry);
+            while ((num = data.read(buffer)) > 0) {
+                out.write(buffer, 0, num);
+            }
+            out.flush();
+        }
+    }
+
+    public static void main(String[] args) {
+        if (args.length != 4) {
+            System.err.println("Usage: signapk " +
+                    "publickey.x509[.pem] privatekey.pk8 " +
+                    "input.jar output.jar");
+            System.exit(2);
+        }
+
+        JarFile inputJar = null;
+        JarOutputStream outputJar = null;
+
+        try {
+            X509Certificate publicKey = readPublicKey(new File(args[0]));
+            PrivateKey privateKey = readPrivateKey(new File(args[1]));
+            inputJar = new JarFile(new File(args[2]), false);  // Don't verify.
+            outputJar = new JarOutputStream(new FileOutputStream(args[3]));
+            outputJar.setLevel(9);
+
+            // MANIFEST.MF
+            Manifest manifest = addDigestsToManifest(inputJar);
+            manifest.getEntries().remove("META-INF/CERT.SF");
+            manifest.getEntries().remove("META-INF/CERT.RSA");
+            outputJar.putNextEntry(new JarEntry(JarFile.MANIFEST_NAME));
+            manifest.write(outputJar);
+
+            // CERT.SF
+            Signature signature = Signature.getInstance("SHA1withRSA");
+            signature.initSign(privateKey);
+            outputJar.putNextEntry(new JarEntry("META-INF/CERT.SF"));
+            writeSignatureFile(manifest,
+                    new SignatureOutputStream(outputJar, signature));
+
+            // CERT.RSA
+            outputJar.putNextEntry(new JarEntry("META-INF/CERT.RSA"));
+            writeSignatureBlock(signature, publicKey, outputJar);
+
+            // Everything else
+            copyFiles(manifest, inputJar, outputJar);
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.exit(1);
+        } finally {
+            try {
+                if (inputJar != null) inputJar.close();
+                if (outputJar != null) outputJar.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+                System.exit(1);
+            }
+        }
+    }
+}
