Проверка ECDSA Android с открытым ключом всегда возвращает false

У меня есть токен, и мне нужно сначала подписать его с помощью SHA256 и ECDSA на основе закрытого и открытого ключей из KeyStore.

Каждый раз, когда я пытаюсь проверить значение, я получаю ложный результат. Я не знаю, почему.

Есть ли у кого-нибудь идеи, как это решить?

Вот мои функции для создания и загрузки ключей:

private void generateKeys(){

    try {

        keyStore = KeyStore.getInstance(KEYSTORE_NAME);
        keyStore.load(null);

        if(!keyStore.containsAlias(KEY_NAME)) {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_NAME);
            keyPairGenerator.initialize(
                    new KeyGenParameterSpec.Builder(KEY_NAME,
                            KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                            .setDigests(KeyProperties.DIGEST_SHA256,
                                    KeyProperties.DIGEST_SHA512)
                            .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
                            .setUserAuthenticationRequired(false)
                            .build());
            keyPairGenerator.generateKeyPair();

            setRegistred(true);
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}



private void loadKeys(){
    try {
        keyStore = KeyStore.getInstance(KEYSTORE_NAME);
        keyStore.load(null);
        if(keyStore.containsAlias(KEY_NAME)) {
            publicKey = keyStore.getCertificate(KEY_NAME).getPublicKey();
            privateKey = (PrivateKey) keyStore.getKey(KEY_NAME, null);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    }
}

Вот как знаковое значение:

 public String sign(String inputStr, FingerprintManager.CryptoObject cryptoObject){
    try {
        Signature signature = Signature.getInstance(SecurityConstants.SIGNATURE);
        signature.initSign(privateKey);
        signature.update(inputStr.getBytes());
        byte[] signedBytes = signature.sign();
        String result = Base64.encodeToString(signedBytes, Base64.DEFAULT);
        Log.d("TAG", result);
        return result;
    } catch (SignatureException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

Вот моя попытка проверить с помощью открытого ключа:

public boolean verifyWithPublicKey(String input, FingerprintManager.CryptoObject cryptoObject){
    try {
        Signature signature = Signature.getInstance(SecurityConstants.SIGNATURE);
        keyStore = KeyStore.getInstance(KEYSTORE_NAME);
        keyStore.load(null);
        PublicKey pk  = getPublicKeyForVerification();
        signature.initVerify(pk);
        signature.update(input.getBytes());
        boolean isVerifed = signature.verify(input.getBytes());
        Log.d("TAG", String.valueOf(isVerifed));
        return isVerifed;
    } catch (SignatureException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}

person Zookey    schedule 26.08.2017    source источник


Ответы (1)


Ошибка здесь, когда вы пишете следующий код для проверки подписи:

signature.update(input.getBytes());
boolean isVerifed = signature.verify(input.getBytes());

С помощью этого кода вы пытаетесь проверить, что подпись была подписана самой собой!

У тебя должно быть:

signature.update(MY_BYTES_ARRAY_OF_DATA);
boolean isVerifed = signature.verify(MY_SIGNATURE);

Не забывайте, что подпись по умолчанию не инкапсулирует подписанные данные.

Если вы хотите иметь формат, включающий подписанные данные и связанную подпись, используйте S / MIME, OpenPGP и т. Д.

person Alexandre Fenyo    schedule 29.08.2017