The main operations of our system are divided into four modules: (1) system setup by the KGC, (2) user registration, (3) blockchain-based employment contract creation using PTEC, and (4) contract management by the cloud server. In the next subsections, we describe the concrete protocols for each module in detail.
3.3.3. Blockchain-Based Employment Contract Creation
A pair of a worker and an employer can create a new employment contract using PTEC in three steps: (1) contract creation, (2) C-Chain update, and (3) contract upload to the cloud server.
- A.
Contract Creation
Let an employer be
ui, and let a worker be
uj. The contract is created interactively between the two participants in five steps as shown in
Figure 2. Each temporary contract generated in each step is encrypted with a recipient’s public key and temporarily stored on the cloud server. Once the contract is created, the temporary contract files in progress are removed from the cloud server.
Step 1: ui creates a new contract denoted as Ci,j1. ui fills out the employer’s part in the online contract form. Ci,j1 is encrypted with uj’s public key and stored temporarily on the cloud server.
Step 2: uj decrypts Ci,j1 and fills out the worker’s part, which is denoted as Ci,j2. Ci,j2 is also encrypted with ui’s public key. The encrypted version ECi,j2 = PKE(CKi+,Ci,j2) is stored on the cloud server.
Step 3: ui decrypts Ci,j2 and attaches its signature for Ci,j2 such as Sigi = S(SKi−,H0(Ci,j2)). That is, Ci,j3 is ui’s signed contract, as in Ci,j3 = {Ci,j2|Sigi = S(SKi−,H0(Ci,j2))}. Ci,j3 is also encrypted with uj’s public key (such as ECi,j3 = PKE(CKj+, Ci,j3)) and stored on the cloud server.
Step 4: uj decrypts Ci,j3 and validates ui’s signature. If the signature is valid, uj attaches its signature to Ci,j3, which is denoted as Ci,j4. Finally, Ci,j4 = {Ci,j3|Sigj = S(SKj−,H0(Ci,j3))}, and the encrypted ECi,j4 = PKE(CKi+, Ci,j4) is stored on the cloud server. If the signature is invalid, the contract is stopped at this stage.
Step 5:
ui decrypts
ECi,j4 and finally verifies the validity of
uj’s signature, and if the signature is valid, the contract creation is completed. Consequently, the final contract
Ci,j between
ui and
uj is defined as follows:
Otherwise, the contract creation fails.
- B.
C-Chain update
Once a contract is successfully created,
PTEC of
ui generates a new transaction
Ti,j for the contract
Ci,j.
Ti,j is defined as follows:
PTEC broadcasts only
TID over the network, and
TID can be validated by the contractual parties associated with the transaction. If
TID is not correct, the transaction is rejected by the signer of the contract corresponding to
TID. At the end of a block interval, for every valid
TID, every
PTEC that created a new transaction in the block interval performs a proof of work on the transactions collected in the block interval in order to add the transaction to the
C-Chain. After mining a nonce that satisfies a predefined difficulty in our system, it broadcasts a new block information as follows:
where
NewRootHash is a root hash of the Merkle hash tree made up of all
TIDs. The
Block is verified by all peers on the network, including verifying that the hash of
Block satisfies the difficulty of the system. If more than half of peers agree to the
Block, then, finally,
C-Chain is updated as follows and broadcasted over the network:
PTEC keeps C-Chain updated. For practical use, the latest C-Chain is also stored at the cloud server. Thus, PTEC can always get the latest C-Chain from the cloud server.
- C.
Contract Upload
Once C-Chain for Ci,j is updated, Ci,j is encrypted with each signer’s public key separately and uploaded to the cloud server along with encrypted keywords for permanent storage and use. Because the contract is encrypted with each signer’s public key, only the contract signer can decrypt the contract. Furthermore, the keywords are homomorphically encrypted with the cloud server’s public key so that each contract is always searchable by the cloud server with the keywords. The PTEC of each ui related to Ci,j performs the following steps to upload each user’s contract to the cloud server.
Step 1: Contract encryption
Step 2: keyword and access token generation
For each contract, a pair consisting of an encrypted keyword token and a contract access token is required for the cloud server to retrieve ui’s contract. The contract access token is required to prove the ownership of the contract. Let ui’s identifier, keyword and secret identifier be idi, wi and qidi, respectively.
PTEC generates a pair of keyword token KTi and access token ATi using GenKeywordToken(idi, wi, qidi, pk).
The
GenKeywordToken() algorithm generates homomorphically encrypted keyword tokens for a keyword
w, a secret identifier
qid, and the cloud server’s public key
pk. It outputs two types of tokens denoted as
KT and
AT;
KT is an encrypted keyword, and
AT is an access token to show the ownership of the contract.
AT distinguishes the signer from others who might have the same keyword. Note that only registered users should be able to store contracts in the cloud server; thus, each user must first be authenticated by the KGC before the token is generated. For an authorized user, the KGC responds with a session key that is used to generate the token. In other words, the session key is required to ensure that only a registered user can upload a contract to the cloud server. A session key is generated by the following
GetSessionKey() algorithm:
GetSessionKey(id, qid): |
it generates auth_code = H0(id|qid|timestamp) with a timestamp for the current time, it generates a session key request SK_RQST = “session key request|id|auth_code|timestamp”, and it sends SK_RQST to the KGC. the KGC performs VerifyUser(id, auth_code, timestamp). if valid, the KGC chooses αu that is a prime satisfying 2l + 2q+r < αu and (p mod αu) ≠ 0, generates auth_codeα = H0(αu | αs | timestamp), and sends <“verified”, αu, auth_codeα> to ui. else the KGC sends a “failed” message to ui. it outputs the KGC’s response.
|
The
GenKeywordToken() algorithm is defined as follows:
GenKeywordToken(id, w, qid, pk): |
it gets a session key αu and its authentication code auth_codeα using GetSessionKey(id, qid), it chooses a random subset from the public key pk = {x0, x1, …, xτ} of the cloud server, it chooses a random integer R, and it computes <C1, C2, C3> as follows: it outputs <KT = (C1, C2), AT = (C2, C3), αu, auth_codeα, timestamp>.
|
Step 3: Contract upload
PTEC sends an encrypted contract upload request UP_RQSTi = <“contract upload”, TID,ECi, KTi, ATi, αu, auth_codeα, timestamp> to the cloud server.
- D.
Contract Request
After the contract upload has been completed, ui can request its contract from the cloud server at any time. For the contract request, ui’s PTEC generates a new pair of KTi and ATi using GenKeywordToken(idi, wi, qidi, pk). Finally, PTEC sends a contract request query CRT_RQST = <“contract request”, KTi, ATi, αu, auth_codeα, timestamp> to the cloud server. We describe how the cloud server stores the uploaded contract and responds to the user’s contract request in the next section.
3.3.4. Contract Management and Encrypted Keyword Searches by Cloud Server
The primary role of the cloud server is to securely store users’ contracts and deliver correct contracts to user requests. As mentioned before, the contracts stored on the cloud server are confidential and anonymous to the server, but the server does need to be able to retrieve the requested contracts accurately and efficiently. To achieve this, the cloud server slightly modifies the uploaded tokens and then stores the contracts in its database (DB) server along with the modified tokens. We describe how the server modifies the uploaded tokens and indexes contract files to increase search efficiency.
- A.
Contract Storage and File Index Table Update
For a single contract Ci,j, each contractual party uploads its encrypted contract and tokens. For each upload request UP_RQST, the cloud server first verifies if the request was created by an authorized user. For αu, auth_codeα and timestamp given in UP_RQST, the server computes AC = H0(αu|αs|timestamp) with its secret αs. If AC = auth_codeα, then the request is valid. Because the user possesses a valid auth_codeα that can be only generated by the KGC knowing the secret αs, the server can be convinced that the KGC has authenticated the user.
If the upload request is valid, the cloud server assigns a single file identifier to all encrypted contracts and tokens created by both contractual parties ui and uj. In other words, a single file identifier is assigned to all encrypted contracts and tokens with the same TID. The file identifier, which is a sequentially increasing number, is automatically generated by the server. Let be a file identifier for a set of files related to Ci,j uploaded at time t. Consequently, indicates a set of < ECi, ECj, KTi, KTj, ATi, ATj >.
Here, the tokens are generated with individual αu randomly assigned to each user by the KGC, which means that the server needs to store αu additionally for each contract. In order to eliminate this inefficiency, the cloud server re-encrypts the given tokens by replacing αu with its private secret αs. For each set of KT = (C1, C2) and AT = (C2, C3), C1 and C3 are recomputed as follows:
P1 = C1 mod p mod αu, P3 = C3 mod p mod αu;
.
Hence, the cloud server can retrieve each user’s contract with the server’s secret αs without storing individual αu. Then, the server stores the encrypted contracts and the modified tokens with its file identifier.
The cloud server maintains a file index table for efficient contract search, as shown in
Table 3. The table consists of two attributes: keyword token and bit string; for each keyword token in the table, the bit string represents whether each contract contains the keyword or not. The table contains only distinct keyword tokens. For example, if two different keyword tokens
KT1 and
KT2 indicate to the same keyword
w,
KT1 and
KT2 are homomorphic to each other and one of them is added to the table; that is, a previously uploaded keyword token is added to the table. Suppose that
KT = {
KT1,
KT2, …,
KTj} is the current set of distinct keyword tokens uploaded to the cloud server. As shown in
Table 3, the bit string of each keyword token
KTi is determined as follows: for all file identifiers
= {1, …,
n}, if the keyword token of the contract indicated by each file identifier is homomorphic to
KTi, then 1 is assigned; otherwise, 0 is assigned.
Whenever a new contract set is uploaded, the table is updated. First, the cloud server compares the given keyword token KTk with all the KTi in KT. If there is a KTj such that the keyword wj represented by KTj is the same as the keyword wj represented by KTk, then the bit strings of all keyword tokens in the table are updated. Otherwise, a new KTk is added to the table and all the bit strings are updated.
- B.
Keyword and Access Token Comparison
The key operation of the cloud server is to determine whether any two tokens are homomorphic or not. We propose two test algorithms to determine the homomorphism of two tokens. Suppose that KTi is a keyword token for a keyword wi and KTj is a token for wj. The two different keyword tokens KTi and KTj are homomorphic if wi = wj. The algorithm Test_KT(KTi, KTj) determines whether two tokens KTi and KTj are homomorphic or not.
Test_KT(
KTi,
KTj): Suppose that
KTi = <
Ci1,
Ci2> and
KTj = <
Cj1,
Cj2>. It computes the following Equation (1). If the result is 1, then the two tokens are homomorphic. That is,
wi =
wj. Otherwise,
wi ≠
wj.
Similarly, the algorithm Test_AT(ATi, ATj) determines whether two tokens ATi and ATj are homomorphic or not. Suppose that ATi is an access token for a secret identifier qidi and ATj is a token for a secret qidj. ATi and ATj are homomorphic if qidi = qidj.
Test_AT(
ATi,
ATj): Suppose that
ATi = <
Ci2,
Ci3> and
KTj = <
Cj2,
Cj3>. It computes the following Equation (2). If the result is 1, then
qidi =
qidj. Otherwise,
qidi ≠
qidj.
- C.
Contract Search
Users can always request their contracts to the cloud server. For a contract request, a user ui creates a contract request query CRT_RQST = < “contract request”, KTi, ATi, αu, auth_codeα, timestamp> using GenKeywordToken(idi, wi, qidi, pk). The cloud server first verifies the validity of the request using auth_codeα and the server’s secret αs. If the request is authorized, then the server performs a keyword-based contract search. It finds a keyword token in the file index table that is homomorphic to KTi. In other words, it finds a token KTj such that Test_KT(KTi, KTj) = 1 by doing Test_TK(KTi, KTj) for all KTj in KT. If there is no such KTj, the search fails. If the search succeeded, the bit string of KTj represents the file identifiers of the contracts containing the same keyword as the requested keyword. For all file identifiers such that the bit value of each file identifier is 1, it performs Test_AT(ATi, ATj) for all access tokens ATj attached to the contracts of the selected file identifiers. Finally, it finds contracts such that Test_AT(ATi, ATj) = 1 and responds with the contracts to the request.
Additionally,
ui’ can make a request with multiple keywords. For example, suppose that a worker
ui wants to search a contract containing both
ui’s name
wi and an employer
uj’s name
wj. Then,
ui generates two sets of keyword tokens <
KT1,
AT1> and <
KT2,
AT2> for
wi and
wj, respectively. <
KT1,
AT1> is the output by calling
GenKeywordToken(
idi,
wi,
qidi,
pk) and <
KT2,
AT2> is the output by calling
GenKeywordToken(
idi,
wj,
qidi,
pk). Thus, <
KT1,
AT1> and <
KT2,
AT2> are defined as follows:
where a pair of (
R1 and α
1) and a pair of (
R2 and α
2) are random values used in each
GenKeywordToken() function for
wi and
wj, respectively.
When two sets of keyword tokens are given to the cloud server, it first looks for homomorphic keyword tokens for the given tokens in the file index table. That is, it finds KTi such that Test_KT(KT1, KTi) = 1 and KTj such that Test_KT(KT2, KTj) = 1. Let the bit string of KTi be Bi and the bit string of KTj be Bj. It calculates B = Bi∙Bj where ∙ is an AND bit operation. Then, it finds all file identifiers such that the bit value of B is 1. Finally, it finds contracts satisfying Test_AT(AT1, ATk) = 1 (or Test_AT(AT2, ATk) = 1). AT1 and AT2 are homomorphic access tokens for authenticating the same qidi, so testing for only one access token is sufficient. Remind that a set of contract files represented by a file identifier uploaded at time t is < ECi, ECj, KTi, KTj, ATi, ATj >. There are two different access tokens generated by both signers participated in the contract. Test_AT() works for each AT; if one of them is 1, then, the contract access is authorized. In this way, the proposed contract search algorithm works for multiple keywords.