首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于Android P的ECDSA数字签名验证

基于Android P的ECDSA数字签名验证
EN

Stack Overflow用户
提问于 2020-08-25 20:33:42
回答 1查看 472关注 0票数 3
代码语言:javascript
运行
复制
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上,我得到了这个异常。

代码语言:javascript
运行
复制
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.

因此,正如前面提到的,我尝试从这些语句中删除here参数,如下所示:

代码语言:javascript
运行
复制
Signature signature = Signature.getInstance("SHA256withECDSA");
KeyFactory keyFactory = KeyFactory.getInstance("EC");

但这并没有解决问题?怎么会这样?现在我得到了这个异常:

代码语言:javascript
运行
复制
java.security.InvalidKeyException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: Error parsing public key

可能的解决方案之一是将targetSdkVersion降低到27,但这还不够好。这个问题有没有更好的解决方案?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-26 04:32:03

我可以在我的机器上重现这个问题(Android P,API级别28)。该问题的一种可能的解决方案是在添加BC提供程序之前删除预安装的版本:

代码语言:javascript
运行
复制
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());

或者:

代码语言:javascript
运行
复制
Security.removeProvider("BC");
Security.insertProviderAt(new BouncyCastleProvider(), 1);

此外,必须显式指定BC提供程序:

代码语言:javascript
运行
复制
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
...
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");

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

与较低API级别相比的不同行为可能与Android P,here中实现的BC提供者相关的更改有关。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63578955

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档