예제 #1
0
async def submit_conclude_secret(app, requester_address, share_secret_state,
                                 zeroth_priv, private_key):
    """
    Args:
        share_secret_address: desrialize share_secret transaction data on share_secret address
        created from the random index for the user
    """

    acc_signer = create_signer(zeroth_priv)

    nonce = random.randint(2**20, 2**30)
    ##nonce signed by zerothprivate key and in hex format
    signed_nonce = ecdsa_signature(private_key, nonce)
    user_signed_nonce = ecdsa_signature(zeroth_priv, nonce)
    nonce_hash = hashlib.sha512(str(nonce).encode()).hexdigest()

    ##ON the processor side, signed_nonce will be checked against admin account
    ##public key

    ##this is required as this will add to the confidence that this tramsaction
    ##was signed  by the database owners or The ADMIN
    transaction_data = {
        "user_address": requester_address,
        "share_secret_address": share_secret_state["address"],
        "active": False,
        "timestamp": indian_time_stamp(),
        "nonce": nonce,
        "nonce_hash": nonce_hash,
        "signed_nonce": signed_nonce,
        "user_signed_nonce": user_signed_nonce,
    }

    ##transaction["address"] is actually an address of the shared_secret_transaction
    inputs = [requester_address, share_secret_state["address"]]

    outputs = [share_secret_state["address"]]

    payload = payload_pb2.CreateConcludeSecret(**transaction_data)
    instance = await SendConcludeSecret(app.config.REST_API_URL,
                                        app.config.TIMEOUT)
    transaction_id, transaction = await instance.create_conclude_secret(
        txn_key=acc_signer,
        batch_key=app.config.SIGNER,
        inputs=inputs,
        outputs=outputs,
        payload=payload)

    transaction_data.update({
        "transaction_id": transaction_id,
        "transaction": transaction,
    })
    logger.info(transaction_data)
    return transaction_data
async def submit_admin_account(app, user):
    acc_signer= encryption_utils.create_signer(app.config.ADMIN_ZERO_PRIV)

    transaction_data= {"config": app.config,
                        "txn_key": acc_signer,
                        "batch_key": app.config.SIGNER,
                        "org_name": user["org_name"],
                                                        #float_account address
                        "user_id": user["user_id"],
                        "pancard": hashlib.\
                                    sha512(app.config.ADMIN_PANCARD.encode())\
                                    .hexdigest(),
                        "gst_number": hashlib.\
                                    sha512(app.config.ADMIN_GST_NUMBER.encode())\
                                    .hexdigest(),
                        "tan_number": hashlib.\
                                    sha512(app.config.ADMIN_TAN_NUMBER.encode())\
                                    .hexdigest(),
                        "phone_number": hashlib.\
                                    sha512(user["phone_number"].encode())\
                                    .hexdigest(),
                        "email": user["email"],
                        "time": int(time.time()),
                        "indian_time": route_utils.indian_time_stamp(),
                        "role": user["role"],
                        "create_asset_idxs": [],
                        "deactivate": False,
                        "deactivate_on": None,
                        }



    transaction_ids, batch_id = await __send_organization_account(**transaction_data)

    logging.info(batch_id)
    if batch_id:

        user.update({
                "transaction_id": transaction_ids[0],
                "batch_id": batch_id,
                "time": transaction_data["time"],
                "indian_time": transaction_data["indian_time"],

        })
        result  = await accounts_query.insert_account(app, user)
        logging.info(result)
        return True
    return
