/
steps.go
179 lines (135 loc) · 3.61 KB
/
steps.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// 25 september 2016
package decryptloop
import (
"fmt"
"crypto/cipher"
"strings"
"github.com/andlabs/reallymine/byteops"
)
// This complicated structure allows us to define a fixed set of Step objects and disallow nil at the same time, reducing the number of things that need validation.
type stepiface interface {
name() string
desc() string
do(c cipher.Block, b []byte)
}
type step struct {
s stepiface
}
type Step step
// for usage information
var validSteps []Step
var stepsByName = make(map[string]Step)
// TODO complain on duplicates
func addstep(s stepiface) Step {
ss := Step{s}
validSteps = append(validSteps, ss)
stepsByName[ss.s.name()] = ss
return ss
}
type stepDecryptType struct{}
func (stepDecryptType) name() string {
return "decrypt"
}
func (stepDecryptType) desc() string {
return "Decrypts the block"
}
func (stepDecryptType) do(c cipher.Block, b []byte) {
c.Decrypt(b, b)
}
var stepDecrypt = addstep(&stepDecryptType{})
var StepDecrypt Step = stepDecrypt
type stepReverseType struct{}
func (stepReverseType) name() string {
return "reverse"
}
func (stepReverseType) desc() string {
return "Reverses the block"
}
func (stepReverseType) do(c cipher.Block, b []byte) {
byteops.Reverse(b)
}
var stepReverse = addstep(&stepReverseType{})
var StepReverse Step = stepReverse
type stepSwapWordsType struct{}
func (stepSwapWordsType) name() string {
return "swapwords"
}
func (stepSwapWordsType) desc() string {
return "Reverses each word (two-byte pair) of the block"
}
func (stepSwapWordsType) do(c cipher.Block, b []byte) {
byteops.SwapWords(b)
}
var stepSwapWords = addstep(&stepSwapWordsType{})
var StepSwapWords Step = stepSwapWords
type stepSwapLongsType struct{}
func (stepSwapLongsType) name() string {
return "swaplongs"
}
func (stepSwapLongsType) desc() string {
return "Reverses each long (four-byte group) of the block"
}
func (stepSwapLongsType) do(c cipher.Block, b []byte) {
byteops.SwapLongs(b)
}
var stepSwapLongs = addstep(&stepSwapLongsType{})
var StepSwapLongs Step = stepSwapLongs
type stepSwapHalvesType struct{}
func (stepSwapHalvesType) name() string {
return "swaphalves"
}
func (stepSwapHalvesType) desc() string {
return "Switches the two halves of the block"
}
func (stepSwapHalvesType) do(c cipher.Block, b []byte) {
byteops.SwapHalves(b)
}
var stepSwapHalves = addstep(&stepSwapHalvesType{})
var StepSwapHalves Step = stepSwapHalves
type StepList []Step
type UnknownStepNameError string
func (e UnknownStepNameError) Error() string {
return fmt.Sprintf("unknown decrypt loop step name %q", string(e))
}
var ErrStepListStringEmpty = fmt.Errorf("step list string is empty/specifies no steps")
func StepListFromString(s string) (StepList, error) {
names := strings.Split(s, " ")
if len(names) == 0 {
return nil, ErrStepListStringEmpty
}
steps := make(StepList, len(names))
for i, name := range names {
step, ok := stepsByName[name]
if !ok {
return nil, UnknownStepNameError(name)
}
steps[i] = step
}
return steps, nil
}
func (s StepList) String() string {
// TODO remove this when PLX is done
if len(s) == 0 {
return "(unknown)"
}
names := make([]string, len(s))
for i, step := range s {
names[i] = step.s.name()
}
return strings.Join(names, " ")
}
// for diskusage.go
func (s StepList) runBlock(c cipher.Block, b []byte) {
for _, step := range s {
step.s.do(c, b)
}
}
// for reallymine to use directly
// TODO merge with package command - can't use command directly since that imports us
func StepUsage() string {
s := ""
for _, step := range validSteps {
s += fmt.Sprintf(" %s - %s\n", step.s.name(), step.s.desc())
}
return s
}