public static function castKey(XMLSecurityKey $key, string $algorithm, string $type = null) : XMLSecurityKey
    {
        $type = $type ?: 'public';
        Assert::oneOf($type, ["private", "public"]);

        // do nothing if algorithm is already the type of the key
        if ($key->type === $algorithm) {
            return $key;
        }

        if (!in_array($algorithm, [
            XMLSecurityKey::RSA_1_5,
            XMLSecurityKey::RSA_SHA1,
            XMLSecurityKey::RSA_SHA256,
            XMLSecurityKey::RSA_SHA384,
            XMLSecurityKey::RSA_SHA512
        ], true)) {
            throw new \Exception('Unsupported signing algorithm.');
        }

        $keyInfo = openssl_pkey_get_details($key->key);
        if ($keyInfo === false) {
            throw new \Exception('Unable to get key details from XMLSecurityKey.');
        }
        if (!isset($keyInfo['key'])) {
            throw new \Exception('Missing key in public key details.');
        }

        $newKey = new XMLSecurityKey($algorithm, ['type' => $type]);
        $newKey->loadKey($keyInfo['key']);

        return $newKey;
    }