예제 #3
0
async def submit_receive_secret(app, requester_user_id, requester_state,
                                requester_address, requester_mnemonic):
    """
    Args:
        requester_state(str): The user state present on the blockchain who wants
            to create a new receive secret address
        requester_mnemonic: decrypted mnemonic of the user
    """

    index = await generate_key_index(requester_state.get("receive_secret_idxs")
                                     )
    logging.info(index)
    nth_keys = await remote_calls.key_index_keys(app, requester_mnemonic,
                                                 [index, 0])

    nth_priv, nth_pub = nth_keys[str(index)]["private_key"], \
                        nth_keys[str(index)]["public_key"]


    zeroth_priv, zeroth_pub = nth_keys[str(0)]["private_key"], \
                        nth_keys[str(0)]["public_key"]

    ##to prove that this receive_secret has been created by the user himself,
    ##nonce must be signed by the zeroth private of the account
    nonce = random.randint(2**20, 2**30)
    ## nonce signed by zerothprivate key and in hex format
    signed_nonce = ecdsa_signature(zeroth_priv, nonce)
    nonce_hash = hashlib.sha512(str(nonce).encode()).hexdigest()

    acc_signer = create_signer(nth_priv)

    transaction_data = {
        "role": requester_state["role"],
        "active": True,
        "created_on": indian_time_stamp(),
        "nonce": nonce,
        "signed_nonce": signed_nonce,
        "nonce_hash": nonce_hash,
        "requester_address": requester_address,
        "idx": index,
    }

    receive_secret_address = addresser.receive_secret_address(
        acc_signer.get_public_key().as_hex(), index)

    ##both the inputs and outputs addresses will be the same
    ##requester addresss will be fetched from blockchain and checked if its exists,
    ##The receive_secret idx will be appended to the array fo account

    addresses = [requester_address, receive_secret_address]
    logging.info(f"addresses are {addresses}")

    payload = payload_pb2.CreateReceiveSecret(**transaction_data)

    instance = await SendReceiveSecret(app.config.REST_API_URL,
                                       app.config.TIMEOUT)
    transaction_id, transaction = await instance.push_receive_secret(
        txn_key=acc_signer,
        batch_key=app.config.SIGNER,
        inputs=addresses,
        outputs=addresses,
        payload=payload)

    transaction_data.update({
        "transaction_id": transaction_id,
        "transaction": transaction,
        "signed_nonce": signed_nonce.decode()
    })

    db_instance = await DBReceiveSecret(app,
                                        app.config.DATABASE["receive_secret"],
                                        "receive_secret_idxs")

    await db_instance.store_receive_secrets(requester_user_id,
                                            transaction_data)
    await db_instance.update_user_receive_secret(requester_user_id, index)

    return transaction_data
