예제 #1
0
    def x25519_key_derivation(
            self,
            public_key: 'OKP',
            context: CoseKDFContext = b'',
            alg: Optional[CoseAlgorithms] = None,
            curve: Optional[CoseEllipticCurves] = None) -> Tuple[bytes, bytes]:

        self._check_key_conf(alg, KeyOps.DERIVE_KEY, public_key, curve)

        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        p = X25519PublicKey.from_public_bytes(public_key.x)
        d = X25519PrivateKey.from_private_bytes(self.d)

        shared_secret = d.exchange(p)

        derived_key = alg_cfg.kdf(
            algorithm=alg_cfg.hash(),
            length=int(context.supp_pub_info.key_data_length / 8),
            salt=None,
            info=context.encode(),
            backend=default_backend()).derive(shared_secret)

        return shared_secret, derived_key
예제 #2
0
    def hmac_key_derivation(self,
                            context: CoseKDFContext,
                            alg: Optional[CoseAlgorithms] = None,
                            salt: bytes = b'') -> bytes:
        """
        HMAC-based key derivation based on secret bytes and a CoseKDFContext object.

        :param context: A CoseKDFContext object which contains necessary input for the KDF algorithm.
        :param alg: An optional CoseAlgorithm parameter.
        :param salt: And optional salt parameter.
        :return: A cryptographic key with a length specified in the CoseKDFContext object.
        """

        self._check_key_conf(alg, KeyOps.DERIVE_KEY)

        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        derived_key = alg_cfg.kdf(
            algorithm=alg_cfg.hash(),
            length=int(context.supp_pub_info.key_data_length / 8),
            salt=salt,
            info=context.encode(),
            backend=default_backend()).derive(self.k)

        return derived_key
예제 #3
0
    def _prepare_cipher(self):
        alg_cfg = config(CoseAlgorithms(self.alg))

        if alg_cfg.tag_length is not None:
            cipher: Union[AESGCM, AESCCM] = alg_cfg.primitive(
                self.k, tag_length=alg_cfg.tag_length)
        else:
            cipher = alg_cfg.primitive(self.k)

        return cipher
예제 #4
0
    def key_unwrap(self,
                   wrapped_key: bytes,
                   alg: Optional[CoseAlgorithms] = None) -> bytes:
        self._check_key_conf(alg, KeyOps.UNWRAP)

        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        return alg_cfg.primitive.aes_key_unwrap(self.k, wrapped_key,
                                                default_backend())
예제 #5
0
    def compute_tag(self,
                    to_be_maced: bytes,
                    alg: Optional[CoseAlgorithms] = None) -> bytes:
        """
        Compute the MAC over the payload.

        :param to_be_maced: The payload over which the authentication tag will be calculated.
        :param alg: An optional CoseAlgorithm for computing the authentication tag.
        :return: The authentication tag.
        """

        self._check_key_conf(alg, KeyOps.MAC_CREATE)

        iv = unhexlify(b"".join([b"00"] * 16))

        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        if self.alg in {
                CoseAlgorithms.AES_MAC_128_128, CoseAlgorithms.AES_MAC_128_64,
                CoseAlgorithms.AES_MAC_256_64, CoseAlgorithms.AES_MAC_256_128
        }:
            encryptor = Cipher(alg_cfg.primitive(self.k),
                               modes.CBC(iv),
                               backend=default_backend()).encryptor()

            while len(to_be_maced) % 16 != 0:
                to_be_maced += unhexlify(b"00")

            ciphertext = encryptor.update(to_be_maced) + encryptor.finalize()

            if alg_cfg.tag_length is not None:
                # truncate the result to the first 64 bits
                ciphertext = ciphertext[:-8]
                digest = ciphertext[-8:]
            else:
                digest = ciphertext[-16:]
        else:
            h = alg_cfg.primitive(self.k,
                                  alg_cfg.hash(),
                                  backend=default_backend())
            h.update(to_be_maced)
            digest = h.finalize()

            if CoseAlgorithms(self.alg) == CoseAlgorithms.HMAC_256_64:
                # truncate the result to the first 64 bits
                digest = digest[:8]

        return digest
예제 #6
0
파일: x509.py 프로젝트: mpzaborski/pycose
    def compute_hash(self) -> bytes:
        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        h = Hash(algorithm=alg_cfg.hash(), backend=openssl.backend)
        h.update(self.certificate)
        digest = h.finalize()

        if alg_cfg.tag_length is not None:
            digest = digest[:8]

        return digest
예제 #7
0
    def key_wrap(self,
                 plaintext_key: bytes,
                 alg: Optional[CoseAlgorithms] = None) -> bytes:
        self._check_key_conf(alg, KeyOps.WRAP)

        try:
            alg_cfg = config(CoseAlgorithms(self.alg))
        except KeyError as err:
            raise CoseIllegalAlgorithm(err)

        if self.alg in {
                CoseAlgorithms.A128KW, CoseAlgorithms.A192KW,
                CoseAlgorithms.A256KW
        }:
            return alg_cfg.primitive.aes_key_wrap(self.k, plaintext_key,
                                                  default_backend())
        elif self.alg == CoseAlgorithms.DIRECT:
            return b''
        else:
            raise CoseIllegalAlgorithm(
                f"Key wrap requires one of the following algorithms: \
            {(CoseAlgorithms.A256KW, CoseAlgorithms.A192KW, CoseAlgorithms.A128KW, CoseAlgorithms.DIRECT)}"
            )