client.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. package main
  2. /*
  3. #cgo CFLAGS: -O2
  4. #cgo LDFLAGS: -lcrypto -lm
  5. #include "../c/dpf.h"
  6. #include "../c/okvClient.h"
  7. #include "../c/dpf.c"
  8. #include "../c/okvClient.c"
  9. */
  10. import "C"
  11. //sssssssssss
  12. import (
  13. lib "2PPS/lib"
  14. "bytes"
  15. "crypto/rand"
  16. "crypto/sha256"
  17. "crypto/tls"
  18. "encoding/json"
  19. "fmt"
  20. "math/big"
  21. "net"
  22. "sync"
  23. "time"
  24. "unsafe"
  25. "golang.org/x/crypto/nacl/box"
  26. )
  27. type tweet struct {
  28. Topics []string
  29. Text string
  30. }
  31. const leader string = "127.0.0.1:4441"
  32. //needs to be changed at leader/follower/client at the same time
  33. const neededSubscriptions = 1
  34. const numClients = 2
  35. var topicList []string
  36. var archiveTopicList []string
  37. //todo! expand this for multiple clients
  38. var archiveInterests = make([]int, 1)
  39. var sharedSecret [numClients][2][32]byte = createSharedSecret()
  40. var wantsArchive = make([]byte, 1)
  41. var dataLen int = 32
  42. var numThreads int = 12
  43. var dbWriteSize int = 2
  44. var leaderPublicKey *[32]byte
  45. var followerPublicKey *[32]byte
  46. var clientPrivateKey *[32]byte
  47. var clientPublicKey *[32]byte
  48. func main() {
  49. //creates test tweets
  50. tweets := make([][]byte, numClients)
  51. for i := range tweets {
  52. tweets[i] = make([]byte, dataLen)
  53. }
  54. for i := 0; i < numClients; i++ {
  55. var tweet []byte
  56. if i == 0 {
  57. topics := []byte("house; mouse")
  58. text := []byte("I am a house in a mouse;")
  59. tweet = append(tweet, topics...)
  60. tweet = append(tweet, text...)
  61. }
  62. length := len(tweet)
  63. for i := length; i < dataLen; i++ {
  64. tweet = append(tweet, []byte(";")[0])
  65. }
  66. tweets[i] = tweet
  67. }
  68. wg := &sync.WaitGroup{}
  69. for i := 0; i < numClients; i++ {
  70. wg.Add(1)
  71. go client(tweets[i], i)
  72. }
  73. wg.Wait()
  74. }
  75. func client(tweet []byte, clientNumber int) {
  76. /*
  77. if len(os.Args) != 4 {
  78. fmt.Println("try again with: numThreads, dataLength, numRows")
  79. return
  80. }
  81. //input when executing is follower amount
  82. serverAmount, _ = strconv.Atoi(os.Args[1])
  83. serverAmount++
  84. dataLen, _ = strconv.Atoi(os.Args[2])
  85. numThreads, _ = strconv.Atoi(os.Args[3])
  86. dbSize, _ = strconv.Atoi(os.Args[4])
  87. */
  88. generatedPublicKey, generatedPrivateKey, err := box.GenerateKey(rand.Reader)
  89. if err != nil {
  90. panic(err)
  91. }
  92. clientPrivateKey = generatedPrivateKey
  93. clientPublicKey = generatedPublicKey
  94. C.initializeCipher()
  95. //initializes the connection to the leader
  96. conf := &tls.Config{
  97. InsecureSkipVerify: true,
  98. }
  99. leaderConn, err := tls.Dial("tcp", leader, conf)
  100. if err != nil {
  101. panic(err)
  102. }
  103. leaderConn.SetDeadline(time.Time{})
  104. //receives topics first so client can participate asap
  105. receiveTopicLists(leaderConn)
  106. //gets the public keys of both servers
  107. var tmpLeaderPubKey [32]byte
  108. _, err = leaderConn.Read(tmpLeaderPubKey[:])
  109. if err != nil {
  110. panic(err)
  111. }
  112. leaderPublicKey = &tmpLeaderPubKey
  113. var tmpFollowerPubKey [32]byte
  114. _, err = leaderConn.Read(tmpFollowerPubKey[:])
  115. if err != nil {
  116. panic(err)
  117. }
  118. followerPublicKey = &tmpFollowerPubKey
  119. //sends own public key
  120. _, err = leaderConn.Write(clientPublicKey[:])
  121. if err != nil {
  122. panic(err)
  123. }
  124. //setup ends above
  125. //while client is active he is always connected and has to participate
  126. for {
  127. //gets current phase
  128. phase := make([]byte, 1)
  129. _, err = leaderConn.Read(phase)
  130. if err != nil {
  131. panic(err)
  132. }
  133. fmt.Println("Phase: ", phase[0])
  134. if phase[0] == 1 {
  135. //gets current dbWriteSize from leader
  136. dbWriteSizeBytes := make([]byte, 4)
  137. _, err = leaderConn.Read(dbWriteSizeBytes)
  138. if err != nil {
  139. panic(err)
  140. }
  141. dbWriteSize = byteToInt(dbWriteSizeBytes)
  142. //todo! put into tweet creation
  143. roundAsBytes := make([]byte, 4)
  144. _, err = leaderConn.Read(roundAsBytes)
  145. if err != nil {
  146. panic(err)
  147. }
  148. //prep the query
  149. dataSize := len(tweet)
  150. querySize := make([]byte, 4)
  151. cQuerySize := C.int(byteToInt(querySize))
  152. var dpfQueryA *C.uchar
  153. var dpfQueryB *C.uchar
  154. C.prepQuery(C.int(clientNumber), C.int(dbWriteSize), (*C.uchar)(&tweet[0]), C.int(dataSize), &cQuerySize, &dpfQueryA, &dpfQueryB)
  155. intQuerySize := int(cQuerySize) //byteToInt(querySize)
  156. //write the query
  157. queryAPlaintext := C.GoBytes(unsafe.Pointer(dpfQueryA), C.int(intQuerySize))
  158. //encrypts queryA and appends it to message
  159. var nonce [24]byte
  160. //fill nonce with randomness
  161. _, err = rand.Read(nonce[:])
  162. if err != nil {
  163. panic("couldn't get randomness for nonce!")
  164. }
  165. dpfQueryAEncrypted := box.Seal(nonce[:], queryAPlaintext, &nonce, leaderPublicKey, clientPrivateKey)
  166. //encrypts queryB and appends it to message
  167. queryBPlaintext := C.GoBytes(unsafe.Pointer(dpfQueryB), C.int(intQuerySize))
  168. //fill nonce with randomness
  169. _, err = rand.Read(nonce[:])
  170. if err != nil {
  171. panic("couldn't get randomness for nonce!")
  172. }
  173. dpfQueryBEncrypted := box.Seal(nonce[:], queryBPlaintext, &nonce, followerPublicKey, clientPrivateKey)
  174. //writes the dpfQuery to the leader
  175. dpfLengthBytes := intToByte(len(dpfQueryAEncrypted))
  176. _, err = leaderConn.Write(dpfLengthBytes)
  177. if err != nil {
  178. panic(err)
  179. }
  180. _, err = leaderConn.Write(dpfQueryAEncrypted)
  181. if err != nil {
  182. panic(err)
  183. }
  184. _, err = leaderConn.Write(dpfQueryBEncrypted)
  185. if err != nil {
  186. panic(err)
  187. }
  188. //auditing starts here
  189. //read seed from leader(in preparation for auditing)
  190. seed := make([]byte, 16)
  191. _, err = leaderConn.Read(seed)
  192. if err != nil {
  193. panic(err)
  194. }
  195. //prepare message for auditor, box it, and send to server A
  196. //prepare the auditor message
  197. outputsA := (*C.uchar)(C.malloc(C.ulong(160)))
  198. outputsB := (*C.uchar)(C.malloc(C.ulong(160)))
  199. C.prepAudit((*C.uchar)(&seed[0]), outputsA, outputsB, dpfQueryA, dpfQueryB)
  200. auditPlaintextLeader := C.GoBytes(unsafe.Pointer(outputsA), C.int(160))
  201. auditPlaintextFollower := C.GoBytes(unsafe.Pointer(outputsB), C.int(160))
  202. //encrypt messages for auditing
  203. //fill nonce with randomness
  204. _, err = rand.Read(nonce[:])
  205. if err != nil {
  206. panic("couldn't get randomness for nonce!")
  207. }
  208. auditCiphertextLeader := box.Seal(nonce[:], auditPlaintextLeader, &nonce, leaderPublicKey, clientPrivateKey)
  209. //fill nonce with randomness
  210. _, err = rand.Read(nonce[:])
  211. if err != nil {
  212. panic("couldn't get randomness for nonce!")
  213. }
  214. auditCiphertextFollower := box.Seal(nonce[:], auditPlaintextFollower, &nonce, followerPublicKey, clientPrivateKey)
  215. //send boxed audits to leader
  216. auditLengthBytes := intToByte(len(auditCiphertextLeader))
  217. _, err = leaderConn.Write(auditLengthBytes)
  218. if err != nil {
  219. panic(err)
  220. }
  221. _, err = leaderConn.Write(auditCiphertextLeader)
  222. if err != nil {
  223. panic(err)
  224. }
  225. _, err = leaderConn.Write(auditCiphertextFollower)
  226. if err != nil {
  227. panic(err)
  228. }
  229. C.free(unsafe.Pointer(outputsA))
  230. C.free(unsafe.Pointer(outputsB))
  231. C.free(unsafe.Pointer(dpfQueryA))
  232. C.free(unsafe.Pointer(dpfQueryB))
  233. } else if phase[0] == 3 {
  234. /*
  235. possible Values
  236. 0 : new client
  237. leader expects sharedSecrets, expects pirQuery
  238. 1 : update needed
  239. leader sends topicList, performs local update of sharedSecret, expects pirQuery
  240. 2 : no update needed
  241. nothing
  242. */
  243. subPhase := make([]byte, 1)
  244. _, err := leaderConn.Read(subPhase)
  245. if err != nil {
  246. panic(err)
  247. }
  248. var encryptedQueryLeader, encryptedQueryFollower []byte
  249. //first time participating
  250. if subPhase[0] == 0 {
  251. receiveTopicLists(leaderConn)
  252. encryptedQueryLeader, encryptedQueryFollower = createPIRQuery(int(subPhase[0]), clientNumber)
  253. sendQuerys(encryptedQueryLeader, encryptedQueryFollower, leaderConn, false)
  254. }
  255. //updates the topic list and what client is interested in
  256. if subPhase[0] == 1 {
  257. receiveTopicLists(leaderConn)
  258. //updates local secret
  259. for index := 0; index < 2; index++ {
  260. sharedSecret[clientNumber][index] = sha256.Sum256(sharedSecret[clientNumber][index][:])
  261. }
  262. encryptedQueryLeader, encryptedQueryFollower = createPIRQuery(int(subPhase[0]), clientNumber)
  263. sendQuerys(encryptedQueryLeader, encryptedQueryFollower, leaderConn, false)
  264. }
  265. receiveTweets(sharedSecret[clientNumber], leaderConn, clientNumber, false)
  266. if len(archiveTopicList) > 0 {
  267. wantsArchive[0] = 0 //archive test
  268. } else {
  269. wantsArchive[0] = 0
  270. }
  271. _, err = leaderConn.Write(wantsArchive)
  272. if err != nil {
  273. panic(err)
  274. }
  275. if wantsArchive[0] == 1 && len(archiveTopicList) > 0 {
  276. encryptedQueryLeader, encryptedQueryFollower = createPIRQuery(-1, clientNumber)
  277. sendQuerys(encryptedQueryLeader, encryptedQueryFollower, leaderConn, true)
  278. receiveTweets(sharedSecret[clientNumber], leaderConn, clientNumber, true)
  279. }
  280. } else {
  281. panic("somethin went wrong")
  282. }
  283. }
  284. }
  285. //creates and sends the pirQuerys for each server
  286. func createPIRQuery(subPhase int, clientNumber int) ([]byte, []byte) {
  287. //later this will be taken from gui, this is only for testing
  288. topicsOfInterest := make([]int, 1)
  289. topicsOfInterest[0] = 1
  290. archiveInterests[0] = 1
  291. tmptopicsOfInterest := make([]int, len(topicsOfInterest))
  292. copy(tmptopicsOfInterest, topicsOfInterest)
  293. tmpNeededSubscriptions := neededSubscriptions
  294. tmpTopicList := make([]string, len(topicList))
  295. copy(tmpTopicList, topicList)
  296. if wantsArchive[0] == 1 && subPhase == -1 {
  297. tmpNeededSubscriptions = len(archiveInterests)
  298. copy(tmptopicsOfInterest, archiveInterests) //archiveInterests from gui
  299. copy(tmpTopicList, archiveTopicList)
  300. }
  301. topicsOfInterestAsBytes := make([][]byte, tmpNeededSubscriptions)
  302. for i := range topicsOfInterestAsBytes {
  303. topicsOfInterestAsBytes[i] = make([]byte, len(tmpTopicList))
  304. }
  305. //creates fake topicsOfInterest if client is boooring
  306. if len(tmptopicsOfInterest) < tmpNeededSubscriptions && subPhase != -1 {
  307. //this should be done when client is idling
  308. tmptopicsOfInterest = addFakeInterests(tmptopicsOfInterest)
  309. }
  310. for topic, position := range tmptopicsOfInterest {
  311. topicsOfInterestAsBytes[topic][position-1] = 1
  312. }
  313. //this for N servers for one topic
  314. /* interested in topic 3, 6 servers
  315. this needs to be repeated for every topic client is interested in
  316. wanted
  317. [0, 0, 1]
  318. random creation of 1 pirQuery
  319. [0, 1, 0]
  320. manual creation of 1 pirQuery
  321. [0, 1, 1]
  322. xor result
  323. [0, 0, 1]
  324. */
  325. //pirQuery [serverAmount][topicsofinterest][topicAmount]byte
  326. pirQuerys := make([][][]byte, 2)
  327. for i := range pirQuerys {
  328. pirQuerys[i] = make([][]byte, len(tmptopicsOfInterest))
  329. for j := range pirQuerys[i] {
  330. pirQuerys[i][j] = make([]byte, len(tmpTopicList))
  331. }
  332. }
  333. //for leader
  334. //pirQuery will be filled with random bits
  335. for topic := range tmptopicsOfInterest {
  336. for index := range tmpTopicList {
  337. bit, err := rand.Int(rand.Reader, big.NewInt(2))
  338. if err != nil {
  339. panic(err)
  340. }
  341. pirQuerys[0][topic][index] = byte(bit.Int64())
  342. }
  343. }
  344. //creating last manually with result and wanted
  345. //if position random result correct -> 0, not correct -> 1
  346. for topic := range tmptopicsOfInterest {
  347. for index := range tmpTopicList {
  348. if pirQuerys[0][topic][index] == topicsOfInterestAsBytes[topic][index] {
  349. pirQuerys[1][topic][index] = 0
  350. } else {
  351. pirQuerys[1][topic][index] = 1
  352. }
  353. }
  354. }
  355. //flattens the querys to be able to send them more efficently
  356. messagesFlattened := make([][]byte, 2)
  357. //adds the sharedSecret to the first pirQuery when first time participating
  358. if subPhase == 0 {
  359. for server := 0; server < 2; server++ {
  360. messagesFlattened[server] = append(messagesFlattened[server], sharedSecret[clientNumber][server][:]...)
  361. }
  362. }
  363. for server := 0; server < 2; server++ {
  364. for topic := range pirQuerys[server] {
  365. messagesFlattened[server] = append(messagesFlattened[server], pirQuerys[server][topic][:]...)
  366. }
  367. }
  368. var nonce [24]byte
  369. _, err := rand.Read(nonce[:])
  370. if err != nil {
  371. panic("couldn't get randomness for nonce!")
  372. }
  373. encryptedQueryLeader := box.Seal(nonce[:], messagesFlattened[0], &nonce, leaderPublicKey, clientPrivateKey)
  374. _, err = rand.Read(nonce[:])
  375. if err != nil {
  376. panic("couldn't get randomness for nonce!")
  377. }
  378. encryptedQueryFollower := box.Seal(nonce[:], messagesFlattened[1], &nonce, followerPublicKey, clientPrivateKey)
  379. return encryptedQueryLeader, encryptedQueryFollower
  380. }
  381. func sendQuerys(encryptedQueryLeader, encryptedQueryFollower []byte, leaderConn net.Conn, getArchive bool) {
  382. encryptedLength := len(encryptedQueryLeader)
  383. //sends the pirQuerysLength to the leader
  384. _, err := leaderConn.Write(intToByte(encryptedLength))
  385. if err != nil {
  386. panic(err)
  387. }
  388. //sends the pirQuerys to the leader
  389. _, err = leaderConn.Write(encryptedQueryLeader)
  390. if err != nil {
  391. panic(err)
  392. }
  393. _, err = leaderConn.Write(encryptedQueryFollower)
  394. if err != nil {
  395. panic(err)
  396. }
  397. if getArchive {
  398. leaderConn.Write(intToByte(len(archiveInterests)))
  399. if err != nil {
  400. panic(err)
  401. }
  402. }
  403. }
  404. func receiveTweets(sharedSecret [2][32]byte, leaderConn net.Conn, clientNumber int, getArchive bool) {
  405. tmpNeededSubscriptions := neededSubscriptions
  406. if getArchive {
  407. tmpNeededSubscriptions = len(archiveInterests)
  408. }
  409. for i := 0; i < tmpNeededSubscriptions; i++ {
  410. //client receives tweets
  411. tweetsLengthBytes := make([]byte, 4)
  412. _, err := leaderConn.Read(tweetsLengthBytes)
  413. if err != nil {
  414. panic(err)
  415. }
  416. tweetsLength := byteToInt(tweetsLengthBytes)
  417. tweets := make([]byte, tweetsLength)
  418. _, err = leaderConn.Read(tweets)
  419. if err != nil {
  420. panic(err)
  421. }
  422. //expand sharedSecret so it is of right length
  423. expandBy := len(tweets) / 32
  424. expandedSharedSecrets := make([][]byte, 2)
  425. for i := 0; i < 2; i++ {
  426. for j := 0; j < expandBy; j++ {
  427. expandedSharedSecrets[i] = append(expandedSharedSecrets[i], sharedSecret[i][:]...)
  428. }
  429. //fmt.Println(expandedSharedSecrets[i])
  430. }
  431. //xors the received messge into the message to display
  432. for i := 0; i < 2; i++ {
  433. lib.Xor(expandedSharedSecrets[i][:], tweets)
  434. }
  435. //tweets can be displayed
  436. fmt.Println("final result: ", string(tweets))
  437. }
  438. }
  439. //creates a shared secret for each server
  440. func createSharedSecret() [numClients][2][32]byte {
  441. var tmpSharedSecret [numClients][2][32]byte
  442. for i := 0; i < numClients; i++ {
  443. for j := 0; j < 2; j++ {
  444. _, err := rand.Read(tmpSharedSecret[i][j][:])
  445. if err != nil {
  446. panic("couldn't get randomness for sharedSecret!")
  447. }
  448. }
  449. }
  450. return tmpSharedSecret
  451. }
  452. //generates a topicOfInterest Array with random values
  453. //todo! fix
  454. func addFakeInterests(topicsOfInterest []int) []int {
  455. length := neededSubscriptions
  456. fakeTopicsOfInterest := make([]int, length)
  457. //fills the array with unique random ascending values in range with len(topicList)
  458. for index := 0; index < length; index++ {
  459. min := (index * (len(topicList) / length)) + 1
  460. max := ((index + 1) * (len(topicList) / length))
  461. //fmt.Println("max", max, "list", len(topicList))
  462. if max == len(topicList)-1 {
  463. max++
  464. }
  465. //fmt.Println("i", index, min, max, len(topicList))
  466. bigNumber, err := rand.Int(rand.Reader, big.NewInt(int64(max-min+1)))
  467. if err != nil {
  468. panic(err)
  469. }
  470. var number int = int(bigNumber.Int64()) + min
  471. fakeTopicsOfInterest[index] = number
  472. }
  473. //adds unique and new random numbers to topicOfInterests until length is satisfied
  474. for _, number := range fakeTopicsOfInterest {
  475. if !inList(number, topicsOfInterest) {
  476. topicsOfInterest = append(topicsOfInterest, number)
  477. }
  478. if len(topicsOfInterest) == length {
  479. break
  480. }
  481. }
  482. return topicsOfInterest
  483. }
  484. func inList(number int, list []int) bool {
  485. for _, element := range list {
  486. if element == number {
  487. return true
  488. }
  489. }
  490. return false
  491. }
  492. func receiveTopicLists(leaderConn net.Conn) {
  493. for i := 0; i < 2; i++ {
  494. topicListLength := make([]byte, 4)
  495. _, err := leaderConn.Read(topicListLength)
  496. if err != nil {
  497. panic(err)
  498. }
  499. recTopicList := make([]byte, byteToInt(topicListLength))
  500. _, err = leaderConn.Read(recTopicList[:])
  501. if err != nil {
  502. panic(err)
  503. }
  504. var tmpTopicList []string
  505. arrayReader := bytes.NewReader(recTopicList[:])
  506. json.NewDecoder(arrayReader).Decode(&tmpTopicList)
  507. if i == 0 {
  508. topicList = tmpTopicList
  509. } else {
  510. archiveTopicList = tmpTopicList
  511. }
  512. }
  513. }
  514. func intToByte(myInt int) (retBytes []byte) {
  515. retBytes = make([]byte, 4)
  516. retBytes[3] = byte((myInt >> 24) & 0xff)
  517. retBytes[2] = byte((myInt >> 16) & 0xff)
  518. retBytes[1] = byte((myInt >> 8) & 0xff)
  519. retBytes[0] = byte(myInt & 0xff)
  520. return
  521. }
  522. func byteToInt(myBytes []byte) (x int) {
  523. x = int(myBytes[3])<<24 + int(myBytes[2])<<16 + int(myBytes[1])<<8 + int(myBytes[0])
  524. return
  525. }