119 lines
3.4 KiB
Python
119 lines
3.4 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# Testing SmartPGP applet up to a crash because of a memory leak
|
||
|
|
||
|
import os
|
||
|
from sys import path
|
||
|
import subprocess
|
||
|
import getpass
|
||
|
import hashlib
|
||
|
import tempfile
|
||
|
|
||
|
|
||
|
path.append(".")
|
||
|
import OpenPGPpy
|
||
|
|
||
|
|
||
|
def sha256(data):
|
||
|
return hashlib.sha256(data).digest()
|
||
|
|
||
|
|
||
|
def pubkey_to_der(pubkey):
|
||
|
# Add ASN1 DER header (EC parameters)
|
||
|
# ECP 256 r1 header
|
||
|
header_hex = "3059301306072A8648CE3D020106082A8648CE3D030107034200"
|
||
|
return bytes.fromhex(header_hex + pubkey.hex())
|
||
|
|
||
|
|
||
|
def check_signature(msg, signature, pubkeyd):
|
||
|
pubkey = pubkey_to_der(pubkeyd)
|
||
|
fpk = tempfile.NamedTemporaryFile(delete=False)
|
||
|
fpk.write(pubkey)
|
||
|
fpk.close()
|
||
|
fsig = tempfile.NamedTemporaryFile(delete=False)
|
||
|
fsig.write(signature)
|
||
|
fsig.close()
|
||
|
verify_cmd = (
|
||
|
f"openssl dgst -sha256 -keyform DER -verify {fpk.name} -signature {fsig.name}"
|
||
|
)
|
||
|
sigOK = False
|
||
|
try:
|
||
|
subprocess.run(
|
||
|
verify_cmd, input=msg, shell=True, check=True, stdout=subprocess.PIPE
|
||
|
)
|
||
|
sigOK = True
|
||
|
except Exception:
|
||
|
print("Error in signature verification")
|
||
|
print(">>> Requires openssl in path to check signatures")
|
||
|
sigOK = False
|
||
|
os.remove(fpk.name)
|
||
|
os.remove(fsig.name)
|
||
|
return sigOK
|
||
|
|
||
|
|
||
|
def main():
|
||
|
try:
|
||
|
# instanciated with (True) to enable debug mode
|
||
|
mydevice = OpenPGPpy.OpenPGPcard(True)
|
||
|
except OpenPGPpy.ConnectionException as exc:
|
||
|
print(exc)
|
||
|
return
|
||
|
print("OpenPGP device detected")
|
||
|
pubkey_card_all = None
|
||
|
try:
|
||
|
pubkey_card_all = mydevice.get_public_key("B600")
|
||
|
except OpenPGPpy.PGPCardException as exc:
|
||
|
# SW = 0x6581 or 0x6A88 ?
|
||
|
if exc.sw_code != 0x6581 and exc.sw_code != 0x6A88:
|
||
|
raise
|
||
|
# SIGn key was not created, continue to setup this key
|
||
|
if pubkey_card_all is None:
|
||
|
print("Setup the new device")
|
||
|
PIN3 = "12345678" #getpass.getpass("Enter PIN3 (PUK) : ")
|
||
|
try:
|
||
|
mydevice.verify_pin(3, PIN3)
|
||
|
except OpenPGPpy.PGPCardException as exc:
|
||
|
if exc.sw_code == 0x6982 or exc.sw_code == 0x6A80:
|
||
|
print("Error: Wrong PUK")
|
||
|
return
|
||
|
# Setup EC256r1 for SIG key
|
||
|
try:
|
||
|
mydevice.put_data("00C1", "132A8648CE3D030107")
|
||
|
except OpenPGPpy.PGPCardException as exc:
|
||
|
if exc.sw_code == 0x6A80:
|
||
|
raise Exception(
|
||
|
"This device is not compatible with ECDSA 256r1."
|
||
|
) from exc
|
||
|
raise
|
||
|
# Generate key for sign
|
||
|
pubkey_card_all = mydevice.gen_key("B600")
|
||
|
pubkey_card = pubkey_card_all[-65:]
|
||
|
print('Device "SIG" public key read')
|
||
|
|
||
|
PIN1 = "123456" #getpass.getpass("Enter PIN1 : ")
|
||
|
|
||
|
# Make 200 ECDSA
|
||
|
print(f"\nPublicKey for signature : 0x{pubkey_card.hex()}")
|
||
|
message = "Hello SmartPGP! Take that message.".encode("ascii")
|
||
|
hash = sha256(message)
|
||
|
for _ in range(200):
|
||
|
mydevice.verify_pin(1, PIN1)
|
||
|
sig_card = mydevice.sign_ec_der(hash)
|
||
|
print(f"Signature : 0x{sig_card.hex()}")
|
||
|
if check_signature(message, sig_card, pubkey_card):
|
||
|
print("OK")
|
||
|
else:
|
||
|
print("Can't check signature")
|
||
|
return
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
try:
|
||
|
main()
|
||
|
except OpenPGPpy.PGPCardException as exc:
|
||
|
if exc.sw_code == 0x6F00:
|
||
|
print("Crash, game over.")
|
||
|
print("SFYL !")
|
||
|
print(exc)
|