pax_global_header00006660000000000000000000000064136722567770014540gustar00rootroot0000000000000052 comment=c62e135d4562c3f66087266a57d04200a60d0192 go_eddystone-1.3.1/000077500000000000000000000000001367225677700142255ustar00rootroot00000000000000go_eddystone-1.3.1/.travis.yml000066400000000000000000000000151367225677700163320ustar00rootroot00000000000000language: go go_eddystone-1.3.1/LICENSE000066400000000000000000000024451367225677700152370ustar00rootroot00000000000000Copyright (c) 2015-2020 go_eddystone authors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. go_eddystone-1.3.1/README.md000066400000000000000000000024071367225677700155070ustar00rootroot00000000000000# eddystone : Golang package for support Eddystone beacon [![GoDoc](https://godoc.org/github.com/suapapa/go_eddystone?status.svg)](https://godoc.org/github.com/suapapa/go_eddystone) [![Build Status](https://travis-ci.org/suapapa/go_eddystone.png?branch=master)](https://travis-ci.org/suapapa/go_eddystone) [Eddystone](https://github.com/google/eddystone) is an open beacon format from Google. This package covers [Eddystone-UID][1], [Eddystone-URL][2], [Eddystone-TLM][3] from [Eddystone Protocol Specification][0]. $ go get github.com/suapapa/go_eddystone ## Example Checkout `example/beacon.go` for using this package with [gatt][4] to make a Eddystone beacon in Golang. ## Authors * Homin Lee <homin.lee@suapapa.net> * Luca Capra <luca.capra@gmail.com> ## Copyright & License Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. [0]: https://github.com/google/eddystone/blob/master/protocol-specification.md [1]: https://github.com/google/eddystone/tree/master/eddystone-uid [2]: https://github.com/google/eddystone/tree/master/eddystone-url [3]: https://github.com/google/eddystone/tree/master/eddystone-tlm [4]: https://github.com/paypal/gatt go_eddystone-1.3.1/cast.go000066400000000000000000000016731367225677700155150ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "encoding/hex" "errors" ) // fixed point representation : https://courses.cit.cornell.edu/ee476/Math/ func float32ToFix(a float32) uint16 { return uint16(a * 256) } func fixTofloat32(a uint16) float32 { if a&0x8000 == 0 { return float32(a) / 256.0 } return -(float32(^a) + 1) / 256.0 } func intToByte(a int) byte { return byte(a & 0xff) } func byteToInt(a byte) (v int) { v = int(a) if v&0x80 != 0 { v = -((^v + 1) & 0xff) } return } func hexStringToBytes(s string, size int) ([]byte, error) { r, err := hex.DecodeString(s) if err != nil { return nil, err } if len(r) > size { return nil, errors.New("too long data") } if len(r) < size { return append(make([]byte, size-len(r), size), r...), nil } return r, nil } go_eddystone-1.3.1/cast_test.go000066400000000000000000000024121367225677700165440ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "bytes" "testing" ) var testData = map[float32]uint16{ 0.0: 0x0000, 1.0: 0x0100, 1.5: 0x0180, 1.75: 0x01c0, // 1.00396: 0x0101, // FAIL on TestFixToFloat32. got:1.003906 -1.0: 0xff00, -1.5: 0xfe80, -2: 0xfe00, -127: 0x8100, -0.5: 0xff80, -0.25: 0xffc0, 0.5: 0x0080, -128: 0x8000, 127: 0x7f00, 2.25: 0x0240, -2.25: 0xfdc0, } func TestFloat32ToFix(t *testing.T) { for k, v := range testData { got := float32ToFix(k) if got != v { t.Errorf("%f wanted: 0x%04x, got:0x%04x", k, v, got) } } } func TestFixToFloat32(t *testing.T) { for k, v := range testData { got := fixTofloat32(v) if got != k { t.Errorf("0x%04x wanted: %f, got:%f", v, k, got) } } } func TestIntToByte(t *testing.T) { if intToByte(-18) != 0xee { t.Errorf("failed to convert int to byte") } if byteToInt(0xee) != -18 { t.Errorf("failed to convert byte to int") } } func TestHexStringToBytes(t *testing.T) { b, _ := hexStringToBytes("0102", 4) if !bytes.Equal([]byte{0x00, 0x00, 0x01, 0x02}, b) { t.Errorf("failed to convert hexString to bytes") } } go_eddystone-1.3.1/doc.go000066400000000000000000000004011367225677700153140ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package eddystone provides tools for making Eddystone frame package eddystone go_eddystone-1.3.1/example/000077500000000000000000000000001367225677700156605ustar00rootroot00000000000000go_eddystone-1.3.1/example/beacon.go000066400000000000000000000025661367225677700174470ustar00rootroot00000000000000package main import ( "fmt" "log" "github.com/paypal/gatt" "github.com/paypal/gatt/examples/option" "github.com/suapapa/go_eddystone" ) const ( advTypeAllUUID16 = 0x03 // Complete List of 16-bit Service Class UUIDs advTypeServiceData16 = 0x16 // Service Data - 16-bit UUID ) const ( advFlagGeneralDiscoverable = 0x02 advFlagLEOnly = 0x04 ) func main() { f, err := eddystone.MakeURLFrame("http://google.com", -20) if err != nil { panic(err) } fmt.Println(f) // Advertise as an Eddystone beacon a := &gatt.AdvPacket{} a.AppendFlags(advFlagGeneralDiscoverable | advFlagLEOnly) a.AppendField(advTypeAllUUID16, eddystone.SvcUUIDBytes) a.AppendField(advTypeServiceData16, append(eddystone.SvcUUIDBytes, f...)) fmt.Println(a.Len(), a) d, err := gatt.NewDevice(option.DefaultServerOptions...) if err != nil { log.Fatalf("Failed to open device, err: %s", err) } // Register optional handlers. d.Handle( gatt.CentralConnected(func(c gatt.Central) { fmt.Println("Connect: ", c.ID()) }), gatt.CentralDisconnected(func(c gatt.Central) { fmt.Println("Disconnect: ", c.ID()) }), ) // A mandatory handler for monitoring device state. onStateChanged := func(d gatt.Device, s gatt.State) { fmt.Printf("State: %s\n", s) switch s { case gatt.StatePoweredOn: d.Advertise(a) default: log.Println(s) } } d.Init(onStateChanged) select {} } go_eddystone-1.3.1/example_test.go000066400000000000000000000024421367225677700172500ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone_test import ( "fmt" eddystone "github.com/suapapa/go_eddystone" ) func ExampleMakeUIDFrame() { f, _ := eddystone.MakeUIDFrame("0102030405060708090a", "0b0c0d0e0f10", -30) fmt.Println(f) fmt.Println([]byte(f)) // Output: UID[Namespace:0x0102030405060708090a Instance:0x0b0c0d0e0f10 TxPwr:-30dBm] // [0 226 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0 0] } func ExampleMakeURLFrame() { f, _ := eddystone.MakeURLFrame("http://github.com", -30) fmt.Println(f) fmt.Println([]byte(f)) // Output: URL[Url:http://github.com TxPwr:-30dBm] // [16 226 2 103 105 116 104 117 98 7] } func ExampleMakeTLMFrame() { f, _ := eddystone.MakeTLMFrame(3300, 23.5, 1, 2) fmt.Println(f) fmt.Println([]byte(f)) // Output: TLM[batt:3300 temp:23.500000, advCnt:1 secCnt:2] // [32 0 12 228 23 128 0 0 0 1 0 0 0 2] } func ExampleMakeEIDFrameFromBytes() { eid, _ := eddystone.ComputeEIDValue([]byte("0123456789abcdef"), 0x12345678, 8) f, _ := eddystone.MakeEIDFrameFromBytes(eid, -30) fmt.Println(f) fmt.Println([]byte(f)) // EID[EphemetalIdentifier:0xb846453b3c9e7b59 TxPwr:-30dBm] // [48 226 184 70 69 59 60 158 123 89] } go_eddystone-1.3.1/frame.go000066400000000000000000000066071367225677700156570ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "encoding/binary" "encoding/hex" "fmt" ) // Frame represent Eddystone frame type Frame []byte // MakeUIDFrame makes Eddystone-UID frame // https://github.com/google/eddystone/tree/master/eddystone-uid func MakeUIDFrame(namespace, instance string, txPwr int) (Frame, error) { n, err := hexStringToBytes(namespace, 10) if err != nil { return nil, err } i, err := hexStringToBytes(instance, 6) if err != nil { return nil, err } f := make(Frame, 2, 20) f[0] = byte(UID) f[1] = intToByte(txPwr) f = append(f, n...) f = append(f, i...) f = append(f, 0x00, 0x00) return f, nil } // MakeUIDFrameFromBytes makes Eddystone-UID frame from namespace and instance bytes // https://github.com/google/eddystone/tree/master/eddystone-uid func MakeUIDFrameFromBytes(namespace, instance []byte, txPwr int) (Frame, error) { if len(namespace) != 10 { return nil, fmt.Errorf("namespace should be length of 10") } if len(instance) != 6 { return nil, fmt.Errorf("instance should be length of 10") } f := make(Frame, 2, 20) f[0] = byte(UID) f[1] = intToByte(txPwr) f = append(f, namespace...) f = append(f, instance...) f = append(f, 0x00, 0x00) return f, nil } // MakeURLFrame makes Eddystone-URL frame // https://github.com/google/eddystone/tree/master/eddystone-url func MakeURLFrame(url string, txPwr int) (Frame, error) { p, u, err := encodeURL(url) if err != nil { return nil, err } f := make(Frame, 3, 21) f[0] = byte(URL) f[1] = intToByte(txPwr) f[2] = p f = append(f, u...) return f, nil } // MakeTLMFrame makes Eddystone-TLM frame // https://github.com/google/eddystone/tree/master/eddystone-tlm func MakeTLMFrame(batt uint16, temp float32, advCnt, secCnt uint32) (Frame, error) { f := make(Frame, 14) f[0] = byte(TLM) f[1] = 0x00 // TLM version // TODO: check min mix for each items binary.BigEndian.PutUint16(f[2:2+2], batt) binary.BigEndian.PutUint16(f[4:4+2], float32ToFix(temp)) binary.BigEndian.PutUint32(f[6:6+4], advCnt) binary.BigEndian.PutUint32(f[10:10+4], secCnt) return f, nil } // MakeEIDFrameFromBytes makes Eddystone-EID frame from EID bytes // https://github.com/google/eddystone/tree/master/eddystone-eid func MakeEIDFrameFromBytes(eid []byte, txPwr int) (Frame, error) { if len(eid) != 8 { return nil, fmt.Errorf("eid should be length of 8") } f := make(Frame, 2, 10) f[0] = byte(EID) f[1] = intToByte(txPwr) return append(f, eid...), nil } func (f Frame) String() string { t := Header(f[0]) switch t { case UID: return fmt.Sprintf("%s[Namespace:0x%s Instance:0x%s TxPwr:%ddBm]", t, hex.EncodeToString(f[2:2+10]), hex.EncodeToString(f[12:12+6]), byteToInt(f[1]), ) case URL: url, err := decodeURL(f[2], f[3:]) if err != nil { panic(err) } return fmt.Sprintf("%s[Url:%s TxPwr:%ddBm]", t, url, byteToInt(f[1]), ) case TLM: return fmt.Sprintf("%s[batt:%d temp:%f, advCnt:%d secCnt:%d]", t, binary.BigEndian.Uint16(f[2:2+2]), fixTofloat32(binary.BigEndian.Uint16(f[4:4+2])), binary.BigEndian.Uint32(f[6:6+4]), binary.BigEndian.Uint32(f[10:10+4]), ) case EID: return fmt.Sprintf("%s[EphemetalIdentifier:0x%s TxPwr:%ddBm]", t, hex.EncodeToString(f[2:2+8]), byteToInt(f[1]), ) } return t.String() } go_eddystone-1.3.1/frame_test.go000066400000000000000000000026601367225677700167110ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "bytes" "testing" ) func TestMakeUIDFrame(t *testing.T) { f, err := MakeUIDFrame("0102030405060708090a", "123456", -30) if err != nil { panic(err) } expect := []byte{ 0, // hdrUID intToByte(-30), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0, 0, } if !bytes.Equal([]byte(f), expect) { t.Errorf("expect: %v, got:%v", expect, []byte(f)) } } func TestMakeURLFrame(t *testing.T) { urlGoogle := "http://google.com/" f, err := MakeURLFrame(urlGoogle, -20) if err != nil { panic(err) } expect := []byte{ 0x10, // hdrURL intToByte(-20), 0x02, // URL Scheme Prefix: http:// 'g', // 'g' 'o', // 'o' 'o', // 'o' 'g', // 'g' 'l', // 'l' 'e', // 'e' 0x00, // Eddystone-URL HTTP URL encoding: .com/ } if !bytes.Equal([]byte(f), expect) { t.Errorf("expect: %v, got:%v", expect, []byte(f)) } } func TestMakeTLMFrame(t *testing.T) { f, err := MakeTLMFrame(50, 28, 100, 100) if err != nil { panic(err) } expect := []byte{ 0x20, // hdrTLM 0x00, 0x00, 0x32, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, } if !bytes.Equal([]byte(f), expect) { t.Errorf("expect: %v, got:%v", expect, []byte(f)) } } go_eddystone-1.3.1/go.mod000066400000000000000000000002271367225677700153340ustar00rootroot00000000000000module github.com/suapapa/go_eddystone go 1.14 require ( github.com/google/uuid v1.1.1 github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf ) go_eddystone-1.3.1/header.go000066400000000000000000000015111367225677700160020ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone // SvcUUID is Eddystone service UUID const SvcUUID = 0xFEAA var ( // SvcUUIDBytes is Eddystone service UUID in Little Endian format SvcUUIDBytes = []byte{0xAA, 0xFE} ) // Header for Eddystone frames type Header byte func (hdr Header) String() string { switch hdr { case UID: return "UID" case URL: return "URL" case TLM: return "TLM" case EID: return "EID" } return "Unknown" } // Eddystone frame types const ( // UID means UID frame UID Header = 0x00 // URL means URL frame URL = 0x10 // TLM means TLM frame TLM = 0x20 // EID means EID frame EID = 0x30 // Unknown means it may not Eddystone frame Unknown = 0xff ) go_eddystone-1.3.1/parse.go000066400000000000000000000022121367225677700156630ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "encoding/binary" "encoding/hex" ) // ParseHeader returns type of Eddystone frame func ParseHeader(frames []byte) Header { return Header(frames[0]) } // ParseUIDFrame returns contents of UID frame func ParseUIDFrame(f []byte) (ns, instance string, txPower int) { return hex.EncodeToString(f[2 : 2+10]), hex.EncodeToString(f[12 : 12+6]), byteToInt(f[1]) } // ParseURLFrame returns contents of URL frame func ParseURLFrame(f []byte) (url string, txPower int, err error) { txPower = byteToInt(f[1]) url, err = decodeURL(f[2], f[3:]) if err != nil { return url, txPower, err } return url, txPower, nil } // ParseTLMFrame returns contents of TLM frame func ParseTLMFrame(f []byte) (batt uint16, temp float32, advCnt uint32, secCnt uint32) { return binary.BigEndian.Uint16(f[2 : 2+2]), fixTofloat32(binary.BigEndian.Uint16(f[4 : 4+2])), binary.BigEndian.Uint32(f[6 : 6+4]), binary.BigEndian.Uint32(f[10 : 10+4]) } // TODO: ParseEIDFrame go_eddystone-1.3.1/parse_test.go000066400000000000000000000041111367225677700167220ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "fmt" "strings" "testing" ) func TestParseHeader(t *testing.T) { frames := []byte{byte(UID)} hdr := ParseHeader(frames) if hdr != UID { t.Fatal("Expected type is UID") } frames = []byte{byte(TLM)} hdr = ParseHeader(frames) if hdr != TLM { t.Fatal("Expected type is TLM") } frames = []byte{byte(URL)} hdr = ParseHeader(frames) if hdr != URL { t.Fatal("Expected type is URL") } } func TestParseUIDFrame(t *testing.T) { namespace := "AAAAAAAAAABBBBBBBBBB" instance := "123456123456" txPwr := 99 f, err := MakeUIDFrame(namespace, instance, txPwr) if err != nil { t.Fatal(err) } namespace1, instance1, txPower1 := ParseUIDFrame(f) if namespace != strings.ToUpper(namespace1) { t.Fatal("namespace mismatch", namespace, namespace1) } if instance != instance1 { t.Fatal("instance mismatch", instance, instance1) } if txPwr != txPower1 { t.Fatal("txPower mismatch", txPwr, txPower1) } } func TestParseTLMFrame(t *testing.T) { var batt uint16 = 10 var temp float32 = 30.1 var advCnt uint32 = 100 var secCnt uint32 = 200 f, err := MakeTLMFrame(batt, temp, advCnt, secCnt) if err != nil { t.Fatal(err) } batt1, temp1, advCnt1, secCnt1 := ParseTLMFrame(f) if batt != batt1 { t.Fatal("batt mismatch", batt, batt1) } tempr := fmt.Sprintf("%.2f", temp) tempr1 := fmt.Sprintf("%.2f", temp1) if tempr != tempr1 { t.Fatal("temp mismatch", temp, temp1) } if advCnt != advCnt1 { t.Fatal("advCnt mismatch", advCnt, advCnt1) } if secCnt != secCnt1 { t.Fatal("secCnt mismatch", secCnt, secCnt1) } } func TestParseURLFrame(t *testing.T) { url := "https://example.com" txPwr := 99 f, err := MakeURLFrame(url, txPwr) if err != nil { t.Fatal(err) } url1, txPwr1, err := ParseURLFrame(f) if err != nil { t.Fatal(err) } if url != url1 { t.Fatal("url mismatch", url, url1) } if txPwr != txPwr1 { t.Fatal("txPwr mismatch", txPwr, txPwr1) } } go_eddystone-1.3.1/url.go000066400000000000000000000024661367225677700153660ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "errors" "strings" ) var urlSchemePrefix = []string{ "http://www.", "https://www.", "http://", "https://", } var urlEncoding = []string{ ".com/", ".org/", ".edu/", ".net/", ".info/", ".biz/", ".gov/", ".com", ".org", ".edu", ".net", ".info", ".biz", ".gov", } func encodeURL(u string) (byte, []byte, error) { prefix := byte(0x02) // http:// for i, v := range urlSchemePrefix { if strings.HasPrefix(u, v) { prefix = byte(i) u = u[len(v):] break } } for i, v := range urlEncoding { u = strings.Replace(u, v, string(byte(i)), -1) } if len(u) > 17 { return 0x00, nil, errors.New("url too long") } return prefix, []byte(u), nil } func decodeURL(prefix byte, encodedURL []byte) (string, error) { if int(prefix) >= len(urlSchemePrefix) { return "", errors.New("invaild prefix") } s := urlSchemePrefix[prefix] for _, b := range encodedURL { switch { case 0x00 <= b && b <= 0x13: s += urlEncoding[b] case 0x0e <= b && b <= 0x20: fallthrough case 0x7f <= b && b <= 0xff: return "", errors.New("invalid byte") default: s += string(b) } } return s, nil } go_eddystone-1.3.1/util.go000066400000000000000000000042301367225677700155300ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "crypto/aes" "crypto/sha1" "encoding/binary" "encoding/hex" "fmt" "strings" "github.com/google/uuid" ) // ConstructNSByTruncatedHashFQDN return 10 bytes namespace for UID frame // by traucated hash of FQDN func ConstructNSByTruncatedHashFQDN(fqdn string) []byte { h := sha1.New() h.Write([]byte(fqdn)) bs := h.Sum(nil) return bs[:10] } // ConstructNSByElidedUUID return 10 bytes namespace for UID frame // by elided version 4 UUID func ConstructNSByElidedUUID(id uuid.UUID) []byte { idStr := id.String() idStr = strings.Replace(idStr, "-", "", -1) uuidBytes, _ := hex.DecodeString(idStr) return append(uuidBytes[:4], uuidBytes[10:]...) } // ComputeEIDValue returns 8 bytes EID value // https://github.com/google/eddystone/blob/master/eddystone-eid/eid-computation.md func ComputeEIDValue(identityKey []byte, ts uint32, k byte) (eid []byte, err error) { if len(identityKey) != 16 { return nil, fmt.Errorf("identityKey should be 16byte length for AES-128") } if 0 > k || k > 15 { return nil, fmt.Errorf("k should be between 0 and 15") } ts = ts & makeTsMask(k) tsBytes := make([]byte, 4) binary.BigEndian.PutUint32(tsBytes, ts) // computing the temporary key tmpKeySrc := make([]byte, 11) // padding tmpKeySrc = append(tmpKeySrc, 0xFF) // salt tmpKeySrc = append(tmpKeySrc, 0x00, 0x00) // padding tmpKeySrc = append(tmpKeySrc, tsBytes[0:0+2]...) tmpBlk, err := aes.NewCipher(identityKey) if err != nil { return nil, err } tmpKey := make([]byte, 16) tmpBlk.Encrypt(tmpKey, tmpKeySrc) // computing the EID value eidSrc := make([]byte, 11) // padding eidSrc = append(eidSrc, k) // rotation period exponent eidSrc = append(eidSrc, tsBytes...) eidBlk, err := aes.NewCipher(tmpKey) if err != nil { return nil, err } eid = make([]byte, 16) eidBlk.Encrypt(eid, eidSrc) return eid[:8], nil } func makeTsMask(k byte) uint32 { var tsMask uint32 for i := byte(0); i < k; i++ { tsMask <<= 1 tsMask |= 1 } return ^tsMask } go_eddystone-1.3.1/util_test.go000066400000000000000000000022721367225677700165730ustar00rootroot00000000000000// Copyright (c) 2015-2020, go_eddystone authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eddystone import ( "bytes" "encoding/hex" "testing" "github.com/google/uuid" ) func TestConstructNSByTracatedHashFQDN(t *testing.T) { expect := []byte{228, 27, 42, 224, 106, 114, 155, 150, 228, 185} got := ConstructNSByTruncatedHashFQDN("kakaoenterprise.com") if !bytes.Equal(expect, got) { t.Errorf("expect %v got %v", expect, got) } } func TestConsturctNSByElidedUUID(t *testing.T) { expect, _ := hex.DecodeString("8b0ca750095477cb3e77") id, _ := uuid.Parse("8b0ca750-e7a7-4e14-bd99-095477cb3e77") got := ConstructNSByElidedUUID(id) if !bytes.Equal(expect, got) { t.Errorf("expect %v got %v", expect, got) } } func TestMakeTsMask(t *testing.T) { expect := uint32(0xFFFFFFFF) got := makeTsMask(0) if expect != got { t.Errorf("expect %v got %v", expect, got) } expect = uint32(0xFFFFFFF0) got = makeTsMask(4) if expect != got { t.Errorf("expect %v got %v", expect, got) } expect = uint32(0xFFFF8000) got = makeTsMask(15) if expect != got { t.Errorf("expect %v got %v", expect, got) } }