def get_backup_auth_from_node(self, base_url, auth_token, hive_did):
        rt, status_code, err = self.post(base_url + '/api/v1/did/backup_auth',
                                         {"jwt": auth_token})
        if err != None:
            return None, "Post backup_auth error: " + err

        token = rt["backup_token"]
        if token is None:
            return None, "Token is none."

        jws = lib.DefaultJWSParser_Parse(token.encode())
        if not jws:
            return None, "Backup token DefaultJWSParser_Parse error: " + ffi.string(
                lib.DIDError_GetLastErrorMessage()).decode()

        aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
        if aud != self.get_did_string():
            lib.JWT_Destroy(jws)
            return None, "Audience is error."

        issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode()
        lib.JWT_Destroy(jws)
        if issuer is None:
            return None, "Issuer is none."

        if issuer != hive_did:
            return None, "Issuer is error."

        return token, None
Exemple #2
0
    def backup_client_auth(self, host_url, challenge_response,
                           backup_service_instance_did):
        """
        for vault /backup & /restore
        :return backup access token
        """
        body = self.http.post(host_url + URL_DID_BACKUP_AUTH, None,
                              {"challenge_response": challenge_response})
        if 'token' not in body or not body["token"]:
            raise InvalidParameterException(
                msg='backup_auth: failed to backup auth to backup node.')

        jws = lib.DefaultJWSParser_Parse(body["token"].encode())
        if not jws:
            raise InvalidParameterException(
                msg=
                f'backup_auth: failed to parse token with error {self.get_error_message()}.'
            )

        audience = ffi.string(lib.JWT_GetAudience(jws)).decode()
        if audience != self.get_did_string():
            lib.JWT_Destroy(jws)
            raise InvalidParameterException(
                msg=f'backup_auth: failed to get the audience of the challenge.'
            )

        issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode()
        lib.JWT_Destroy(jws)
        if issuer != backup_service_instance_did:
            raise InvalidParameterException(
                msg=f'backup_auth: failed to get the issuer of the challenge.')

        return body["token"]
Exemple #3
0
    def __get_app_instance_did(self, app_instance_doc):
        doc_str = json.dumps(app_instance_doc)
        app_instance_doc = lib.DIDDocument_FromJson(doc_str.encode())
        if not app_instance_doc or lib.DIDDocument_IsValid(
                app_instance_doc) != 1:
            raise BadRequestException(
                msg='The did document is invalid in getting app instance did.')

        app_instance_did = lib.DIDDocument_GetSubject(app_instance_doc)
        if not app_instance_did:
            raise BadRequestException(
                msg='Can not get did from document in getting app instance did.'
            )

        spec_did_str = ffi.string(
            lib.DID_GetMethodSpecificId(app_instance_did)).decode()
        try:
            with open(hive_setting.DID_DATA_LOCAL_DIDS + os.sep + spec_did_str,
                      "w") as f:
                f.write(doc_str)
        except Exception as e:
            logging.getLogger("HiveAuth").error(
                f"Exception in sign_in:{str(e)} in getting app instance did")

        return "did:" + ffi.string(
            lib.DID_GetMethod(app_instance_did)).decode() + ":" + spec_did_str
