Skip to content

Return value in bytes if the attribute is not currently handled + add object dictionary for printing #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions pkcs11/_utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ cdef bytes _pack_attribute(key, value):


cdef _unpack_attributes(key, value):
"""Unpack a Attribute bytes array into a Python value."""
"""
Unpack a Attribute bytes array into a Python value.
For more custom translations, expand ATTRIBUTE_TYPES in defaults.py.
"""

try:
_, unpack = ATTRIBUTE_TYPES[key]
return unpack(bytes(value))
except KeyError:
raise NotImplementedError("Can't unpack this %s. "
"Expand ATTRIBUTE_TYPES!" % key)
return bytes(value)
58 changes: 58 additions & 0 deletions pkcs11/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from threading import RLock
from binascii import hexlify
from base64 import b64encode

from cached_property import cached_property

Expand All @@ -16,11 +17,13 @@
SlotFlag,
TokenFlag,
UserType,
CertificateType,
)
from .mechanisms import KeyType, Mechanism
from .exceptions import (
ArgumentsBad,
AttributeTypeInvalid,
AttributeSensitive,
NoSuchKey,
MultipleObjectsReturned,
SignatureInvalid,
Expand Down Expand Up @@ -621,6 +624,61 @@ def destroy(self):
The :class:`Object` is no longer valid.
"""
raise NotImplementedError()


def dict_for_print(self):
"""
This function returns dictionary with most of the object attribute types unchanged.
However, some of them can not be translated directly - in that case the dictionary value is a string explaining, what happened.
In the same fasion, bytes objects are base64 encoded for printing.

Returns:
dict: A dictionary where keys are the pkcs11.constants.Attributes names and values are original value objects OR
strings with <explanation> OR
base64 encoded bytes objects as strings.

"""
ret = {}
for attr in list(Attribute):
try:
attr_value = self[attr]
except AttributeTypeInvalid:
# Attribute is missing, that's fine.
pass
except AttributeSensitive:
# Attribute is sensitive, but we might still want information about the attribute existence.
ret[attr.name] = "<sensitive>"
except ValueError as e:
# Some bytes-encoded datetimes can't be parsed by Python datetime.datetime(), it might happen with other types as well.
# It depends on what exactly is stored on the token.
# (bytes value should be included in the error message)
ret[attr.name] = f"<ValueError: {e}>"
except NotImplementedError as e:
# Should not happened, kept here for legacy reasons. Might be removed in the future.
# Just in case, we want to atleast know that it happened.
ret[attr.name] = (
f"<NotImplementedError: {e} "
"(the number is pointing to the attribute name)>"
)
else: # (all known exceptions are handled)
attr_type = type(attr_value)

# If the result is member of the IntEnum, we want to know the name, not the number
if attr_type in (
ObjectClass,
CertificateType,
KeyType,
):
attr_value = attr_value.name
elif attr_type is bytes:
# Since all other value types are oriented mainly for printing
if attr_value == b"":
attr_value = "<empty byte array>"
else:
attr_value = b64encode(attr_value).decode("utf-8")

ret[attr.name] = attr_value
return ret


class DomainParameters(Object):
Expand Down