client.go 18 KB

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