Beispiel #1
0
def test_signer_protected_headers():
    payload = "Please take a moment to register today"
    eck = ec.generate_private_key(ec.SECP256R1(), default_backend())
    _key = ECKey().load_key(eck)
    keys = [_key]
    _jws = JWS(payload, alg="ES256")
    protected = dict(header1=u"header1 is protected",
                     header2="header2 is protected too",
                     a=1)
    _jwt = _jws.sign_compact(keys, protected=protected)

    exp_protected = protected.copy()
    exp_protected["alg"] = "ES256"
    enc_header, enc_payload, sig = _jwt.split(".")
    assert json.loads(b64d(
        enc_header.encode("utf-8")).decode("utf-8")) == exp_protected
    assert b64d(enc_payload.encode("utf-8")).decode("utf-8") == payload

    _pub_key = ECKey().load_key(eck.public_key())
    _rj = JWS(alg="ES256")
    info = _rj.verify_compact(_jwt, [_pub_key])
    assert info == payload
    # Protected by default
    protected["alg"] = "ES256"
    assert _rj.protected_headers() == protected
    def test_get_token(self):
        """Get BoB auth token (good)"""
        response = self.env.get_auth_response(api='authentication')
        now = int(time.time())
        self.assertEqual(response.status_code, 200)
        data = response.json()
        (header, payload, signature) = data['jwtCompact'].split('.')
        header_dict = json.loads(b64d(header.encode()))
        payload_dict = json.loads(b64d(payload.encode()))
        signature_dict = b64d(signature.encode())

        # check for supported algorithms
        self.assertIn(header_dict['alg'], TOKEN_ALGS)

        # ensure some headers are not missing
        self.assertIsNotNone(header_dict.get('kid'))
        self.assertIsNotNone(payload_dict.get('iss'))
        self.assertIsNotNone(payload_dict.get('sub'))
        self.assertIsNotNone(payload_dict.get('bobAuthZ'))
        self.assertIsNotNone(payload_dict.get('exp'))

        # ensure iat/nbf/exp are reasonable (if provided)
        if 'iat' in payload_dict:
            self.assertTrue(now + TIMESKEW >= payload_dict['iat'])
        if 'nbf' in payload_dict:
            self.assertTrue(now + TIMESKEW >= payload_dict['nbf'])
        if 'exp' in payload_dict:
            self.assertTrue(now - TIMESKEW < payload_dict['exp'])
Beispiel #3
0
def modify_header(token, **kwargs):
    part = token.split('.')
    _txt = utils.b64d(as_bytes(part[0]))
    header = json.loads(as_unicode(_txt))
    header.update(kwargs)
    part[0] = utils.b64e(as_bytes(json.dumps(header)))
    return b'.'.join([as_bytes(p) for p in part])
Beispiel #4
0
def command_sign(args: argparse.Namespace):
    """Create signed EHC"""

    private_key = read_cosekey(args.key, private=True)
    if args.kid:
        private_key.kid = b64d(args.kid.encode())

    with open(args.input, "rt") as input_file:
        input_data = input_file.read()

    logger.info("Input JSON data: %d bytes", len(input_data))

    eu_dgc_v1 = json.loads(input_data)
    cwt_bytes = sign(
        private_key=private_key,
        payload=eu_dgc_v1,
        issuer=args.issuer,
        ttl=args.ttl,
        sign1=args.sign1,
    )
    logger.info("Raw signed CWT: %d bytes", len(cwt_bytes))

    if args.output:
        with open(args.output, "wb") as output_file:
            output_file.write(cwt_bytes)
    else:
        logger.info("Output: %s", binascii.hexlify(cwt_bytes).decode())

    if args.qrcode:
        save_qrcode(cwt_bytes, args.qrcode)
