示例#1
0
    def __init__(self,
                 crv: Union[Type['CoseCurve'], str, int],
                 x: bytes = b'',
                 d: bytes = b'',
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        """
        Create an COSE OKP key.

        :param crv: An OKP elliptic curve.
        :param x: Public value of the OKP key.
        :param d: Private value of the OKP key.
        :param optional_params: A dictionary with optional key parameters.
        :param allow_unknown_key_attrs: Allow unknown key attributes (not registered at the IANA registry)
        """

        transformed_dict = {KpKty: KtyOKP}

        if optional_params is None:
            optional_params = {}

        for _key_attribute, _value in optional_params.items():
            try:
                # translate the key_attribute
                kp = OKPKeyParam.from_id(_key_attribute,
                                         allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtyOKP:
            raise CoseIllegalKeyType(
                f"Illegal key type in OKP COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(OKPKey, self).__init__(transformed_dict)

        if len(x) == 0 and len(d) == 0:
            raise CoseInvalidKey(
                "Either the public values or the private value must be specified"
            )

        if crv is not None:
            self.crv = crv
        else:
            raise CoseInvalidKey("COSE curve cannot be None")
        if x != b'':
            self.x = x
        if d != b'':
            self.d = d
示例#2
0
    def __init__(self,
                 crv: Union[Type['CoseCurve'], str, int],
                 x: bytes = b'',
                 y: bytes = b'',
                 d: bytes = b'',
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        transformed_dict = {}

        if len(x) == 0 and len(y) == 0 and len(d) == 0:
            raise CoseInvalidKey(
                "Either the public values or the private value must be specified"
            )

        if (len(x) == 0 and len(y) != 0) or (len(x) != 0 and len(y) == 0):
            raise CoseInvalidKey("Missing public coordinate X/Y")

        new_dict = dict({KpKty: KtyEC2, EC2KpCurve: crv})

        if len(x) != 0 and len(y) != 0:
            new_dict.update({EC2KpX: x, EC2KpY: y})
        if len(d) != 0:
            new_dict.update({EC2KpD: d})

        if optional_params is not None:
            new_dict.update(optional_params)

        for _key_attribute, _value in new_dict.items():
            try:
                # translate the key_attribute
                kp = EC2KeyParam.from_id(_key_attribute,
                                         allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtyEC2:
            raise CoseIllegalKeyType(
                f"Illegal key type in EC2 COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(EC2Key, self).__init__(transformed_dict)
示例#3
0
 def k(self, k: bytes):
     if type(k) is not bytes:
         raise ValueError("SymKpK parameter must be of type 'bytes'")
     if len(k) not in [16, 24, 32]:
         raise CoseInvalidKey(
             "Key length should be either 16, 24, or 32 bytes")
     self.store[SymKpK] = k
示例#4
0
 def k(self) -> bytes:
     """ Returns the mandatory :class:`~cose.keys.keyparam.SymKpK` attribute of the COSE Symmetric Key object. """
     if SymKpK in self.store:
         return self.store[SymKpK]
     else:
         raise CoseInvalidKey(
             "Symmetric COSE key must have the SymKpK attribute")
示例#5
0
 def __delitem__(self, key):
     if self._key_transform(key) != KpKty and self._key_transform(
             key) != SymKpK:
         super().__delitem__(key)
     else:
         raise CoseInvalidKey(
             f"Deleting {key} attribute would lead to an invalide COSE Symmetric Key"
         )
示例#6
0
    def key(self, key: Optional['CK']):
        if not isinstance(key, SymmetricKey) and \
                not isinstance(key, EC2Key) and \
                not isinstance(key, OKPKey) and \
                not isinstance(key, RSAKey) and \
                key is not None:

            raise CoseInvalidKey(f"Unknown key type: {type(key)}")
        else:
            self._key = key
示例#7
0
    def crv(self) -> Optional[Type['CoseCurve']]:
        """
        Returns the mandatory :class:`~cose.keys.keyparam.OKPKpCurve` attribute of the COSE OKP Key object.
        """

        if OKPKpCurve in self.store:
            return self.store[OKPKpCurve]
        else:
            raise CoseInvalidKey(
                "OKP COSE key must have the OKP KpCurve attribute")
示例#8
0
    def __delitem__(self, key: Union['KeyParam', str, int]):
        if self._key_transform(key) != KpKty and self._key_transform(
                key) != OKPKpCurve:
            if self._key_transform(key) == OKPKpD and OKPKpX not in self.store:
                pass
            if self._key_transform(key) == OKPKpX and OKPKpD not in self.store:
                pass
            else:
                return super(OKPKey, self).__delitem__(key)

        raise CoseInvalidKey(
            f"Deleting {key} attribute would lead to an invalid COSE OKP Key")
示例#9
0
    def from_dict(cls, cose_key: dict) -> 'EC2Key':
        """
        Returns an initialized COSE Key object of type EC2Key.

        :param cose_key: Dict containing COSE Key parameters and there values.
        :return: an initialized EC2Key key
        """

        if EC2KpX in cose_key:
            x = cose_key[EC2KpX]
        elif EC2KpX.identifier in cose_key:
            x = cose_key[EC2KpX.identifier]
        elif EC2KpX.fullname in cose_key:
            x = cose_key[EC2KpX.fullname]
        else:
            x = b''

        if EC2KpY in cose_key:
            y = cose_key[EC2KpY]
        elif EC2KpY.identifier in cose_key:
            y = cose_key[EC2KpY.identifier]
        elif EC2KpY.fullname in cose_key:
            y = cose_key[EC2KpY.fullname]
        else:
            y = b''

        if EC2KpD in cose_key:
            d = cose_key[EC2KpD]
        elif EC2KpD.identifier in cose_key:
            d = cose_key[EC2KpD.identifier]
        elif EC2KpD.fullname in cose_key:
            d = cose_key[EC2KpD.fullname]
        else:
            d = b''

        if EC2KpCurve in cose_key:
            curve = cose_key[EC2KpCurve]
        elif EC2KpCurve.identifier in cose_key:
            curve = cose_key[EC2KpCurve.identifier]
        elif EC2KpCurve.fullname in cose_key:
            curve = cose_key[EC2KpCurve.fullname]
        else:
            raise CoseInvalidKey(
                "COSE EC2 Key must have an EC2KpCurve attribute")

        return cls(crv=curve,
                   x=x,
                   y=y,
                   d=d,
                   optional_params=cose_key,
                   allow_unknown_key_attrs=True)
示例#10
0
    def __delitem__(self, key):
        if self._key_transform(key) != KpKty and self._key_transform(
                key) != EC2KpCurve:
            if self._key_transform(key) == EC2KpD and (
                    EC2KpY not in self.store or EC2KpX not in self.store):
                pass
            elif self._key_transform(
                    key) == EC2KpX and EC2KpD not in self.store:
                pass
            elif (self._key_transform(key) == EC2KpX or
                  self._key_transform(key) == EC2KpY) and EC2KpD in self.store:
                super(EC2Key, self).__delitem__(EC2KpX)
                super(EC2Key, self).__delitem__(EC2KpY)
                return
            else:
                return super(EC2Key, self).__delitem__(key)

        raise CoseInvalidKey(
            f"Deleting {key} attribute would lead to an invalid COSE EC2 Key")
示例#11
0
    def from_dict(cls, cose_key: dict) -> 'SymmetricKey':
        """
        Returns an initialized COSE Key object of type SymmetricKey.

        :param cose_key: Dict containing COSE Key parameters and their values.

        :return: an initialized COSE SymmetricKey object
        """

        if SymKpK in cose_key:
            key_bytes = cose_key[SymKpK]
        elif SymKpK.identifier in cose_key:
            key_bytes = cose_key[SymKpK.identifier]
        elif SymKpK.fullname in cose_key:
            key_bytes = cose_key[SymKpK.fullname]
        else:
            raise CoseInvalidKey(
                "COSE Symmetric Key must have an SymKpK attribute")

        return cls(k=key_bytes,
                   optional_params=cose_key,
                   allow_unknown_key_attrs=True)
示例#12
0
    def __init__(self,
                 k: bytes,
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        transformed_dict = {}

        if len(k) not in [16, 24, 32]:
            raise CoseInvalidKey(
                "Key length should be either 16, 24, or 32 bytes")

        new_dict = dict({KpKty: KtySymmetric, SymKpK: k})

        if optional_params is not None:
            new_dict.update(optional_params)

        for _key_attribute, _value in new_dict.items():
            try:
                # translate the key_attribute
                kp = SymmetricKeyParam.from_id(_key_attribute,
                                               allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtySymmetric:
            raise CoseIllegalKeyType(
                f"Illegal key type in Symmetric COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(SymmetricKey, self).__init__(transformed_dict)
示例#13
0
    def __init__(self,
                 k: bytes,
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        transformed_dict = {KpKty: KtySymmetric}

        if optional_params is None:
            optional_params = {}

        for _key_attribute, _value in optional_params.items():
            try:
                # translate the key_attribute
                kp = SymmetricKeyParam.from_id(_key_attribute,
                                               allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtySymmetric:
            raise CoseIllegalKeyType(
                f"Illegal key type in Symmetric COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(SymmetricKey, self).__init__(transformed_dict)

        if k != b'':
            self.k = k
        else:
            raise CoseInvalidKey("SymKpK parameter cannot be None")
示例#14
0
    def __init__(self,
                 crv: Union[Type['CoseCurve'], str, int],
                 x: bytes = b'',
                 y: bytes = b'',
                 d: bytes = b'',
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        """Initialize a COSE key from its components

        Not passing a `y` component is accepted; in this case, one (of the two)
        valid `y` will be found for the `x`. This is good enough for everything
        that only operates on the `x` of any derived outputs (in "compact"
        mode), as per RFC 6090 Section 4.2.
        """
        transformed_dict = {KpKty: KtyEC2}

        if optional_params is None:
            optional_params = {}

        for _key_attribute, _value in optional_params.items():
            try:
                # transform the key_attribute
                kp = EC2KeyParam.from_id(_key_attribute,
                                         allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtyEC2:
            raise CoseIllegalKeyType(
                f"Illegal key type in EC2 COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(EC2Key, self).__init__(transformed_dict)

        if crv is not None:
            self.crv = crv
        else:
            raise CoseInvalidKey("COSE curve cannot be None")

        if not x and not y and not d:
            raise CoseInvalidKey(
                "Either the public values or the private value must be specified"
            )

        if not d and not x:
            raise CoseInvalidKey("Missing public coordinate X")

        if d:
            public_nums = ec.derive_private_key(
                int.from_bytes(d, byteorder="big"),
                curve=self.crv.curve_obj()).public_key().public_numbers()
            if x:
                assert x == public_nums.x.to_bytes(self.crv.size, 'big')
            else:
                x = public_nums.x.to_bytes(self.crv.size, 'big')

            if y:
                assert y == public_nums.y.to_bytes(self.crv.size, 'big')
            else:
                y = public_nums.y.to_bytes(self.crv.size, 'big')

        if x and not y:
            # try to derive y from x
            key = ec.EllipticCurvePublicKey.from_encoded_point(
                self.crv.curve_obj(),
                # don't care which of the two possible Y values we get
                b'\x03' + x  # or [::-1]?
            )
            # Just to check the endianness of the conversions -- if we get the
            # right X back out, then the X and Y are consistent, and anyway the
            # crypto backend will check whether the point is on the curve
            assert x == key.public_numbers().x.to_bytes(self.crv.size, 'big')
            y = key.public_numbers().y.to_bytes(self.crv.size, 'big')

        if x != b'':
            self.x = x
        if y != b'':
            self.y = y
        if d != b'':
            self.d = d
示例#15
0
    def __init__(self,
                 n: bytes = b'',
                 e: bytes = b'',
                 d: bytes = b'',
                 p: bytes = b'',
                 q: bytes = b'',
                 dp: bytes = b'',
                 dq: bytes = b'',
                 qinv: bytes = b'',
                 other: Optional[List[dict]] = None,
                 r_i: bytes = b'',
                 d_i: bytes = b'',
                 t_i: bytes = b'',
                 optional_params: Optional[dict] = None,
                 allow_unknown_key_attrs: bool = True):
        transformed_dict = {KpKty: KtyRSA}

        if other is None:
            other = []

        if optional_params is None:
            optional_params = {}

        # public key, n and e must be defined
        if len(n) != 0 and len(e) != 0 and all(
                map(lambda x: len(x) == 0,
                    [d, p, q, dp, dq, qinv, other, r_i, d_i, t_i])):
            is_valid_key = True

        # private keys with two primes, except other, r_i, t_i and d_i, all other parameters need to be defined
        elif all(map(lambda x: len(x) == 0, [other, r_i, t_i, d_i])) and \
                all(map(lambda x: len(x) != 0, [n, e, d, p, q, dp, dq, qinv])):
            is_valid_key = True

        # private keys with more than two primes, everything needs to be defined
        elif all(
                map(lambda x: len(x) != 0,
                    [n, e, d, p, q, dp, dq, qinv, other, r_i, d_i, t_i])):
            is_valid_key = True
            # TODO: verify contents of other
        else:
            is_valid_key = False

        if not is_valid_key:
            raise CoseInvalidKey(
                "Invalid RSA key: not a public key, private key with two primes or private key "
                "with more than two primes")

        for _key_attribute, _value in optional_params.items():
            try:
                # transform the key_attribute
                kp = RSAKeyParam.from_id(_key_attribute,
                                         allow_unknown_key_attrs)

                # parse the value of the key attribute if possible
                if hasattr(kp, 'value_parser') and hasattr(
                        kp.value_parser, '__call__'):
                    _value = kp.value_parser(_value)

                # store in new dict
                transformed_dict[kp] = _value
            except ValueError:
                transformed_dict[_key_attribute] = _value

        # final check if key type is correct
        if transformed_dict.get(KpKty) != KtyRSA:
            raise CoseIllegalKeyType(
                f"Illegal key type in RSA COSE Key: {transformed_dict.get(KpKty)}"
            )

        super(RSAKey, self).__init__(transformed_dict)

        self.e = e
        self.n = n

        if d != b'':
            self.d = d
        if p != b'':
            self.p = p
        if q != b'':
            self.q = q
        if dp != b'':
            self.dp = dp
        if dq != b'':
            self.dq = dq
        if qinv != b'':
            self.qinv = qinv
        if other:
            self.other = other
        if r_i != b'':
            self.r_i = r_i
        if d_i != b'':
            self.d_i = d_i
        if t_i != b'':
            self.t_i = t_i