Exemple #4
0
    def backup_client_sign_in(self, host_url, credential, subject):
        """
        for vault /backup & /restore
        :return challenge_response, backup_service_instance_did
        """
        vc = lib.Credential_FromJson(credential.encode(), ffi.NULL)
        if not vc:
            raise InvalidParameterException(
                msg='backup_sign_in: invalid credential.')

        doc_str = ffi.string(
            lib.DIDDocument_ToJson(lib.DIDStore_LoadDID(self.store, self.did),
                                   True)).decode()
        doc = json.loads(doc_str)
        body = self.http.post(host_url + URL_DID_SIGN_IN, None, {"id": doc})
        if 'challenge' not in body or not body["challenge"]:
            raise InvalidParameterException(
                msg='backup_sign_in: failed to sign in to backup node.')

        jws = lib.DefaultJWSParser_Parse(body["challenge"].encode())
        if not jws:
            raise InvalidParameterException(
                msg=
                f'backup_sign_in: failed to parse challenge with error {self.get_error_message()}.'
            )

        aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
        if aud != self.get_did_string():
            lib.JWT_Destroy(jws)
            raise InvalidParameterException(
                msg=
                f'backup_sign_in: failed to get the audience of the challenge.'
            )

        nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode()
        if nonce is None:
            lib.JWT_Destroy(jws)
            raise InvalidParameterException(
                msg=f'backup_sign_in: failed to get the nonce of the challenge.'
            )

        issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode()
        lib.JWT_Destroy(jws)
        if issuer is None:
            raise InvalidParameterException(
                msg=
                f'backup_sign_in: failed to get the issuer of the challenge.')

        vp_json = self.create_presentation(vc, nonce, issuer)
        if vp_json is None:
            raise InvalidParameterException(
                msg=f'backup_sign_in: failed to create presentation.')
        challenge_response = self.create_vp_token(
            vp_json, subject, issuer, hive_setting.AUTH_CHALLENGE_EXPIRED)
        if challenge_response is None:
            raise InvalidParameterException(
                msg=f'backup_sign_in: failed to create the challenge response.'
            )
        return challenge_response, issuer
Exemple #5
0
    def verify_order_proof(self, proof, user_did, order_id):
        # INFO:DefaultJWSParser_Parse will validate the sign information.
        jws = lib.DefaultJWSParser_Parse(proof.encode())
        if not jws:
            raise BadRequestException(
                msg=self.get_error_message('parse the proof error'))

        issuer = lib.JWT_GetIssuer(jws)
        if not issuer:
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=self.get_error_message('the issue of the proof error'))
        if self.did_str != ffi.string(issuer).decode():
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=
                f'the issue of the proof not match: {ffi.string(issuer).decode()}'
            )

        audience = lib.JWT_GetAudience(jws)
        if not audience:
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=self.get_error_message('the audience of the proof error'))
        if user_did != ffi.string(audience).decode():
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=
                f'the audience of the proof not match: {ffi.string(audience).decode()}'
            )

        props = lib.JWT_GetClaim(jws, "props".encode())
        if not props:
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=self.get_error_message('the claim of the proof error'))
        props_json = json.loads(ffi.string(props).decode())
        if props_json.get('order_id') != order_id:
            lib.JWT_Destroy(jws)
            raise BadRequestException(
                msg=
                f'the order_id of the proof not match: {props_json.get("order_id")}'
            )

        if hive_setting.PAYMENT_CHECK_EXPIRED:
            expired = lib.JWT_GetExpiration(jws)
            now = int(datetime.now().timestamp())
            if now > expired:
                lib.JWT_Destroy(jws)
                raise BadRequestException(
                    msg=f'the proof is expired (valid for 7 days)')

        lib.JWT_Destroy(jws)
