Switch order of digest and digest encryption algorithm

Sometimes "digest encryption algorithm" would be "RSA" which would match
a Signature provider, but its default setup would be whatever the
provider chose. This works fine with newer algorithms that have a
specific OID for their signature format (e.g., ECDSA and SHA256), but
not with algorithms that just have a generic OID for all possible uses
(e.g., RSA). Stock Android never hits this problem, because nothing
registers a "Signature.RSA" provider, but Spongycastle does so using
JarURLClassLoader after inserting Spongycastle causes a problem.

Flip the order of tries to make this work more uniformly with more JAR
and provider combinations.

(cherry picked from commit b1da6d3df5f9cce6e6d77c63599eba62edb465d6)

Bug: 17790692
Bug: https://code.google.com/p/android/issues/detail?id=68562
Change-Id: I3bb07ea25d7bf1d55fa2466b204594179ac38932
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
index d5d8191..f55829d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
@@ -24,7 +24,15 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.security.CodeSigner;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
 import java.security.Permission;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
@@ -1014,4 +1022,73 @@
         res = jarFile.getInputStream(zipEntry).read();
         assertEquals("Wrong length of empty jar entry", -1, res);
     }
+
+    public void testJarFile_BadSignatureProvider_Success() throws Exception {
+        Security.insertProviderAt(new JarFileBadProvider(), 1);
+        try {
+            // Needs a JAR with "RSA" as digest encryption algorithm
+            checkSignedJar(jarName6);
+        } finally {
+            Security.removeProvider(JarFileBadProvider.NAME);
+        }
+    }
+
+    public static class JarFileBadProvider extends Provider {
+        public static final String NAME = "JarFileBadProvider";
+
+        public JarFileBadProvider() {
+            super(NAME, 1.0, "Bad provider for JarFileTest");
+
+            put("Signature.RSA", NotReallyASignature.class.getName());
+        }
+
+        /**
+         * This should never be instantiated, so everything throws an exception.
+         */
+        public static class NotReallyASignature extends SignatureSpi {
+            @Override
+            protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+                fail("Should not call this provider");
+            }
+
+            @Override
+            protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+                fail("Should not call this provider");
+            }
+
+            @Override
+            protected void engineUpdate(byte b) throws SignatureException {
+                fail("Should not call this provider");
+            }
+
+            @Override
+            protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+                fail("Should not call this provider");
+            }
+
+            @Override
+            protected byte[] engineSign() throws SignatureException {
+                fail("Should not call this provider");
+                return null;
+            }
+
+            @Override
+            protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+                fail("Should not call this provider");
+                return false;
+            }
+
+            @Override
+            protected void engineSetParameter(String param, Object value)
+                    throws InvalidParameterException {
+                fail("Should not call this provider");
+            }
+
+            @Override
+            protected Object engineGetParameter(String param) throws InvalidParameterException {
+                fail("Should not call this provider");
+                return null;
+            }
+        }
+    }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index e7f3596..5755dc2 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -124,28 +124,12 @@
         final String daOid = sigInfo.getDigestAlgorithm();
         final String daName = sigInfo.getDigestAlgorithmName();
         final String deaOid = sigInfo.getDigestEncryptionAlgorithm();
+        final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
 
         String alg = null;
         Signature sig = null;
 
-        if (deaOid != null) {
-            alg = deaOid;
-            try {
-                sig = Signature.getInstance(alg);
-            } catch (NoSuchAlgorithmException e) {
-            }
-
-            final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
-            if (sig == null && deaName != null) {
-                alg = deaName;
-                try {
-                    sig = Signature.getInstance(alg);
-                } catch (NoSuchAlgorithmException e) {
-                }
-            }
-        }
-
-        if (sig == null && daOid != null && deaOid != null) {
+        if (daOid != null && deaOid != null) {
             alg = daOid + "with" + deaOid;
             try {
                 sig = Signature.getInstance(alg);
@@ -153,8 +137,7 @@
             }
 
             // Try to convert to names instead of OID.
-            if (sig == null) {
-                final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
+            if (sig == null && daName != null && deaName != null) {
                 alg = daName + "with" + deaName;
                 try {
                     sig = Signature.getInstance(alg);
@@ -163,6 +146,22 @@
             }
         }
 
+        if (sig == null && deaOid != null) {
+            alg = deaOid;
+            try {
+                sig = Signature.getInstance(alg);
+            } catch (NoSuchAlgorithmException e) {
+            }
+
+            if (sig == null) {
+                alg = deaName;
+                try {
+                    sig = Signature.getInstance(alg);
+                } catch (NoSuchAlgorithmException e) {
+                }
+            }
+        }
+
         // We couldn't find a valid Signature type.
         if (sig == null) {
             return null;