Android — Использование PHP / Python для проверки подписи ECDSA

Я пишу код для генерации подписи ECDSA на Android, используя spongycastle lib. Затем я отправляю подписывающую строку и открытый ключ на сервер (Ubuntu 16.04) и пытаюсь использовать php и python для проверки этого знака.

Я проверяю подтверждение на моем приложении для Android. Это сработало хорошо.

Я использую расширение php-openssl и с Python я использую ecdsa 0.13. Но оба этого не удалось. Я пытаюсь снова, используя команду openssl, и она не может проверить тоже.

Я не знаю, где я не прав.

Почему проверка ECDSA не проходит?


Вот мой код:

  1. Создать подпись (андроид):

    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1");
    try {
    KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA","SC");
    g.initialize(spec, new SecureRandom());
    KeyPair keyPair = g.generateKeyPair();
    privateKey = keyPair.getPrivate();
    publicKey = keyPair.getPublic();
    ///write public key to pem file
    ......
    FileOutputStream fileOutputStream1 = new FileOutputStream(file1);
    StringWriter writer1 = new StringWriter();
    PemWriter pemWriter1 = new PemWriter(writer1);
    pemWriter1.writeObject(new PemObject("PUBLIC KEY",publicKey.getEncoded()));
    pemWriter1.flush();
    pemWriter1.close();
    String publickeyPem = writer1.toString();
    fileOutputStream1.write(publickeyPem.getBytes());
    fileOutputStream1.close();
    } catch (Exception e) {
    e.printStackTrace();}
    ......
    //Sign and veryfied
    String chuoi = txtChuoi.getText().toString();
    byte[] chuoiInput = chuoi.getBytes("UTF-8");
    Signature sig = Signature.getInstance("NONEwithECDSA","SC");
    sig.initSign(privateKey);
    sig.update(chuoiInput);
    ///SIGN
    byte[] signatureBytes = sig.sign()
    txtMaHoa.setText(Base64.encodeToString(signatureBytes,Base64.DEFAULT));
    sig.initVerify(publicKey);
    sig.update(chuoiInput);
    ///VERIFIED
    txtGiaiMa.setText(sig.verify(signatureBytes)+"");
    ///Write string sign in txtMahoa to file
    .......
    
  2. Выходные данные У меня есть Подпись и publickey:

    (Signature string) MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9j iAT1x0q2C5Mdu+2aZKtN
    

    (PublicKey)

    -----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEj07XEM+ulPyrdsfAf9prN2L2dNUd /Yy0rABcFdueAwYUf86f8Cc93Ws6sxzIvf2iKOapFby7EjHewjhLM/z7Qg==
    -----END PUBLIC KEY-----
    
  3. Проверьте с помощью PHP:

    $pubkeyid = openssl_pkey_get_public("/var/www/html/ca.pem");
    
    $data = "nguyen tran thanh Lam";
    
    $signature =
    "MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9jiAT1x0q2C5Mdu+2aZKtN";
    $ok = openssl_verify($data, $signature, $pubkeyid);
    if ($ok == 1) {
    echo "good";
    } elseif ($ok == 0) {
    echo "bad";
    } else {
    echo "ugly, error checking signature";
    }
    ?>
    

1

Решение

Комментарий: … но функция проверки ничего не возвращает. Так что я не уверен

Если crypto.verify(... не выдавайте ошибку, это означает, что проверка в порядке. Смотрите обновленный код ниже.
Подтвердите, используя НЕПРАВИЛЬНЫЙ Сертификат, Подпись или Данные.


Комментарий: что вы думаете о добавлении base64.b64decode. … потому что в коде Android у меня есть это linetxtMaHoa.setText(Base64.encodeToString(signatureBytes,Ba‌​se64.DEFAULT));

PEM уже base64проверьте, если выше .setText(Base64... можно опустить. На данный момент я обновил код ниже с base64.b64decode,


ВопросПример —- b «sha256»? «b» — это двоичный файл (встроенная функция или я должен преобразовать строку sha256 в двоичный файл?)

У меня работает только как String (DIGEST-имена), например:

import pem, base64
from OpenSSL import crypto

signature  = b"MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9jiAT1x0q2C5Mdu+2aZKtN"
# As Creator of the Signatur do additional base64 encoding!
signature = base64.b64decode(signature)

data = "nguyen tran thanh Lam"
certificate = pem.parse_file('Android.pem')[0]
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate.as_bytes())

try:
crypto.verify(cert=cert, signature=signature, data=data, digest='sha256')
except crypto.Error as exp:
print('crypto.Error:{}'.format(exp.args))

>>>crypto.Error:([('', 'ECDSA_do_verify', 'bad signature')],)

Заметка: Броски crypto.Error потому что не используя certificate который создал signature,


OpenSSL.crypto.verify (сертификат, подпись, данные, дайджест)

Проверьте подпись для строки данных.
сертификат — это экземпляр X509, соответствующий закрытому ключу, который сгенерировал подпись.
signature — это экземпляр str, дающий саму подпись.
data — это экземпляр str, содержащий данные, к которым применяется подпись.
digest — это экземпляр str с именем типа подписи сообщения подписи, например, b «sha256».

Новое в версии 0.11.

2

Другие решения

Других решений пока нет …