client.go 16 KB

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