-
Notifications
You must be signed in to change notification settings - Fork 0
/
redactor.go
158 lines (143 loc) · 3.94 KB
/
redactor.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
package core
import (
"regexp"
"strings"
"github.com/cyrildever/feistel"
"github.com/cyrildever/feistel/common/utils/base256"
"github.com/cyrildever/redacted/go/model"
)
const DEFAULT_TAG = "~"
//--- TYPES
// Redactor ...
type Redactor struct {
Dictionary model.Dictionary
Tag string
Cipher *feistel.FPECipher
both bool
}
//--- METHODS
// Redact transforms the passed line
func (r Redactor) Redact(line string, delimiters ...string) string {
var actualDelimiters []string
for _, delim := range delimiters {
if delim != " " && delim != "\t" && delim != "\n" {
actualDelimiters = append(actualDelimiters, delim)
}
}
if len(actualDelimiters) == 0 {
actualDelimiters = append(actualDelimiters, "\\s")
}
var outputs []string
re := regexp.MustCompile(strings.Join(actualDelimiters, ""))
words := re.Split(line, -1)
for _, word := range words {
if r.both || r.Dictionary.NonEmpty() {
if r.Dictionary.Contains(word) {
if obfuscated, err := r.Cipher.Encrypt(word); err == nil && obfuscated != "" {
outputs = append(outputs, obfuscated.String())
continue
}
} else if r.Tag != "" && strings.HasPrefix(word, r.Tag) {
toRedact := word[len(r.Tag):]
if obfuscated, err := r.Cipher.Encrypt(toRedact); err == nil && obfuscated != "" {
outputs = append(outputs, r.Tag+obfuscated.String())
continue
}
}
} else if !r.both && r.Dictionary.IsEmpty() {
if r.Tag != "" && strings.HasPrefix(word, r.Tag) {
toRedact := word[len(r.Tag):]
if obfuscated, err := r.Cipher.Encrypt(toRedact); err == nil && obfuscated != "" {
outputs = append(outputs, r.Tag+obfuscated.String())
continue
}
}
}
outputs = append(outputs, word)
}
return strings.Join(outputs, " ")
}
// Expand deciphers the passed line
func (r Redactor) Expand(line string) string {
var outputs []string
re := regexp.MustCompile(`\s`)
words := re.Split(line, -1)
for _, word := range words {
if r.both || r.Dictionary.NonEmpty() {
toExpand := word
expanded := false
if r.Tag != "" && strings.HasPrefix(word, r.Tag) {
toExpand = word[len(r.Tag):]
expanded = true
}
if deciphered, err := r.Cipher.Decrypt(base256.Readable(toExpand)); err == nil {
if r.Dictionary.Contains(deciphered) {
if expanded {
deciphered = r.Tag + deciphered
}
outputs = append(outputs, deciphered)
continue
}
if expanded {
outputs = append(outputs, r.Tag+deciphered)
continue
}
}
} else if !r.both && r.Dictionary.IsEmpty() {
if r.Tag != "" && strings.HasPrefix(word, r.Tag) {
toExpand := word[len(r.Tag):]
if deciphered, err := r.Cipher.Decrypt(base256.Readable(toExpand)); err == nil {
outputs = append(outputs, r.Tag+deciphered)
continue
}
}
}
outputs = append(outputs, word)
}
return strings.Join(outputs, " ")
}
// Clean remove tags from the passed string
func (r Redactor) Clean(str string) string {
if r.Tag != "" {
re := regexp.MustCompile(r.Tag)
return re.ReplaceAllString(str, "")
}
return str
}
//--- FUNCTIONS
// NewRedactor ...
func NewRedactor(dictionary model.Dictionary, tag string, cipher *feistel.FPECipher) (r *Redactor) {
if dictionary.NonEmpty() {
if tag != "" {
r = &Redactor{
Dictionary: dictionary,
Tag: tag,
Cipher: cipher,
both: true,
}
} else {
r = &Redactor{
Dictionary: dictionary,
Cipher: cipher,
}
}
} else {
r = &Redactor{
Tag: tag,
Cipher: cipher,
}
}
return
}
// NewRedactorWithDictionary ...
func NewRedactorWithDictionary(dic model.Dictionary, cipher *feistel.FPECipher) *Redactor {
return NewRedactor(dic, "", cipher)
}
// NewRedactorWithDictionary ...
func NewRedactorWithTag(tag string, cipher *feistel.FPECipher) *Redactor {
return NewRedactor(model.Dictionary{}, tag, cipher)
}
// NewDefaultRedactor ...
func NewDefaultRedactor(cipher *feistel.FPECipher) *Redactor {
return NewRedactor(model.Dictionary{}, DEFAULT_TAG, cipher)
}