In my app I need to verify a signature. An example is below. It works perfectly on Android 6 and older versions but just recently I noticed that it doesn't work on Android 7 or 8. When I run verifyData()
I get this exception:
java.security.SignatureException: error decoding signature bytes.
at com.android.org.bouncycastle.jcajce.provider.asymmetric.util.DSABase.engineVerify(DSABase.java:82)
at java.security.Signature$Delegate.engineVerify(Signature.java:1380)
at java.security.Signature.verify(Signature.java:806)
What has been changed in these Android version that I don't know? How to verify signatures on Android 7 or later version?
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import java.io.Reader;
import java.io.StringReader;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
public class Test {
static final String PUBLIC_KEY =
"-----BEGIN PUBLIC KEY-----\n" +
"MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEXMHnQfWiM4oCaLfx296llgz7iaVv\n" +
"avMPppkzVNZAxtlNLhFlXnNWD0Mw9yzP8/Go\n" +
"-----END PUBLIC KEY-----\n";
static final String DATA = "0443607A263B8001484E4C310100010561186AF1398003000000000000000000000001";
static final String SIGNATURE = "303402181938B3C6FE3EFE75E1B1DF42D8E54055E07D6A5542E9ED3A021816AB6B9D1E5AF55E0E3E0B3E1A4DEA5EC4A120AFC6D51FE60000000000000000000000000000";
static boolean verifyData() throws Exception {
PublicKey pk = getPublicKey();
byte[] data = hexToBytes(DATA);
byte[] signatureBytes = hexToBytes(SIGNATURE);
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initVerify(pk);
signature.update(data);
return signature.verify(signatureBytes);
}
static PublicKey getPublicKey() throws Exception {
Security.addProvider(new BouncyCastleProvider());
Reader reader = new StringReader(PUBLIC_KEY);
PemObject pemObject = new PemReader(reader).readPemObject();
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pemObject.getContent());
PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
return key;
}
static byte[] hexToBytes(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
Dependency I use:
compile group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46'