Android P上的ECDSA数字签名验证 [英] ECDSA Digital Signature Verification on Android P

查看:217
本文介绍了Android P上的ECDSA数字签名验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import android.os.Bundle;
import android.util.Base64;
import android.widget.Toast;
import org.bouncycastle.jce.provider.BouncyCastleProvider; // implementation 'org.bouncycastle:bcprov-jdk16:1.46'
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    static final String PUBLIC_KEY = "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMEV3EPREEDc0t4MPeuYgreLMHMVfD7iYJ2Cnkd0ucwf3GYVySvYTttMVMNMEKF554NYmdrOlqwo2s8J2tKt/oQ==";

    static final String DATA = "Hello";

    static final String SIGNATURE = "MEUCIQCsuI4OcBAyA163kiWji1lb7xAtC8S0znf62EpdA+U4zQIgBcLbXtcuxXHcwQ9/DmiVfoiigKnefeYgpVXZzjIuYn8=";

    static boolean verifyData() throws Exception {
        PublicKey pk = getPublicKey();
        byte[] signatureBytes = Base64.decode(SIGNATURE, Base64.NO_WRAP);

        Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
        signature.initVerify(pk);
        signature.update(DATA.getBytes("UTF-8"));
        return signature.verify(signatureBytes);
    }

    static PublicKey getPublicKey() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(PUBLIC_KEY, Base64.NO_WRAP));
        PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
        return key;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            Toast.makeText(this, verifyData() + "", Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            Toast.makeText(this, "Failure: " + e.getMessage(), Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
    }

}

上面的代码执行ECDSA数字签名验证.这段代码在Android P以下的每个Android版本上均能正常工作.在Android P上,我会遇到此异常.

The code above performs ECDSA digital signature verification. This code works fine on every android version below Android P. On Android P I get this exception.

java.security.NoSuchAlgorithmException: The BC provider no longer provides an implementation for Signature.SHA1withRSA. Please see https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html for more details.

因此,如此处我试图从这些语句中删除提供者参数,如下所示:

So as mentioned here I tried to remove the provider parameter from these statements like this:

Signature signature = Signature.getInstance("SHA256withECDSA");
KeyFactory keyFactory = KeyFactory.getInstance("EC");

但是它没有解决问题?怎么来的?现在,我遇到了这个异常:

But it didn't solve the problem? How come? Now I'm getting this exception:

java.security.InvalidKeyException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: Error parsing public key

可能的解决方案之一是将targetSdkVersion降低到27,但这还不够好.有更好的解决方案吗?

One of the possible solutions is to lower targetSdkVersion to 27 but this not good enough. Is there a better solution to the problem?

推荐答案

我可以在计算机上重现该问题(Android P,API级别28).该问题的一种可能解决方案是在添加BC Provider之前删除预安装的版本:

I can reproduce the issue on my machine (Android P, API Level 28). One possible solution of the problem is to delete the pre-installed version before adding the BC Provider:

Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());

或者:

Security.removeProvider("BC");
Security.insertProviderAt(new BouncyCastleProvider(), 1);

此外,还必须明确指定BC Provider:

Additionally the BC Provider must be specified explicitly:

KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
...
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");

在这个星座中,可以验证签名.

In this constellation the signature can be verified.

与较低的API级别相比,不同的行为可能与在Android P中实现的有关BC Provider的更改有关,

The different behavior compared to lower API levels might be related to the changes concerning the BC Provider that were implemented in Android P, here.

这篇关于Android P上的ECDSA数字签名验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