async def submit_execute_share_secret(app, requester, receive_secret_address,
                                      shared_secret_state, private, public):
    """
    app(dict): configuration of the whole application
    requester(dict): database entry of the user who requested this api, i.e who tries to
            execute a share_Secret transactions shared with him on his receive_secret
            transaction
    share_secret_state(dict): Blcokchain state of the share_secret tansaction
        which will be executed by this user
    private(hex encoded string): Private key of the requester with whom the
        receive secret transaction was created, this private was generaed from the idx
        mentioned in the receive_secret transaction from the requester mnemonic

    public(hex encoded string): corresponding public of the private

    Process:
        share_secret transaction has three keys ,
            key: hex encoded AES key encrypted with the public key of the requester
            secret: hex encoded shamir secret share encrypted with the AES key
                    mentioned above
            reset_key: The new hex encoded key generated from the users new_password
                this is also encrypted with requester public key.

    Step1: decrypt hex encoded KEY (AES) with private key
    Step2: decrypt unhexlified secret with AES key from step1.
    Step3: decrypt unhexlified reset_key with private_key
    Step4: Encrypt Secret with reset_key
    """

    secret = shared_secret_state[
        "secret"]  ##encrypted secret with AES key i.e key
    reset_key = shared_secret_state["reset_key"]  ##new aes key which will be
    #used to encrypt the secret after decryption
    key = shared_secret_state[
        "key"]  #THE aes key which was oriniginally used to encrypt secret

    ##the key is hex encoed but this function will first dehexlify it and then
    ## decrypt with private key
    de_org_key = decrypt_w_privkey(key, private)

    #this orginal AES key de_org_key will be in bytes

    unhexlified_secret = binascii.unhexlify(secret)

    ##This is the bare secret which was originally shared with this user
    de_org_secret = aes_decrypt(de_org_key, unhexlified_secret)

    ##Now we have to decrypt the new aes key which user has updated as reset_key
    ##in this contract
    ##It was also encrypted with the public key of the account address
    de_reset_key = priv_decrypt(binascii.unhexlify(reset_key), private)

    ##now encypting orginila share with new reset key
    ciphertext, tag, nonce = aes_encrypt(de_reset_key, de_org_secret)
    secret = b"".join([tag, ciphertext, nonce])

    ##encrypting the shared mnemonic with users account public key
    ##the return will also be in bytes i.e encrypted_secret_share
    #encrypted_secret_share = pub_encrypt(secret_share, account["public"])

    #logging.info(encrypted_secret_share)
    #secret_share = binascii.hexlify(encrypted_secret_share)

    nonce = random.randint(2**20, 2**30)
    ##nonce signed by zerothprivate key and in hex format
    signed_nonce = ecdsa_signature(private, nonce)
    nonce_hash = hashlib.sha512(str(nonce).encode()).hexdigest()
    acc_signer = create_signer(private)

    transaction_data = {
        "share_secret_address": shared_secret_state["address"],
        "reset_secret": binascii.hexlify(secret),
        "timestamp": indian_time_stamp(),
        "nonce": nonce,
        "nonce_hash": nonce_hash,
        "signed_nonce": signed_nonce,
    }

    addresses = [shared_secret_state["address"], receive_secret_address]
    logging.info(f"addresses are {addresses}")

    payload = payload_pb2.CreateExecuteShareSecret(**transaction_data)

    instance = await SendExecuteSecret(app.config.REST_API_URL,
                                       app.config.TIMEOUT)
    transaction_id, batch_id = await instance.push_receive_secret(
        txn_key=acc_signer,
        batch_key=app.config.SIGNER,
        inputs=addresses,
        outputs=addresses,
        payload=payload)

    logging.info(transaction_data)
    #transaction_ids, batch_id = await __send_execute_share_mnemonic(**transaction_data)
    """

    if transaction_ids:
        logging.info("Execute share secret Transaction has been created successfully")
        ##which imlies the transaction has been submitted successfully,
        ##now all the changes that are required to be done on the databse can
        ##be done
        ##Update users create_asset_idxs key on users entry will be updated by
        ## whomever will call this, because update can happend on pending_users
        share_asset_address = addresser.share_asset_address(
                share_asset_pub,
                key_index)
        account_signature = account_hex_signature.decode()
        asset_signature=asset_hex_signature.decode()
        transaction_data.update({"transaction_id": transaction_ids[0],
                            "batch_id": batch_id,
                            "account_signature": account_signature,
                            "asset_signature": asset_signature,
                            "address": share_asset_address })

        [transaction_data.pop(field) for field in ["config", "txn_key", "batch_key"]]
        await share_assets_query.store_share_asset(app, transaction_data)

        ##now asset must be update with share_with key
        await assets_query.update_issuer_asset_shared(
                            app, asset_address, key_index)
        ##TOFO update receiver_address asset and issuer_asset_Address in DB

        await accounts_query.update_share_asset_idxs(
                    app, org_state["user_id"], key_index)

        if child_user_id:
            await accounts_query.update_share_asset_idxs(
                    app, child_user_id, key_index)


        return share_asset_address
    else:
        return False
    """
    return
