Exemplo n.º 1
0
    def generate_key(
            algorithm: CoseAlgorithms,
            key_ops: KeyOps,
            curve_type: CoseEllipticCurves = CoseEllipticCurves.X25519
    ) -> 'OKP':
        """
        Generate a random OKP COSE key object.

        :param algorithm: Specify the CoseAlgorithm to use.
        :param key_ops: Specify the key operation (KeyOps).
        :param curve_type: Specify curve, must be X25519 or X448.
        """

        if curve_type == CoseEllipticCurves.X25519:
            private_key = X25519PrivateKey.generate()
        elif curve_type == CoseEllipticCurves.X448:
            private_key = X448PrivateKey.generate()
        else:
            raise CoseIllegalCurve(
                f"curve must be of type {CoseEllipticCurves.X25519} or {CoseEllipticCurves.X448}"
            )

        encoding = Encoding(serialization.Encoding.Raw)
        private_format = PrivateFormat(serialization.PrivateFormat.Raw)
        public_format = PublicFormat(serialization.PublicFormat.Raw)
        encryption = serialization.NoEncryption()

        return OKP(alg=CoseAlgorithms(algorithm),
                   key_ops=KeyOps(key_ops),
                   crv=CoseEllipticCurves(curve_type),
                   x=private_key.public_key().public_bytes(
                       encoding, public_format),
                   d=private_key.private_bytes(encoding, private_format,
                                               encryption))
Exemplo n.º 2
0
 def crv(self, crv: Union[Type['CoseCurve'], int, str]):
     supported_curves = {X25519, X448, Ed25519, Ed448}
     if not self._supported_by_key_type(crv, supported_curves):
         raise CoseIllegalCurve(
             f"Invalid COSE curve {crv} for key type {OKPKey.__name__}")
     else:
         self.store[OKPKpCurve] = CoseCurve.from_id(crv)
Exemplo n.º 3
0
    def verify(self,
               to_be_verified: bytes,
               signature: bytes,
               alg: Optional[CoseAlgorithms] = None,
               curve: Optional[CoseEllipticCurves] = None) -> bool:
        """
        Verifies the digital signature over 'to_be_verified'. The parameter 'alg' and 'curve' parameters are optional in
        case they are already provided by the key object self.

        :param to_be_verified: Data that was signed.
        :param signature: Signature to verify.
        :param alg: An optional algorithm parameter.
        :param curve: An optional curve
        :return: True when the signature is valid and False if the signature is invalid.
        """

        self._check_key_conf(algorithm=alg,
                             key_operation=KeyOps.VERIFY,
                             curve=curve)

        if self.crv == CoseEllipticCurves.ED25519:
            vk = Ed25519PublicKey.from_public_bytes(self.x)
        elif self._crv == CoseEllipticCurves.ED448:
            vk = Ed448PublicKey.from_public_bytes(self.x)
        else:
            raise CoseIllegalCurve(
                f"Illegal curve for OKP singing: {self.crv}")

        try:
            vk.verify(signature, to_be_verified)
            return True
        except InvalidSignature:
            return False
Exemplo n.º 4
0
    def sign(self,
             to_be_signed: bytes,
             alg: Optional[CoseAlgorithms] = None,
             curve: CoseEllipticCurves = None) -> bytes:
        """
        Computes a digital signature over 'to_be_signed'. The parameter 'alg' and 'curve' parameters are optional in
        case they are already provided by the key object self.

        :param to_be_signed: Data over which the signature is calculated.
        :param alg: An optional algorithm parameter.
        :param curve: An optional curve parameter.
        :return: the signature over the COSE object.
        """

        self._check_key_conf(algorithm=alg,
                             key_operation=KeyOps.SIGN,
                             curve=curve)

        if self.crv == CoseEllipticCurves.ED25519:
            sk = Ed25519PrivateKey.from_private_bytes(self.d)
        elif self._crv == CoseEllipticCurves.ED448:
            sk = Ed448PrivateKey.from_private_bytes(self.d)
        else:
            raise CoseIllegalCurve(
                f"Illegal curve for OKP singing: {self.crv}")

        return sk.sign(to_be_signed)
Exemplo n.º 5
0
    def shared_secret(private_key: 'CK', public_key: 'CK') -> bytes:
        """ Compute the shared secret. """

        if public_key.crv == X25519:
            d = X25519PrivateKey.from_private_bytes(private_key.d)
            x = X25519PublicKey.from_public_bytes(public_key.x)
            secret = d.exchange(x)
        elif public_key.crv == X448:
            d = X448PrivateKey.from_private_bytes(private_key.d)

            x = X448PublicKey.from_public_bytes(public_key.x)
            secret = d.exchange(x)
        elif public_key.crv == P256:
            d = ec.derive_private_key(int(hexlify(private_key.d), 16),
                                      SECP256R1(), default_backend())

            x = ec.EllipticCurvePublicNumbers(int(hexlify(public_key.x), 16),
                                              int(hexlify(public_key.y), 16),
                                              SECP256R1())
            x = x.public_key()
            secret = d.exchange(ec.ECDH(), x)
        else:
            raise CoseIllegalCurve(f"{public_key.crv} is unsupported")

        return secret