Exemple #6
0
    def __get_auth_token_by_challenge(self, challenge, did: DIDApp):
        jws = lib.DefaultJWSParser_Parse(challenge.encode())
        assert jws, f'Cannot get challenge: {ffi.string(lib.DIDError_GetLastErrorMessage()).decode()}'
        aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
        assert aud == self.app_did.get_did_string()
        nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode()
        hive_did = self.__get_issuer_by_challenge2(jws)
        lib.JWT_Destroy(jws)

        # auth
        vc = did.issue_auth(self.app_did)
        vp_json = self.app_did.create_presentation(vc, nonce, hive_did)
        return self.app_did.create_vp_token(vp_json, "DIDAuthResponse", hive_did, 60)
    def get_did_string_from_did(self, did):
        if not did:
            return None

        method = lib.DID_GetMethod(did)
        if not method:
            return None
        method = ffi.string(method).decode()
        sep_did = lib.DID_GetMethodSpecificId(did)
        if not sep_did:
            return None
        sep_did = ffi.string(sep_did).decode()
        return "did:" + method + ":" + sep_did
    def get_auth_token_by_sign_in(self, base_url, vc_str, subject):
        vc = lib.Credential_FromJson(vc_str.encode(), ffi.NULL)
        if not vc:
            return None, None, "The credential string is error, unable to rebuild to a credential object."

        #sign_in
        doc = lib.DIDStore_LoadDID(self.store, self.did)
        doc_str = ffi.string(lib.DIDDocument_ToJson(doc, True)).decode()
        doc = json.loads(doc_str)

        rt, status_code, err = self.post(base_url + '/api/v1/did/sign_in',
                                         {"document": doc})

        if err != None:
            return None, None, "Post sign_in error: " + err

        jwt = rt["challenge"]
        if jwt is None:
            return None, None, "Challenge is none."

        # print(jwt)
        jws = lib.DefaultJWSParser_Parse(jwt.encode())
        if not jws:
            return None, None, "Challenge DefaultJWSParser_Parse error: " + ffi.string(
                lib.DIDError_GetLastErrorMessage()).decode()

        aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
        if aud != self.get_did_string():
            lib.JWT_Destroy(jws)
            return None, None, "Audience is error."

        nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode()
        if nonce is None:
            lib.JWT_Destroy(jws)
            return None, None, "Nonce is none."

        hive_did = ffi.string(lib.JWT_GetIssuer(jws)).decode()
        lib.JWT_Destroy(jws)
        if hive_did is None:
            return None, None, "Issuer is none."

        #auth_token
        vp_json = self.create_presentation(vc, nonce, hive_did)
        if vp_json is None:
            return None, None, "create_presentation error."
        auth_token = self.create_vp_token(vp_json, subject, hive_did,
                                          hive_setting.AUTH_CHALLENGE_EXPIRED)
        if auth_token is None:
            return None, None, "create_vp_token error."
        return auth_token, hive_did, None
Exemple #9
0
def get_info_from_token(token):
    if token is None:
        return None, "Then token is none!"

    token_splits = token.split(".")
    if token_splits is None:
        return None, "Then token is invalid!"

    if (len(token_splits) != 3) or token_splits[2] == "":
        return None, "Then token is invalid!"

    jws = lib.DefaultJWSParser_Parse(token.encode())
    if not jws:
        return None, get_error_message("JWS parser")

    issuer = lib.JWT_GetIssuer(jws)
    if not issuer:
        lib.JWT_Destroy(jws)
        return None, get_error_message("JWT getIssuer")

    issuer = ffi.string(issuer).decode()
    if issuer != get_current_node_did_string():
        lib.JWT_Destroy(jws)
        return None, "The issuer is invalid!"

    expired = lib.JWT_GetExpiration(jws)
    now = (int)(datetime.now().timestamp())
    if now > expired:
        lib.JWT_Destroy(jws)
        return None, "Then token is expired!"

    props = lib.JWT_GetClaim(jws, "props".encode())
    if not props:
        lib.JWT_Destroy(jws)
        return None, "Then props is none!"

    props_str = ffi.string(props).decode()
    props_json = json.loads(props_str)

    app_instance_did = ffi.string(lib.JWT_GetAudience(jws)).decode()
    if not app_instance_did:
        lib.JWT_Destroy(jws)
        return None, "Then app instance id is none!"

    props_json[APP_INSTANCE_DID] = app_instance_did

    lib.JWT_Destroy(jws)
    # print(props_json)

    return props_json, None
