Signature Record¶
The NDEF Signature Record is a well-known record type defined by the NFC Forum. It contains three fields: a version field, a signature field and a certificate field.
The version field is static. Currently this implementation only supports v2.0 of the NDEF Signature Record.
The signature field contains the signature type, the message hash type and either the signature itself or a URI to the signature.
The certificate field contains the certificate format type, a certificate chain store and an option URI to the next certificate in the chain.
-
class
SignatureRecord(signature_type=None, hash_type='SHA-256', signature=b'', signature_uri='', certificate_format='X.509', certificate_store=[], certificate_uri='')¶ The
SignatureRecordclass decodes or encodes an NDEF Signature Record.Parameters: - signature_type (str) – initial value for the
signature_typeattribute, default None - hash_type (str) – initial value for the
hash_typeattribute, default ‘SHA-256’ - signature (bytes) – initial value for the
signatureattribute, default b’‘ - signature_uri (str) – initial value for the
signature_uriattribute, default ‘’ - certificate_format (str) – initial value for the
certificate_formatattribute, default ‘X.509’ - certificate_store (list) – initial value for the
certificate_storeattribute, default [] - certificate_uri (str) – initial value for the
certificate_uriattribute, default ‘’
-
type¶ The Signature Record type is
urn:nfc:wkt:Sig.
-
version¶ The version of the NDEF Signature Record.
-
signature_type¶ The signature type used in the signature algorithm.
>>> import ndef >>> print('\n'.join([str(x[1]) for x in ndef.signature.SignatureRecord()._mapping_signature_type])) None RSASSA-PSS-1024 RSASSA-PKCS1-v1_5-1024 DSA-1024 ECDSA-P192 RSASSA-PSS-2048 RSASSA-PKCS1-v1_5-2048 DSA-2048 ECDSA-P224 ECDSA-K233 ECDSA-B233 ECDSA-P256
-
hash_type¶ The hash type used in the signature algorithm.
>>> import ndef >>> print("\n".join([str(x[1]) for x in ndef.signature.SignatureRecord()._mapping_hash_type])) SHA-256
-
signature¶ The signature (if not specified by
signature_uri).
-
certificate_format¶ The format of the certificates in the chain.
>>> import ndef >>> print("\n".join([str(x[1]) for x in ndef.signature.SignatureRecord()._mapping_certificate_format])) X.509 M2M
-
certificate_store¶ A list of certificates in the certificate chain.
-
certificate_uri¶ The uniform resource identifier for the next certificate in the certificate chain.
This is default usage:
>>> import ndef >>> signature_record = ndef.SignatureRecord(None, 'SHA-256', b'', '', 'X.509', [], '')
This is a full example creating records, signing them and verifying them:
>>> import ndef >>> import io >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import hashes >>> from cryptography.hazmat.primitives.asymmetric import ec >>> from cryptography.hazmat.primitives.asymmetric import utils >>> from cryptography.exceptions import InvalidSignature >>> from asn1crypto.algos import DSASignature
>>> private_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) >>> public_key = private_key.public_key()
>>> r1 = ndef.UriRecord("https://example.com") >>> r2 = ndef.TextRecord("TEST")
>>> stream = io.BytesIO() >>> records = [r1, r2, ndef.SignatureRecord("ECDSA-P256", "SHA-256")] >>> encoder = ndef.message_encoder(records, stream) >>> for _ in range(len(records) - 1): e=next(encoder)
>>> signature = private_key.sign(stream.getvalue(), ec.ECDSA(hashes.SHA256())) >>> records[-1].signature = DSASignature.load(signature, strict=True).to_p1363() >>> e=next(encoder) >>> octets = stream.getvalue()
>>> records_verified = [] >>> records_to_verify = [] >>> known_types = {'urn:nfc:wkt:Sig': ndef.signature.SignatureRecord} >>> for record in ndef.message_decoder(octets, known_types=known_types): ... if not record.type == 'urn:nfc:wkt:Sig': ... records_to_verify.append(record) ... else: ... stream_to_verify = io.BytesIO() ... encoder_to_verify = ndef.message_encoder(records_to_verify + [record], stream_to_verify) ... for _ in range(len(records_to_verify)): e=next(encoder_to_verify) ... try: ... public_key.verify(DSASignature.from_p1363(record.signature).dump(), stream_to_verify.getvalue(), ec.ECDSA(hashes.SHA256())) ... records_verified.extend(records_to_verify) ... records_to_verify = [] ... except InvalidSignature: ... pass
>>> records_verified = list(ndef.message_decoder(b''.join(ndef.message_encoder(records_verified))))
- signature_type (str) – initial value for the