Can't verify ECDSA signature in Python which generated in Android Studio(Kotlin)

108 views Asked by At

I generate an ECDSA PKI and a signature. I need to verify the signature in Python. But the verifier I make in Python can't verify the signature from android.

This is the code I use to generate the PKI and signature. I use secp256r1 curve and "SHA256withECDSA" option.

// Generate key store
keyStore = KeyStore.getInstance("AndroidKeyStore").apply {
    load(null)
}

// Set Key spec for Alice
val paramSpec = KeyGenParameterSpec.Builder(
    aliasAlice,
    KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
).run {
    setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))
    setDigests(
        KeyProperties.DIGEST_SHA512,
        KeyProperties.DIGEST_SHA256
    )
    setUserAuthenticationRequired(false)
    build()
}

val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
    KeyProperties.KEY_ALGORITHM_EC,
    "AndroidKeyStore"
)

kpg.initialize(paramSpec)

val privateKey = keyStore.getKey(aliasAlice, null) as PrivateKey
val publicKey = keyStore.getCertificate(aliasAlice).publicKey

val signature : ByteArray = Signature.getInstance("SHA256withECDSA").run {
    initSign(privateKey)
    update("random text".toByteArray())
    sign()
}

I export public key in PER format and import it to python Public Key example

-----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH4OjpeXBF0pEQ6gytvxV+7qbyEQo
    b7TgeMWjX7xs
    hTkaXh6PKAFYmnjE3qeY3xgMfZQunRpuba5IeZyKp3PhZg==
-----END PUBLIC KEY-----

Signature example(Hex string)

"3045022100868161225C1620215BFB65B7CB797CB3D6E0B9DA0FB355FDD2A1595ECC2D229202205AD3C651826DBD0834F76E6F596363C576B489F45FFA2E77A06F3C1B6BF541AC"

Before verify in python I try to decode asn1 DER of the signature. Because pycryptodom want 64byte length signature but my signature length is 70-72byte. So I manually make a decoder for it.

[Rule]

  • 6 byte | DER encoding overhead
  • 32 byte | r-value
  • (1 byte) | r-value padding (if needed)
  • 32 byte | S-value
  • (1 byte) | S-value padding (if needed)
  • 1 byte | Signature Hash
# Decoder for signature
def der_decoder(signature):
    len_r = int(signature[6:8], 16)
    if len_r == 32:
        hex_r = signature[8:72]
    else:
        hex_r = signature[10:74]
    hex_s = signature[-64:]
    return hex_r+hex_s

Verify code in Python

from Crypto.Hash import SHA256
from Crypto.PublicKey import ECC
from Crypto.Signature import DSS

# import public key & generate verifier
public_key = ECC.import_key(publicKey)
verifier = DSS.new(public_key, 'fips-186-3')

# signed message
message = bytes("random text", 'ascii')
hashed_message = SHA256.new(message)

decoded_signature = der_decoder.der_decoder(hex_string_signature)
ba_signature = hex2ba(decoded_signature)
signature = bytes.fromhex(decoded_signature)

print(verifier.verify(hashed_message, signature))

The python code doesn't make any error, but the verifier said the signature is not valid.(It print out False). I don't know how to fix it.... I would appreciate it if you could give me any advice.

0

There are 0 answers