async def submit_activate_secret(app, transaction, password):
    """
    Args:
        transaction: desrialize share_secret transaction data on share_secret address
        created from the random index for the user
    """
    key, salt = generate_scrypt_key(password, 1, None)

    ##the encrypted scrypt key will also be in bytes. this is the scrypt key
    ##which will be encrypted with other users  public key,
    ##The other user will decrypt with their account private key
    ##and also the secret stored on shasred address,
    ##now he will encrypt the unencrypted original secret with this new scrypt
    ##key
    encrypted_key = pub_encrypt(key, transaction["owner_public"])

    acc_signer = create_signer(app.config.ADMIN_ZERO_PRIV)

    nonce = random.randint(2**20, 2**30)
    ##nonce signed by zerothprivate key and in hex format
    signed_nonce = ecdsa_signature(app.config.ADMIN_ZERO_PRIV, nonce)
    nonce_hash = hashlib.sha512(str(nonce).encode()).hexdigest()

    ##ON the processor side, signed_nonce will be checked against admin account
    ##public key

    ##this is required as this will add to the confidence that this tramsaction
    ##was signed  by the database owners or The ADMIN
    admin_address = addresser.organization_address(app.config.ADMIN_ZERO_PUB,
                                                   0)
    transaction_data = {
        "share_secret_address": transaction["address"],
        "reset_key": binascii.hexlify(encrypted_key),
        "nonce": nonce,
        "nonce_hash": nonce_hash,
        "signed_nonce": signed_nonce,
        "admin_address": admin_address,
        "timestamp": indian_time_stamp()
    }

    ##transaction["address"] is actually an address of the shared_secret_transaction
    inputs = [transaction["address"], admin_address]

    outputs = [transaction["address"], admin_address]

    payload = payload_pb2.CreateActivateSecret(**transaction_data)
    instance = await SendActivateSecret(app.config.REST_API_URL,
                                        app.config.TIMEOUT)
    transaction_id, transaction = await instance.create_activate_secret(
        txn_key=acc_signer,
        batch_key=app.config.SIGNER,
        inputs=inputs,
        outputs=outputs,
        payload=payload)

    transaction_data.update({
        "transaction_id": transaction_id,
        "transaction": transaction,
        "key": binascii.hexlify(key).decode(),
        "salt": binascii.hexlify(salt).decode(),
    })

    return transaction_data
async def submit_user_account(app, pancard=None, phone_number=None, email=None, role=None, \
                     password=None, first_name=None, last_name=None):
    """
    org_name is by default None for the user
    """
    if role != "USER":
        raise errors.CustomError("Roel required is USER")

    user = await route_utils.new_user_account(app,
                                              pancard=pancard,
                                              phone_number=phone_number,
                                              email=email,
                                              role=role,
                                              first_name=first_name,
                                              last_name=last_name)
    ##no9w the create account address and signer will be the user himself

    user_mnemonic, user_account = await route_utils.set_password(
        app, account=user, password=password)


    master_pub, master_priv, zero_pub, zero_priv = await \
                remote_calls.from_mnemonic(app.config.GOAPI_URL, user_mnemonic)

    acc_signer = create_signer(zero_priv)
    ##hashing gst number and tan number if present

    ##import from ledger.account import float_account, other then create_asset_idxs
    ## wil be emprty for the float_account, if we push empty list on blockchain
    ##it wil hsow an error, its better to not to send them at the first place
    find_hash = lambda x: hashlib.sha512(x.encode()).hexdigest() if x else None

    transaction_data = {
        "config": app.config,
        "txn_key": acc_signer,
        "batch_key": app.config.SIGNER,
        "first_name": first_name,
        "last_name": last_name,
        "user_id": user_account["user_id"],
        "pancard": find_hash(pancard),
        "phone_number": find_hash(phone_number),
        "email": find_hash(email),
        "time": int(time.time()),
        "indian_time": route_utils.indian_time_stamp(),
        "role": "USER",
        "deactivate": False,
        "deactivate_on": None,
    }

    transaction_ids, batch_id = await __send_user_account(**transaction_data)

    logging.info(batch_id)
    if batch_id:
        ##if successful, insert this user in pending_users table
        user_account.update({
            "time": transaction_data["time"],
            "indian_time": transaction_data["indian_time"],
            "transaction_id": transaction_ids[0],
            "batch_id": batch_id,
            "role": "USER",
            "pancard": transaction_data["pancard"],
        })

        logging.debug(user_account)
        await accounts_query.insert_account(app, user_account)

        ##update user pending_user with claim, claim_by , claimed_on keys
    return user_account