Beispiel #5
0
def command_verify(args: argparse.Namespace):
    """Verify signed EHC"""

    public_keys = []
    if args.jwks:
        with open(args.jwks) as jwks_file:
            jwks = json.load(jwks_file)
            for jwk_dict in jwks.get("keys", []):
                key = cosekey_from_jwk_dict(jwk_dict, private=False)
                key.issuer = jwk_dict.get("issuer")
                public_keys.append(key)
    elif args.key:
        public_keys = [read_cosekey(args.key, private=False)]

    if args.kid:
        public_key.kid = b64d(args.kid.encode())

    with open(args.input, "rb") as input_file:
        signed_data = input_file.read()

    res = verify(signed_data=signed_data, public_keys=public_keys)

    logger.info("Signatured issued by: %s", res.iss)
    logger.info(
        "Signature verified by: %s (%s)",
        b64e(res.kid).decode(),
        res.key.issuer if hasattr(res.key, "issuer") else None,
    )
    logger.info("Signatured issued at: %s", res.iat)

    if res.expired:
        logger.warning("Signatured expired at: %s", res.exp)
    else:
        logger.info("Signatured expires at: %s", res.exp)

    if res.eu_dgc_v1 is None:
        logger.warning("No EU DCC version 1 found in payload")

    if args.output:
        with open(args.output, "wt") as output_file:
            json.dump(res.eu_dgc_v1, output_file, indent=4)
    else:
        logger.info("Verified payload: %s", json.dumps(res.eu_dgc_v1, indent=4))
Beispiel #6
0
def modify_json_message(token):
    part = [as_bytes(p) for p in token.split('.')]
    _txt = utils.b64d(part[1])
    msg = json.loads(as_unicode(_txt))
    for k, v in msg.items():
        msg_copy = msg.copy()
        del msg_copy[k]

        for _k in modify_str(k):
            msg_copy[_k] = v
            part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
            yield b'.'.join([as_bytes(p) for p in part])

        if isinstance(v, str):
            for _v in modify_str(v):
                msg_copy[k] = _v
                part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
                yield b'.'.join([as_bytes(p) for p in part])
        elif isinstance(v, int):
            _v = v + 1
            msg_copy[k] = _v
            part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
            yield b'.'.join([as_bytes(p) for p in part])
Beispiel #7
0
async def process_csv(filename: str, server: str, speed: float = 1.0):
    """Process CSV realtime data"""
    mqtt = MQTTClient()
    ret = await mqtt.connect(server)
    logging.debug("MQTT connect to %s -> %s", server, ret)
    testdata_file = open(filename)
    header = testdata_file.readline()
    last_timestamp = None
    for line in testdata_file:
        (timestamp, topic, qos, message) = line.rstrip().split(",")
        topic = topic.strip()
        message = message.strip()
        payload = b64d(message)
        if last_timestamp is not None and speed != 0:
            delay = (float(timestamp) - float(last_timestamp)) / speed
            if delay > 0:
                logging.info("Sleeping for %f seconds", delay)
                time.sleep(delay)
        logging.info("Topic %s, Payload %s", topic, message)
        asyncio.get_event_loop().run_until_complete(
            send_realtime(server, [(topic, payload)]))
        last_timestamp = timestamp
    testdata_file.close()
Beispiel #8
0
def get_channel_contents(config: dict, name: str, contents: dict):
    """Publish channel contents on MQTT"""
    if name in config:
        channel_topic = config[name]["topic"]
        channel_format = config[name]["format"]
        if channel_format == "json":
            new_contents = {}
            for key, value in contents.items():
                if key.startswith(FILE_PREFIX):
                    key = key[len(FILE_PREFIX):]
                    with open(value, "rb") as input_file:
                        value = input_file.read()
                    if key.startswith(BASE64_PREFIX):
                        key = key[len(BASE64_PREFIX):]
                        value = b64e(value)
                    value = value.decode()
                new_contents[key] = value
            payload = json.dumps(new_contents).encode()
        elif channel_format == "nmea":
            payload = contents_to_nmea(contents).encode()
        elif channel_format == "bytes":
            if "base64" in contents:
                payload = b64d(contents["base64"])
            elif "file" in contents:
                filename = contents["file"]
                with open(filename, "rb") as input_file:
                    payload = input_file.read()
            elif "string" in contents:
                payload = contents["string"].encode()
            else:
                raise Exception("No binary contents found")
        else:
            raise Exception("Undefined format: {}".format(channel_format))
        return (channel_topic, payload)
    else:
        raise Exception("Undefined channel: {}".format(name))
