Skip to content

Commit 6fe71d7

Browse files
committed
Don't use PRNG (for portability to other languages); add documentation
1 parent 12468c5 commit 6fe71d7

File tree

3 files changed

+61
-40
lines changed

3 files changed

+61
-40
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Programmatic generation of US English word lists.
13+
- Generation of machine names from 32-bit serial numbers.

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,29 @@ Devices often assign a (pseudo-)unique serial number to each unit. However, each
77

88
## Usage
99

10-
TBD
10+
First, you will need to download machine-name, which is available as a single self-contained executable file. You should visit this repository's [releases page](https://github.com/PlanktoScope/machine-name/releases/latest) and download an archive file for your platform and CPU architecture; for example, on a Raspberry Pi 4, you should download the archive named `machine-name{version number}_linux_arm.tar.gz` (where the version number should be substituted). You can extract the machine-name binary from the archive using a command like:
11+
```
12+
tar -xzf machine-name{version number}_{os}_{cpu architecture}.tar.gz machine-name
13+
```
14+
15+
Then you may need to move the machine-name binary into a directory in your system path, or you can just run the machine-name binary in your current directory (in which case you should replace `machine-name` with `./machine-name` in the commands listed below).
16+
17+
Once you have machine-name, you should run it as follows:
18+
```
19+
machine-name name --format=hex --sn=0xd6b82659
20+
```
21+
but replacing `0xd6b82659` with a 32-bit hex string representing a serial number. The program will then print the machine name corresponding to that serial number. For example, the following serial numbers will result in the following machine names:
22+
23+
| Serial Number | Machine Name |
24+
|---------------|-----------------------|
25+
| `0xdeadc0de` | metal-slope-23501 |
26+
| `0xd6b82659` | chain-list-27764 |
27+
| `0x0` | able-account-0 |
28+
| `0x1` | small-ball-26954 |
29+
| `0x2` | safe-minute-6738 |
30+
| `0x3` | linen-opinion-33692 |
31+
| `0x4` | conscious-pocket-1684 |
32+
| `0x8123` | clear-field-33719 |
1133

1234
## Licensing
1335

cmd/machinename/main.go

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"io/fs"
66
"log"
77
"math/bits"
8-
"math/rand"
98
"os"
109
"strconv"
1110
"strings"
@@ -69,16 +68,7 @@ var nameCmd = &cli.Command{
6968
if err != nil {
7069
return errors.Wrapf(err, "couldn't load wordlists for language '%s", c.String("lang"))
7170
}
72-
shuffleWordlist(first, 0)
73-
shuffleWordlist(second, 1)
74-
firstSize := uint32(len(first))
75-
secondSize := uint32(len(second))
76-
quotient := shuffle(parsed)
77-
firstIndex := quotient % firstSize
78-
quotient /= firstSize
79-
secondIndex := quotient % secondSize
80-
quotient /= secondSize
81-
fmt.Printf("%s-%s-%d\n", first[firstIndex], second[secondIndex], quotient)
71+
fmt.Println(computeName(parsed, first, second))
8272
return nil
8373
},
8474
}
@@ -127,55 +117,63 @@ func loadWordlist(lang fs.FS, file string) ([]string, error) {
127117
return words, nil
128118
}
129119