async def submit_share_secret(app, requester, requester_address,
                              receive_secret, index, private_key):
    """
    Args:
        requester(dict): The db entry of the user who wants to share the mnemonic
        receive_secret(dict): The blockchain state of the receive_secret addr  to whom
                this user wants to share the mnemonic
                {'role': 'USER',
                'active': True,
                'created_on': '2018-12-28 19:59:14 IST+0530',
                'nonce': 802584806,
                'signed_nonce': '304402204b79ebf02b7.........',
                'nonce_hash': '87b4e684b071956e5598b.........',
                'idx': 1044988318,
                'public': '026f914d49e6321f668139e75.........',
                'address': 'a9d5c23e49419e21d9f5a2ef.........',
                "salt":
                "secret": the part of the mnemonic share shared with this receive_secret}
                address is added by deserialize_receive_secret function
        secret_share (str): One share of the encrypted mnemonic of the user out of many
            others which will be shared with the user represented by account.
        index(int): ranom index generated from the user mnemonic at which a new
            shared_mnemonic address will be generated at which this share of the mnemonic
            will be stored after encrypting it with a random AES key and encrypting AES
            key with the public key of the user represented but the account.
        private_key(str): private key of the requested generated from its mnemonic
            present at the index.
    """

    acc_signer = create_signer(private_key)

    ##encrypting the shared mnemonic with users account public key
    ##the return will also be in bytes i.e encrypted_secret_share
    #encrypted_secret_share = pub_encrypt(secret_share, account["public"])

    #logging.info(encrypted_secret_share)
    #secret_share = binascii.hexlify(encrypted_secret_share)

    key = generate_aes_key(16)  ##this is in bytes
    ciphertext, tag, nonce = aes_encrypt(key, receive_secret["secret"])
    ciphertext = b"".join([tag, ciphertext, nonce])
    ##The AES_GCM encrypted file content
    encryptes_secret_share = binascii.hexlify(ciphertext).decode()

    ##Encrypting AES key with the public key present at the receive_secret transaction,
    ##output will ne hex encoded encryted AES key
    encrypted_key = encrypt_w_pubkey(key, receive_secret["public"])

    nonce = random.randint(2**20, 2**30)
    ##nonce signed by zerothprivate key and in hex format
    signed_nonce = ecdsa_signature(requester["zeroth_private"], nonce)
    nonce_hash = hashlib.sha512(str(nonce).encode()).hexdigest()

    transaction_data = {
        "ownership": receive_secret["address"],
        "active": False,
        "secret": encryptes_secret_share,
        "key": encrypted_key,
        "secret_hash": hashlib.sha512(receive_secret["secret"]).hexdigest(),
        "role": "USER",
        "idx": index,
        "created_on": route_utils.indian_time_stamp(),
        "nonce": nonce,
        "signed_nonce": signed_nonce,
        "nonce_hash": nonce_hash,
        "user_address": requester_address  #because at the processing side
        ##user state needs to be appended with
        ##shared_asecret_address on their share_secret_addresses
    }

    share_secret_address = addresser.shared_secret_address(
        acc_signer.get_public_key().as_hex(), index)

    ##both the inputs and outputs addresses will be the same
    ##requester addresss will be fetched from blockchain and checked if its exists
    ##and the shared_secret_addresses will be appended to its
    inputs = [
        requester_address, share_secret_address, receive_secret["address"]
    ]
    outputs = [requester_address, share_secret_address]

    payload = payload_pb2.CreateShareSecret(**transaction_data)

    instance = await SendTransactions(app.config.REST_API_URL,
                                      app.config.TIMEOUT)
    transaction_id, transaction = await instance.share_mnemonic_transaction(
        txn_key=acc_signer,
        batch_key=app.config.SIGNER,
        inputs=inputs,
        outputs=outputs,
        payload=payload)

    transaction_data.update({
        "transaction_id": transaction_id,
        "transaction": transaction,
        "share_secret_address": share_secret_address,
        "signed_nonce": signed_nonce.decode(),
        "public": acc_signer.get_public_key().as_hex()
    })

    return transaction_data