├── Advanced_Meter.csv ├── COPYRIGHT ├── README.md ├── build_index.py ├── keywordlist ├── masterkey ├── sse_search.py └── trapdoor.py /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Please contact the author (jli103@vols.utk.edu) to obtain permission before using either the source code or algorithm for commercial purpose. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Searchable_Encryption 2 | This project gives the python 2.7 implementation of a space efficient searchable encryption algorithm for smart grid data. 3 | 4 | **Anyone who uses the algorithm or the source code need to cite the following paper:** 5 | 6 | **_Jiangnan Li, Xiangyu Niu, and Jinyuan Stella Sun, " A Practical Searchable Symmetric Encryption Scheme for Smart Grid Data, " 2019 IEEE International Conference on Communication (ICC), Shanghai, China, May 2019_** 7 | 8 | **build_index.py** is used to build an search index for the given csv file. The request input are a csv file, a document that stores master key and a document contains the keyword types that the client want to search. The output is a csv file that stores the hex string index. 9 | 10 | **trapdoor.py** is used to generate the trapdoor for a given keyword. 11 | 12 | **sse_search.py** is used to search documents that contains a specific keyword. The input should be the hex string index dociment and the trapdoor of the keyword to be searched. 13 | 14 | **Advanced_Meter.csv** is the document that contains statistical AMI data provided by EIA. keywordlist is a document contains ten keywords selected by the author. masterkey contains the master key for index build. 15 | 16 | The source code requires Pandas library for CSV file reading. 17 | 18 | A simple demenstration of this project can be: 19 | 20 | In terminal: 21 | 22 | (1) 23 | 24 | python build_index.py 25 | 26 | Please input the file to be encrypted: Advanced_Meter.csv 27 | 28 | Please input the file stored the master key: masterkey 29 | 30 | please input the file stores keyword type: keywordlist 31 | 32 | Finished 33 | 34 | (A csv file named Advanced_Meter_index.csv will be generated) 35 | 36 | (2) 37 | 38 | python trapdoor.py 39 | 40 | Please input the keyword you want to search: TN 41 | 42 | Please input the file that stored the master key: masterkey 43 | 44 | (A file named TN_trapdoor will be generated) 45 | 46 | (3) 47 | 48 | python sse_search.py 49 | 50 | Please input the index file you want to search: Advanced_Meter_index.csv 51 | 52 | Please input the file stored the trapdoor you want to search: TN_trapdoor 53 | 54 | The identifiers of records that contain the keyword are: 55 | 56 | [308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750] 57 | -------------------------------------------------------------------------------- /build_index.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from Crypto.Cipher import AES 3 | from Crypto.Hash import MD5 4 | from Crypto.Random import random 5 | import numpy as np 6 | import time 7 | 8 | 9 | def build_trapdoor(MK, keyword): 10 | keyword_index = MD5.new() 11 | keyword_index.update(str(keyword)) 12 | ECB_cipher = AES.new(MK, AES.MODE_ECB) 13 | return ECB_cipher.encrypt(keyword_index.digest()) 14 | 15 | 16 | def build_codeword(ID, trapdoor): 17 | ID_index = MD5.new() 18 | ID_index.update(str(ID)) 19 | ECB_cipher = AES.new(trapdoor, AES.MODE_ECB) 20 | return ECB_cipher.encrypt(ID_index.digest()).encode("hex") 21 | 22 | 23 | def build_index(MK, ID, keyword_list): 24 | secure_index = [0] * len(keyword_list) 25 | for i in range(len(keyword_list)): 26 | codeword = build_codeword(ID, build_trapdoor(MK, keyword_list[i])) 27 | secure_index[i] = codeword 28 | random.shuffle(secure_index) 29 | return secure_index 30 | 31 | def searchable_encryption(raw_data_file_name, master_key, keyword_type_list): 32 | raw_data = pd.read_csv(raw_data_file_name) 33 | features = list(raw_data) 34 | raw_data = raw_data.values 35 | 36 | keyword_number = [i for i in range(0, len(features)) if features[i] in keyword_type_list] 37 | 38 | index_header = [] 39 | for i in range(1, len(keyword_type_list) + 1): 40 | index_header.append("index_" + str(i)) 41 | 42 | document_index = [] 43 | start_time = time.time() 44 | for row in range(raw_data.shape[0]): 45 | record = raw_data[row] 46 | record_keyword_list = [record[i] for i in keyword_number] 47 | record_index = build_index(master_key, row, record_keyword_list) 48 | document_index.append(record_index) 49 | 50 | time_cost = time.time() - start_time 51 | print time_cost 52 | document_index_dataframe = pd.DataFrame(np.array(document_index), columns=index_header) 53 | document_index_dataframe.to_csv(raw_data_file_name.split(".")[0] + "_index.csv") 54 | 55 | 56 | if __name__ == "__main__": 57 | 58 | document_name = raw_input("Please input the file to be encrypted: ") 59 | 60 | master_key_file_name = raw_input("Please input the file stored the master key: ") 61 | master_key = open(master_key_file_name).read() 62 | if len(master_key) > 16: 63 | print "the length of master key is larger than 16 bytes, only the first 16 bytes are used" 64 | master_key = bytes(master_key[:16]) 65 | 66 | keyword_list_file_name = raw_input("please input the file stores keyword type: ") 67 | keyword_type_list = open(keyword_list_file_name).read().split(",") 68 | 69 | searchable_encryption(document_name, master_key, keyword_type_list) 70 | 71 | print "Finished" 72 | 73 | -------------------------------------------------------------------------------- /keywordlist: -------------------------------------------------------------------------------- 1 | Year,Month,Utility_Number,Name,State,AMI_Res,AMI_Com,AMI_Ind,AMI_Tran,AMI_Total -------------------------------------------------------------------------------- /masterkey: -------------------------------------------------------------------------------- 1 | huskudynzjdylopt -------------------------------------------------------------------------------- /sse_search.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from Crypto.Cipher import AES 3 | from Crypto.Hash import MD5 4 | # import time 5 | 6 | def build_codeword(ID, trapdoor): 7 | ID_index = MD5.new() 8 | ID_index.update(str(ID)) 9 | ECB_cipher = AES.new(trapdoor, AES.MODE_ECB) 10 | return ECB_cipher.encrypt(ID_index.digest()).encode("hex") 11 | 12 | def search_index(document, trapdoor): 13 | search_result = [] 14 | data_index = pd.read_csv(document) 15 | data_index = data_index.values 16 | # start_time = time.time() 17 | for row in range(data_index.shape[0]): 18 | if build_codeword(row, trapdoor) in data_index[row]: 19 | search_result.append(row) 20 | 21 | # print time.time() - start_time 22 | return search_result 23 | 24 | if __name__ == "__main__": 25 | 26 | index_file_name = raw_input("Please input the index file you want to search: ") 27 | keyword_trapdoor = raw_input("Please input the file stored the trapdoor you want to search: ") 28 | keyword_trapdoor = open(keyword_trapdoor).read().strip() 29 | search_result = search_index(index_file_name, keyword_trapdoor) 30 | print "The identifiers of files that contain the keyword are: \n", search_result 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /trapdoor.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | from Crypto.Hash import MD5 3 | 4 | 5 | def build_trapdoor(MK, keyword): 6 | keyword_index = MD5.new() 7 | keyword_index.update(str(keyword)) 8 | ECB_cipher = AES.new(MK, AES.MODE_ECB) 9 | return ECB_cipher.encrypt(keyword_index.digest()) 10 | 11 | if __name__ == "__main__": 12 | 13 | keyword = raw_input("Please input the keyword you want to search: ") 14 | 15 | master_key_file_name = raw_input("Please input the file stored the master key: ") 16 | master_key = open(master_key_file_name).read() 17 | if len(master_key) > 16: 18 | print "the length of master key is larger than 16 bytes, only the first 16 bytes are used" 19 | master_key = bytes(master_key[:16]) 20 | 21 | 22 | trapdoor_file = open(keyword + "_trapdoor", "w+") 23 | trapdoor_of_keyword = build_trapdoor(master_key, keyword) 24 | trapdoor_file.write(trapdoor_of_keyword) 25 | trapdoor_file.close() --------------------------------------------------------------------------------