130-
func shuffleWordlist(wordlist []string, randSeed int64) {
131-
rng := rand.New(rand.NewSource(randSeed)) //nolint:gosec // We need a PRNG to shuffle reproducibly
132-
rng.Shuffle(len(wordlist), func(i, j int) {
133-
atI := wordlist[i]
134-
atJ := wordlist[j]
135-
wordlist[i] = atJ
136-
wordlist[j] = atI
137-
})
120+
func computeName(sn uint32, first []string, second []string) string {
121+
firstSize := uint32(len(first))
122+
secondSize := uint32(len(second))
123+
quotient := shuffle(sn)
124+
firstIndex := quotient % firstSize
125+
quotient /= firstSize
126+
secondIndex := quotient % secondSize
127+
quotient /= secondSize
128+
return fmt.Sprintf("%s-%s-%d\n", first[firstIndex], second[secondIndex], quotient)
138129
}
139130

131+
const (
132+
shuffleShift8 = 8
133+
shuffleShift4 = 4
134+
shuffleShift2 = 2
135+
shuffleShift1 = 1
136+
shuffleMask8 = 0x0000ff00
137+
shuffleMask4 = 0x00f000f0
138+
shuffleMask2 = 0x0c0c0c0c
139+
shuffleMask1 = 0x22222222
140+
)
141+
140142
// shuffle performs a one-to-one mapping of the serial number so that consecutive numbers are no
141143
// longer close to each other.
142-
//
143-
//nolint:gomnd // We need a bunch of well-defined bit shifts and masks for this algorithm
144144
func shuffle(x uint32) uint32 {
145145
// This code was copied from the Hacker's Delight website at
146146
// https://web.archive.org/web/20160405214331/http://hackersdelight.org/hdcodetxt/shuffle.c.txt
147147
// which is licensed released to the public domain - for details, refer to
148148
// https://web.archive.org/web/20160309224818/http://www.hackersdelight.org/permissions.htm
149-
t := (x ^ (x >> 8)) & 0x0000ff00
150-
x = x ^ t ^ (t << 8)
151-
t = (x ^ (x >> 4)) & 0x00f000f0
152-
x = x ^ t ^ (t << 4)
153-
t = (x ^ (x >> 2)) & 0x0c0c0c0c
154-
x = x ^ t ^ (t << 2)
155-
t = (x ^ (x >> 1)) & 0x22222222
156-
x = x ^ t ^ (t << 1)
149+
t := (x ^ (x >> shuffleShift8)) & shuffleMask8
150+
x = x ^ t ^ (t << shuffleShift8)
151+
t = (x ^ (x >> shuffleShift4)) & shuffleMask4
152+
x = x ^ t ^ (t << shuffleShift4)
153+
t = (x ^ (x >> shuffleShift2)) & shuffleMask2
154+
x = x ^ t ^ (t << shuffleShift2)
155+
t = (x ^ (x >> shuffleShift1)) & shuffleMask1
156+
x = x ^ t ^ (t << shuffleShift1)
157157
x = bits.Reverse32(x)
158158
return x
159159
}
160160

161161
/*
162162
// unshuffle inverts the shuffle operation.
163-
//
164-
//nolint:gomnd // We need a bunch of well-defined bit shifts and masks for this algorithm
165163
func unshuffle(x uint32) uint32 {
166164
// This code was copied from the Hacker's Delight website at
167165
// https://web.archive.org/web/20160405214331/http://hackersdelight.org/hdcodetxt/shuffle.c.txt
168166
// which is licensed released to the public domain - for details, refer to
169167
// https://web.archive.org/web/20160309224818/http://www.hackersdelight.org/permissions.htm
170168
x = bits.Reverse32(x)
171-
t := (x ^ (x >> 1)) & 0x22222222
172-
x = x ^ t ^ (t << 1)
173-
t = (x ^ (x >> 2)) & 0x0c0c0c0c
174-
x = x ^ t ^ (t << 2)
175-
t = (x ^ (x >> 4)) & 0x00f000f0
176-
x = x ^ t ^ (t << 4)
177-
t = (x ^ (x >> 8)) & 0x0000ff00
178-
x = x ^ t ^ (t << 8)
169+
t := (x ^ (x >> shuffleShift1)) & shuffleMask1
170+
x = x ^ t ^ (t << shuffleShift1)
171+
t = (x ^ (x >> shuffleShift2)) & shuffleMask2
172+
x = x ^ t ^ (t << shuffleShift2)
173+
t = (x ^ (x >> shuffleShift4)) & shuffleMask4
174+
x = x ^ t ^ (t << shuffleShift4)
175+
t = (x ^ (x >> shuffleShift8)) & shuffleMask8
176+
x = x ^ t ^ (t << shuffleShift8)
179177
return x
180178
}
181179
*/

0 commit comments

Comments
 (0)