Exemple #10
0
    def create_order_proof(self, user_did, doc_id, amount=0, is_receipt=False):
        doc = lib.DIDStore_LoadDID(self.store, self.did)
        if not doc:
            raise BadRequestException(
                'Can not load service instance document in creating order proof.'
            )

        builder = lib.DIDDocument_GetJwtBuilder(doc)
        if not builder:
            raise BadRequestException(
                msg='Can not get builder from doc in creating order proof.')

        lib.JWTBuilder_SetHeader(builder, "typ".encode(), "JWT".encode())
        lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode())
        lib.JWTBuilder_SetSubject(builder, 'ORDER_PROOF'.encode())
        lib.JWTBuilder_SetAudience(builder, user_did.encode())
        exp = int(datetime.utcnow().timestamp()
                  ) + 7 * 24 * 3600 if not is_receipt else -1
        lib.JWTBuilder_SetExpiration(builder, exp)
        props = {'order_id': doc_id}
        if is_receipt:
            props = {'receipt_id': doc_id, 'amount': amount}
        lib.JWTBuilder_SetClaim(builder, "props".encode(),
                                json.dumps(props).encode())

        lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass)
        proof = lib.JWTBuilder_Compact(builder)
        lib.JWTBuilder_Destroy(builder)
        if not proof:
            raise BadRequestException(
                msg='Can not build token in creating order proof.')

        return ffi.string(proof).decode()
Exemple #11
0
 def sign_in(self):
     doc_c = lib.DIDStore_LoadDID(self.app_did.store, self.app_did.did)
     doc_str = ffi.string(lib.DIDDocument_ToJson(doc_c, True)).decode()
     doc = json.loads(doc_str)
     response = self.http_client.post('/api/v2/did/signin', {"id": doc}, need_token=False, is_skip_prefix=True)
     assert response.status_code == 201
     return response.json()["challenge"]
Exemple #12
0
 def __validate_presentation_realm(self, presentation):
     realm = lib.Presentation_GetRealm(presentation)
     if not realm:
         raise BadRequestException(msg='Can not get presentation realm.')
     realm = ffi.string(realm).decode()
     if not realm or realm != self.get_did_string():
         raise BadRequestException(
             msg='Invalid presentation realm or not match.')
Exemple #13
0
 def __get_presentation_nonce(self, presentation):
     nonce = lib.Presentation_GetNonce(presentation)
     if not nonce:
         raise BadRequestException(msg='Failed to get presentation nonce.')
     nonce_str = ffi.string(nonce).decode()
     if not nonce_str:
         raise BadRequestException(msg='Invalid presentation nonce.')
     nonce_info = get_did_info_by_nonce(nonce_str)
     if not nonce_info:
         raise BadRequestException(
             msg='Can not get presentation nonce information from database.'
         )
     return nonce_str, nonce_info
    def create_presentation(self, vc, nonce, realm):
        vpid = lib.DIDURL_NewByDid(self.did, "jwtvp".encode())
        type0 = ffi.new("char[]", "VerifiablePresentation".encode())
        types = ffi.new("char **", type0)

        vp = lib.Presentation_Create(vpid, self.did, types, 1, nonce.encode(),
                                     realm.encode(), ffi.NULL, self.store,
                                     self.storepass, 1, vc)
        lib.DIDURL_Destroy(vpid)

        # print_err()
        vp_json = ffi.string(lib.Presentation_ToJson(vp, True)).decode()
        # print(vp_json)
        logging.debug(f"vp_json: {vp_json}")
        return vp_json
def MyDIDLocalResovleHandle(did):
    spec_did_str = ffi.string(lib.DID_GetMethodSpecificId(did)).decode()
    doc = ffi.NULL

    file_path = hive_setting.DID_DATA_LOCAL_DIDS + os.sep + spec_did_str
    is_exist = os.path.exists(file_path)
    if is_exist:
        f = open(file_path, "r")
        try:
            doc_str = f.read()
            doc = lib.DIDDocument_FromJson(doc_str.encode())
        finally:
            f.close()

    return doc
Exemple #16
0
    def __get_values_from_challenge_response(self, challenge_response):
        challenge_response_cstr = lib.DefaultJWSParser_Parse(
            challenge_response.encode())
        if not challenge_response_cstr:
            raise BadRequestException(msg='Invalid challenge response.')

        presentation_cstr = lib.JWT_GetClaimAsJson(challenge_response_cstr,
                                                   "presentation".encode())
        lib.JWT_Destroy(challenge_response_cstr)
        if not presentation_cstr:
            raise BadRequestException(msg='Can not get presentation cstr.')
        presentation = lib.Presentation_FromJson(presentation_cstr)
        if not presentation or lib.Presentation_IsValid(presentation) != 1:
            raise BadRequestException(msg='The presentation is invalid.')
        if lib.Presentation_GetCredentialCount(presentation) < 1:
            raise BadRequestException(msg='No presentation credential exists.')

        self.__validate_presentation_realm(presentation)
        nonce, nonce_info = self.__get_presentation_nonce(presentation)
        return json.loads(
            ffi.string(presentation_cstr).decode()), nonce, nonce_info
