尝试验证 CBOR 消息上的签名时出错

Error trying to verify signature on CBOR message

我在使用 COSE-JAVA 解码欧盟数字证书(“Covid pass”)时遇到问题。 Public 密钥似乎加载正常,但当我尝试验证 CBOR 消息时,出现以下错误:

COSE.CoseException: Signature verification failure
    at COSE.SignCommon.validateSignature(SignCommon.java:205)
    at COSE.Signer.validate(Signer.java:212)
    at COSE.Message.validate(Message.java:288)
Caused by: java.lang.NullPointerException: Attempt to get length of null array
    at COSE.SignCommon.convertConcatToDer(SignCommon.java:212)

验证代码如下:

public static String DecodeMessage(byte[] data) throws CoseException, CborParseException {
    Message m = Encrypt0Message.DecodeFromBytes(data);

    PublicKey key = getPublicKey("here goes PEM of public key");

    CborMap cborMap = CborMap.createFromCborByteArray(m.GetContent());

    CounterSign signer = new CounterSign();
    signer.setKey(new OneKey(key, null));
    signer.addAttribute(HeaderKeys.Algorithm, AlgorithmID.ECDSA_256.AsCBOR(), Attribute.ProtectedAttributes);

    // error happens here
    m.validate(signer);


    return cborMap.toJsonString();
}

这是从 PEM 生成 public 密钥的方式:

    public static PublicKey getPublicKey(String keyData) {
    try
    {
        Security.removeProvider("BC");
        Security.addProvider(new BouncyCastleProvider());
        Reader rdr = new StringReader(
                "-----BEGIN EC PUBLIC KEY-----\n" + keyData + "\n" + "-----END EC PUBLIC KEY-----\n"
        );

        org.bouncycastle.util.io.pem.PemObject spki = new org.bouncycastle.util.io.pem.PemReader(rdr).readPemObject();

        byte[] content = spki.getContent();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
        return KeyFactory.getInstance("EC", "BC").generatePublic(pubKeySpec);
    }
    catch (Exception ex)
    {
        return  null;
    }

Public 键定义为:

"publicKeyAlgorithm": {
  "hash": {
    "name": "SHA-256"
  },
  "name": "ECDSA",
  "namedCurve": "P-256"
},
"publicKeyPem": "..."

Here is code 在 Python 中做同样的事情,可能会对某人有所帮助。代码必须在 Android 7.1 上运行(嵌入式设备,无法升级到更新的 Android)。

已解决...

public static boolean VerifySignature(byte[] data, String publicKey) {
    boolean result = false;
    try {

        Message m = Encrypt0Message.DecodeFromBytes(data);
        Sign1Message sm = (Sign1Message) m;

        PublicKey key = getPublicKey(publicKey);

        if (sm.validate(new OneKey(key, null))) {
            result = true;
        }
    } catch (Exception ex) {
        log.error("Error verifying signature", ex);
    }
    return result;
}

    public static PublicKey getPublicKey(String keyData) {
    try {
        Security.removeProvider("BC");
        Security.addProvider(new BouncyCastleProvider());
        Reader rdr = new StringReader(
                "-----BEGIN EC PUBLIC KEY-----\n" + keyData + "\n" + "-----END EC PUBLIC KEY-----\n"
        );

        org.bouncycastle.util.io.pem.PemObject spki = new org.bouncycastle.util.io.pem.PemReader(rdr).readPemObject();

        byte[] content = spki.getContent();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
        return KeyFactory.getInstance("EC", "BC").generatePublic(pubKeySpec);
    } catch (Exception ex) {
        return null;
    }
}
ODqaG8mnbro=": {
        "serialNumber": "5dfefffd3a560d58",
        "subject": "C=BE, O=eHealth - Belgium, CN=Belgium Covid19 DSC 01",
        "issuer": "C=BE, O=eHealth - Belgium, CN=Belgium Covid19 Country Signing CA 01",
        "notBefore": "2021-05-27T10:12:47.000Z",
        "notAfter": "2023-05-27T10:12:47.000Z",
        "signatureAlgorithm": "ECDSA",
        "fingerprint": "2942d10907cf19f27aeb0dc391f35197c69dea87",
        "publicKeyAlgorithm": {
            "hash": {
                "name": "SHA-256"
            },
            "name": "ECDSA",
            "namedCurve": "P-256"
        },
        "publicKeyPem": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEU/f/KsmP3NasU/jZo7aulTrd9GHoznfnwWvX8xmHtK49EoobMAG7LhXnpLQ+aRwmmnSMcIWy8wPxM8QDMBUtyA=="
    }