-
Notifications
You must be signed in to change notification settings - Fork 15
/
rotor.go
76 lines (68 loc) · 2.01 KB
/
rotor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package enigma
// Rotor is the device performing letter substitutions inside
// the Enigma machine. Rotors can be put in different positions,
// swapped, and replaced; they are also rotated during the encoding
// process, following the machine configuration. As a result, there
// are millions of possible combinations, making brute-forcing attacks
// on Enigma unfeasible (and even more so when the plugboard is used).
type Rotor struct {
ID string
StraightSeq [26]int
ReverseSeq [26]int
Turnover []int
Offset int
Ring int
}
// NewRotor is a constructor for rotors, taking a mapping string
// and a turnover position.
func NewRotor(mapping string, id string, turnovers string) *Rotor {
r := &Rotor{ID: id, Offset: 0, Ring: 0}
r.Turnover = make([]int, len(turnovers))
for i := range turnovers {
r.Turnover[i] = CharToIndex(turnovers[i])
}
for i, letter := range mapping {
index := CharToIndex(byte(letter))
r.StraightSeq[i] = index
r.ReverseSeq[index] = i
}
return r
}
// Move the rotor, shifting the offset by a given number.
func (r *Rotor) move(offset int) {
r.Offset = (r.Offset + offset) % 26
}
// ShouldTurnOver checks if the current rotor position corresponds
// to a notch that is supposed to move the next rotor.
func (r *Rotor) ShouldTurnOver() bool {
for _, turnover := range r.Turnover {
if r.Offset == turnover {
return true
}
}
return false
}
// Step through the rotor, performing the letter substitution depending
// on the offset and direction.
func (r *Rotor) Step(letter int, invert bool) int {
letter = (letter - r.Ring + r.Offset + 26) % 26
if invert {
letter = r.ReverseSeq[letter]
} else {
letter = r.StraightSeq[letter]
}
letter = (letter + r.Ring - r.Offset + 26) % 26
return letter
}
// Rotors is a simple list of rotor pointers.
type Rotors []Rotor
// GetByID takes a "name" of the rotor (e.g. "III") and returns the
// Rotor pointer.
func (rs *Rotors) GetByID(id string) *Rotor {
for _, rotor := range *rs {
if rotor.ID == id {
return &rotor
}
}
return nil
}