Exemple #17
0
 def __create_challenge(self, app_instance_did, nonce, expire_time):
     """
     Create challenge for sign in response.
     """
     builder = lib.DIDDocument_GetJwtBuilder(
         self.doc)  # service instance doc
     if not builder:
         raise BadRequestException(
             msg=
             f'Can not get challenge builder: {self.get_error_message()}.')
     lib.JWTBuilder_SetHeader(builder, "type".encode(), "JWT".encode())
     lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode())
     lib.JWTBuilder_SetSubject(builder, "DIDAuthChallenge".encode())
     lib.JWTBuilder_SetAudience(builder, app_instance_did.encode())
     lib.JWTBuilder_SetClaim(builder, "nonce".encode(), nonce.encode())
     lib.JWTBuilder_SetExpiration(builder, expire_time)
     lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass)
     token = lib.JWTBuilder_Compact(builder)
     lib.JWTBuilder_Destroy(builder)
     if not token:
         raise BadRequestException(msg="Failed to create challenge token.")
     return ffi.string(token).decode()
    def create_vp_token(self, vp_json, subject, hive_did, expire):
        doc = lib.DIDStore_LoadDID(self.store, self.did)
        builder = lib.DIDDocument_GetJwtBuilder(doc)
        ticks = int(datetime.now().timestamp())
        iat = ticks
        nbf = ticks
        exp = ticks + expire

        lib.JWTBuilder_SetHeader(builder, "type".encode(), "JWT".encode())
        lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode())

        lib.JWTBuilder_SetSubject(builder, subject.encode())
        lib.JWTBuilder_SetAudience(builder, hive_did.encode())
        lib.JWTBuilder_SetIssuedAt(builder, iat)
        lib.JWTBuilder_SetExpiration(builder, exp)
        lib.JWTBuilder_SetNotBefore(builder, nbf)
        lib.JWTBuilder_SetClaimWithJson(builder, "presentation".encode(),
                                        vp_json.encode())

        lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass)
        token = ffi.string(lib.JWTBuilder_Compact(builder)).decode()
        lib.JWTBuilder_Destroy(builder)
        # print(token)
        return token
Exemple #19
0
    def __create_access_token(self, credential_info, subject):
        doc = lib.DIDStore_LoadDID(self.store, self.did)
        if not doc:
            raise BadRequestException(
                'Can not load service instance document in creating access token.'
            )

        builder = lib.DIDDocument_GetJwtBuilder(doc)
        if not builder:
            raise BadRequestException(
                msg='Can not get builder from doc in creating access token.')

        lib.JWTBuilder_SetHeader(builder, "typ".encode(), "JWT".encode())
        lib.JWTBuilder_SetHeader(builder, "version".encode(), "1.0".encode())
        lib.JWTBuilder_SetSubject(builder, subject.encode())
        lib.JWTBuilder_SetAudience(builder, credential_info["id"].encode())
        lib.JWTBuilder_SetExpiration(builder, credential_info["expTime"])

        props = {
            k: credential_info[k]
            for k in credential_info if k not in ['id', 'expTime']
        }
        if not lib.JWTBuilder_SetClaim(builder, "props".encode(),
                                       json.dumps(props).encode()):
            lib.JWTBuilder_Destroy(builder)
            raise BadRequestException(
                msg='Can not set claim in creating access token.')

        lib.JWTBuilder_Sign(builder, ffi.NULL, self.storepass)
        token = lib.JWTBuilder_Compact(builder)
        lib.JWTBuilder_Destroy(builder)
        if not token:
            raise BadRequestException(
                msg='Can not build token in creating access token.')

        return ffi.string(token).decode()