Beispiel #9
0
def modify_signature(token):
    part = [as_bytes(p) for p in token.split('.')]
    signature = utils.b64d(part[2])
    for sig in modify_bytes(signature):
        part[2] = utils.b64e(sig)
        yield b'.'.join([as_bytes(p) for p in part])
Beispiel #10
0
    def setup_auth(self,
                   request,
                   redirect_uri,
                   cinfo,
                   cookie,
                   acr=None,
                   **kwargs):
        """

        :param request: The authorization/authentication request
        :param redirect_uri:
        :param cinfo: client info
        :param cookie:
        :param acr: Default ACR, if nothing else is specified
        :param kwargs:
        :return:
        """

        res = self.pick_authn_method(request, redirect_uri, acr, **kwargs)

        authn = res["method"]
        authn_class_ref = res["acr"]

        try:
            _auth_info = kwargs.get("authn", "")
            if "upm_answer" in request and request["upm_answer"] == "true":
                _max_age = 0
            else:
                _max_age = max_age(request)

            identity, _ts = authn.authenticated_as(cookie,
                                                   authorization=_auth_info,
                                                   max_age=_max_age)
        except (NoSuchAuthentication, TamperAllert):
            identity = None
            _ts = 0
        except ToOld:
            logger.info("Too old authentication")
            identity = None
            _ts = 0
        else:
            if identity:
                try:  # If identity['uid'] is in fact a base64 encoded JSON string
                    _id = b64d(as_bytes(identity["uid"]))
                except BadSyntax:
                    pass
                else:
                    identity = json.loads(as_unicode(_id))

                    session = self.endpoint_context.sdb[identity.get("sid")]
                    if not session or "revoked" in session:
                        identity = None

        authn_args = authn_args_gather(request, authn_class_ref, cinfo,
                                       **kwargs)

        # To authenticate or Not
        if identity is None:  # No!
            logger.info("No active authentication")
            logger.debug("Known clients: {}".format(
                list(self.endpoint_context.cdb.keys())))

            if "prompt" in request and "none" in request["prompt"]:
                # Need to authenticate but not allowed
                return {
                    "error": "login_required",
                    "return_uri": redirect_uri,
                    "return_type": request["response_type"],
                }
            else:
                return {"function": authn, "args": authn_args}
        else:
            logger.info("Active authentication")
            if re_authenticate(request, authn):
                # demand re-authentication
                return {"function": authn, "args": authn_args}
            else:
                # I get back a dictionary
                user = identity["uid"]
                if "req_user" in kwargs:
                    sids = self.endpoint_context.sdb.get_sids_by_sub(
                        kwargs["req_user"])
                    if (sids and user !=
                            self.endpoint_context.sdb.get_authentication_event(
                                sids[-1]).uid):
                        logger.debug("Wanted to be someone else!")
                        if "prompt" in request and "none" in request["prompt"]:
                            # Need to authenticate but not allowed
                            return {
                                "error": "login_required",
                                "return_uri": redirect_uri,
                            }
                        else:
                            return {"function": authn, "args": authn_args}

        authn_event = create_authn_event(
            identity["uid"],
            identity.get("salt", ""),
            authn_info=authn_class_ref,
            time_stamp=_ts,
        )
        if "valid_until" in authn_event:
            vu = time.time() + authn.kwargs.get("expires_in", 0.0)
            authn_event["valid_until"] = vu

        return {"authn_event": authn_event, "identity": identity, "user": user}