Exemplo n.º 6
0
    def _ecdh(cls, curve: 'CoseCurve', private_key: 'EC2', public_key: 'EC2') -> bytes:
        if curve == curves.P256():
            curve_instance = SECP256R1()
        elif curve == curves.P384():
            curve_instance = SECP384R1()
        elif curve == curves.P521():
            curve_instance = SECP521R1()
        else:
            raise CoseIllegalCurve()

        d_value = int(hexlify(private_key.d), 16)
        x_value = int(hexlify(public_key.x), 16)
        y_value = int(hexlify(public_key.y), 16)

        d = ec.derive_private_key(d_value, curve_instance, default_backend())
        p = ec.EllipticCurvePublicNumbers(x_value, y_value, curve_instance)
        p = p.public_key(default_backend())

        shared_key = d.exchange(ECDH(), p)
        return shared_key
Exemplo n.º 7
0
    def generate_key(crv: Union[Type['CoseCurve'], str, int],
                     optional_params: dict = None) -> 'OKPKey':
        """
        Generate a random OKPKey COSE key object.

        :param crv: Specify an elliptic curve.
        :param optional_params: Optional key attributes for the :class:`~cose.keys.okp.OKPKey` object, e.g., \
        :class:`~cose.keys.keyparam.KpAlg` or  :class:`~cose.keys.keyparam.KpKid`.

        :returns: A COSE `OKPKey` key.
        """

        if type(crv) == str or type(crv) == int:
            crv = CoseCurve.from_id(crv)

        if crv == X25519:
            private_key = X25519PrivateKey.generate()
        elif crv == Ed25519:
            private_key = Ed25519PrivateKey.generate()
        elif crv == Ed448:
            private_key = Ed448PrivateKey.generate()
        elif crv == X448:
            private_key = X448PrivateKey.generate()
        else:
            raise CoseIllegalCurve(
                f"Curve must be of type {X25519}, {X448}, {Ed25519}, or {Ed448}"
            )

        encoding = Encoding(serialization.Encoding.Raw)
        private_format = PrivateFormat(serialization.PrivateFormat.Raw)
        public_format = PublicFormat(serialization.PublicFormat.Raw)
        encryption = serialization.NoEncryption()

        return OKPKey(crv=crv,
                      x=private_key.public_key().public_bytes(
                          encoding, public_format),
                      d=private_key.private_bytes(encoding, private_format,
                                                  encryption),
                      optional_params=optional_params)
Exemplo n.º 8
0
    def shared_secret(private_key: Key, public_key: Key) -> bytes:
        """ Compute the shared secret. """

        if public_key.crv == CoseEllipticCurves.X25519:
            d = X25519PrivateKey.from_private_bytes(private_key.d)
            x = X25519PublicKey.from_public_bytes(public_key.x)
        elif public_key.crv == CoseEllipticCurves.X448:
            d = X448PrivateKey.from_private_bytes(private_key.d)
            x = X448PublicKey.from_public_bytes(public_key.x)
        elif public_key.crv == CoseEllipticCurves.P_256:
            d = ec.derive_private_key(int(hexlify(private_key.d), 16),
                                      config_cose(public_key.crv).curve[1](),
                                      default_backend())

            x = ec.EllipticCurvePublicNumbers(
                int(hexlify(public_key.x), 16), int(hexlify(public_key.y), 16),
                config_cose(public_key.crv).curve[1]())
        else:
            raise CoseIllegalCurve(f"{public_key.crv} is unsupported")

        secret = d.exchange(x)
        return secret
Exemplo n.º 9
0
    def generate_key(crv: Union[Type['CoseCurve'], str, int],
                     optional_params: dict = None) -> 'EC2Key':
        """
        Generate a random EC2Key COSE key object.

        :param crv: Specify an :class:`~cose.attributes.algorithms.CoseEllipticCurves`.
        :param optional_params: Optional key attributes for the :class:`~cose.keys.ec2.EC2Key` object, e.g., \
        :class:`~cose.keys.keyparam.KpAlg` or  :class:`~cose.keys.keyparam.KpKid`.

        :return: An COSE `EC2Key` key.
        """

        if type(crv) == str or type(crv) == int:
            crv = CoseCurve.from_id(crv)

        if crv == P256:
            curve_obj = SECP256R1()
        elif crv == P384:
            curve_obj = SECP384R1()
        elif crv == P521:
            curve_obj = SECP521R1()
        else:
            raise CoseIllegalCurve(f'Illegal COSE curve: {crv}')

        private_key = ec.generate_private_key(curve_obj,
                                              backend=default_backend())
        d_value = private_key.private_numbers().private_value
        x_coor = private_key.public_key().public_numbers().x
        y_coor = private_key.public_key().public_numbers().y

        return EC2Key(crv=crv,
                      d=d_value.to_bytes((d_value.bit_length() + 7) // 8,
                                         byteorder="big"),
                      x=x_coor.to_bytes((x_coor.bit_length() + 7) // 8,
                                        byteorder="big"),
                      y=y_coor.to_bytes((y_coor.bit_length() + 7) // 8,
                                        byteorder="big"),
                      optional_params=optional_params)
Exemplo n.º 10
0
 def crv(self, crv: Union[Type['CoseCurve'], int, str]):
     supported_curves = {P256, P384, P521, SECP256K1}
     if not self._supported_by_key_type(crv, supported_curves):
         raise CoseIllegalCurve("Invalid COSE curve attribute")
     else:
         self.store[EC2KpCurve] = CoseCurve.from_id(crv)