Exemple #20
0
def test_auth_common(self, user_did, app_did):
    # sign_in
    doc = lib.DIDStore_LoadDID(app_did.store, app_did.did)
    doc_str = ffi.string(lib.DIDDocument_ToJson(doc, True)).decode()
    logging.getLogger("test_auth_common").debug(f"\ndoc_str: {doc_str}")
    doc = json.loads(doc_str)
    rt, s = self.parse_response(
        self.test_client.post('/api/v1/did/sign_in',
                              data=json.dumps({
                                  "document": doc,
                              }),
                              headers=self.json_header))
    self.assert200(s)
    self.assertEqual(rt["_status"], "OK")
    jwt = rt["challenge"]
    # print(jwt)
    jws = lib.DefaultJWSParser_Parse(jwt.encode())
    # if not jws:
    #     print(ffi.string(lib.DIDError_GetLastErrorMessage()).decode())
    aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
    self.assertEqual(aud, app_did.get_did_string())
    nonce = ffi.string(lib.JWT_GetClaim(jws, "nonce".encode())).decode()
    hive_did = ffi.string(lib.JWT_GetIssuer(jws)).decode()
    lib.JWT_Destroy(jws)

    # auth
    vc = user_did.issue_auth(app_did)
    vp_json = app_did.create_presentation(vc, nonce, hive_did)
    auth_token = app_did.create_vp_token(vp_json, "DIDAuthResponse", hive_did,
                                         60)
    # print(auth_token)
    logging.getLogger("test_auth_common").debug(f"\nauth_token: {auth_token}")

    rt, s = self.parse_response(
        self.test_client.post('/api/v1/did/auth',
                              data=json.dumps({
                                  "jwt": auth_token,
                              }),
                              headers=self.json_header))
    self.assert200(s)
    self.assertEqual(rt["_status"], "OK")

    token = rt["access_token"]
    jws = lib.DefaultJWSParser_Parse(token.encode())
    aud = ffi.string(lib.JWT_GetAudience(jws)).decode()
    self.assertEqual(aud, app_did.get_did_string())
    issuer = ffi.string(lib.JWT_GetIssuer(jws)).decode()
    lib.JWT_Destroy(jws)
    # print(token)
    logging.getLogger("test_auth_common").debug(f"\ntoken: {token}")
    app_did.set_access_token(token)

    # auth_check
    # token = test_common.get_auth_token()
    self.json_header = [
        ("Authorization", "token " + token),
        self.content_type,
    ]
    rt, s = self.parse_response(
        self.test_client.post('/api/v1/did/check_token',
                              headers=self.json_header))
    self.assert200(s)
    self.assertEqual(rt["_status"], "OK")
    return token, hive_did
Exemple #21
0
 def get_backup_credential(self, backup_node_did):
     """ INFO: current url to backup url and node did. """
     vc = self.get_current_user_did().issue_backup_auth(self.get_node_did(),
                                                        self.test_config.backup_url,
                                                        backup_node_did)
     return ffi.string(lib.Credential_ToString(vc, True)).decode()
Exemple #22
0
 def __get_issuer_by_challenge2(self, jws):
     node_did = ffi.string(lib.JWT_GetIssuer(jws)).decode()
     assert node_did, 'Invalid hive did'
     self.test_config.save_node_did(self.http_client.base_url, node_did)
     return node_did
def get_error_message():
    return str(ffi.string(lib.DIDError_GetLastErrorMessage()),
               encoding='utf-8')
 def get_error_message(self, prompt):
     err_message = ffi.string(lib.DIDError_GetLastErrorMessage()).decode()
     if not prompt is None:
         err_message = prompt + " error: " + err_message
     return err_message
Exemple #25
0
 def get_error_message(self, prompt=None):
     """ helper method to get error message from did.so """
     err_message = ffi.string(lib.DIDError_GetLastErrorMessage()).decode()
     return err_message if not prompt else f'[{prompt}] {err_message}'