Beispiel #11
0
def main():
    """Main function"""

    parser = argparse.ArgumentParser(description="JWS verifier")

    parser.add_argument(
        "--trusted",
        dest="trusted",
        metavar="filename",
        help="Trusted keys (JWKS)",
        required=False,
    )
    parser.add_argument(
        "--input",
        dest="jws_input",
        metavar="filename",
        help="JWS file input",
        required=True,
    )
    parser.add_argument(
        "--output",
        dest="output",
        metavar="filename",
        help="Output",
        required=False,
    )
    parser.add_argument(
        "--headers",
        dest="headers_output",
        metavar="filename",
        help="Headers output",
        required=False,
    )
    parser.add_argument("--debug",
                        dest="debug",
                        action="store_true",
                        help="Enable debugging")

    args = parser.parse_args()

    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)

    trusted_keys = []
    if args.trusted:
        with open(args.trusted) as input_file:
            trusted_payload = json.load(input_file)
            if isinstance(trusted_payload, dict):
                trusted_keys.append(key_from_jwk_dict(trusted_payload))
            elif isinstance(trusted_payload, dict):
                for jwk_dict in trusted_payload["keys"]:
                    trusted_keys.append(
                        key_from_jwk_dict(jwk_dict, private=False))
            else:
                raise ValueError("Unknown trusted list format")

    with open(args.jws_input, "rt") as input_file:
        jws_file = input_file.read()

    protected_headers = []
    jws_dict = json.loads(jws_file)

    if args.trusted:
        jws = JWS()
        message = jws.verify_json(jws_file, keys=trusted_keys)
    else:
        message = json.loads(b64d(jws_dict["payload"].encode()).decode())

    for signatures in jws_dict["signatures"]:
        if "protected" in signatures:
            protected_headers.append(extract_headers(signatures["protected"]))

    if args.headers_output:
        with open(args.headers_output, "wt") as output_file:
            print(json.dumps(protected_headers, indent=4), file=output_file)
    else:
        if args.trusted:
            print("# JWS PROTECTED HEADERS (VERIFIED)")
        else:
            print("# JWS PROTECTED HEADERS (NOT VERIFIED)")
        print(json.dumps(protected_headers, indent=4, sort_keys=True))

    if args.output:
        with open(args.output, "wt") as output_file:
            print(json.dumps(message, indent=4), file=output_file)
    else:
        if args.trusted:
            print("# JWS CONTENTS (VERIFIED)")
        else:
            print("# JWS CONTENTS (NOT VERIFIED)")
        print(json.dumps(message, indent=4, sort_keys=True))
Beispiel #12
0
def extract_headers(data: str) -> dict:
    """Extract JSON-encoded headers"""
    return json.loads(b64d(data.encode()).decode())
Beispiel #13
0
def cosekey_from_jwk_dict(jwk_dict: Dict, private: bool = True) -> CoseKey:
    """Read key and return CoseKey"""

    if jwk_dict["kty"] == "EC":

        if jwk_dict["crv"] != "P-256":
            raise ValueError("Only P-256 supported")

        if private:
            key = EC2Key(
                crv=cose.keys.curves.P256,
                x=b64d(jwk_dict["x"].encode()),
                y=b64d(jwk_dict["y"].encode()),
                d=b64d(jwk_dict["d"].encode()),
            )
        else:
            key = EC2Key(
                crv=cose.keys.curves.P256,
                x=b64d(jwk_dict["x"].encode()),
                y=b64d(jwk_dict["y"].encode()),
            )

    elif jwk_dict["kty"] == "RSA":

        if private:
            key = RSAKey(
                e=b64d(jwk_dict["e"].encode()),
                n=b64d(jwk_dict["n"].encode()),
                p=b64d(jwk_dict["p"].encode()),
                q=b64d(jwk_dict["q"].encode()),
                d=b64d(jwk_dict["d"].encode()),
            )
        else:
            key = RSAKey(
                e=b64d(jwk_dict["e"].encode()),
                n=b64d(jwk_dict["n"].encode()),
            )

    else:
        raise ValueError("Unsupport key type: " + jwk_dict["kty"])

    if private:
        key.key_ops = [cose.keys.keyops.SignOp, cose.keys.keyops.VerifyOp]
    else:
        key.key_ops = [cose.keys.keyops.VerifyOp]

    if "kid" in jwk_dict:
        kid = jwk_dict["kid"]
        try:
            key.kid = b64d(kid.encode())
        except cryptojwt.exception.BadSyntax:
            key.kid = b64decode(kid.encode())

    return key