-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvigenere.go
76 lines (70 loc) · 2.06 KB
/
vigenere.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 vinegar
import (
"slices"
"strings"
)
// Enforce interface
var _ Vigenere = (*vigenere)(nil)
// vigenere is the implementation of the Vigenere cipher containing the table
// used for encryption and decryption of plain/cipher text
type vigenere struct {
table [26][26]rune
}
// NewVigenere produces a Vigenere Table using the given keyword. It first
// will format the keyword given by removing any duplicates and enforcing it
// to be 26 lowercasse latin characters. Once formatted the table is produced
// by shifting the alphabet 26 times maaking a 26x26 matrix of runes
func NewVigenere(keyword string) Vigenere {
v := &vigenere{
table: [26][26]rune{},
}
alphabet := "abcdefghijklmnopqrstuvwxyz"
if keyword != "" {
valid := formatTableKeyword(keyword)
for _, c := range valid {
alphabet = strings.ReplaceAll(alphabet, string(c), "")
}
alphabet = valid + alphabet
}
v.table[0] = ([26]rune)([]rune(alphabet))
for i := 1; i < 26; i++ {
alphabet = alphabet[1:] + string(alphabet[0])
v.table[i] = ([26]rune)([]rune(alphabet))
}
return v
}
// Encrypt encrypts the given message using the keyword provided
// according to the vigenere table of the Vigenere struct.
func (v *vigenere) Encrypt(message, keyword string) string {
msg := formatKeyword(message)
key := formatEncryptionKeyword(keyword, msg)
str := strings.Builder{}
for i := 0; i < len(msg); i++ {
p := rune(msg[i])
idx := slices.Index(v.table[0][:], rune(key[i]))
for _, row := range v.table {
if row[0] == p {
str.WriteRune(row[idx])
break
}
}
}
return str.String()
}
// Decrypt decrypts the provided ciphertext using the keyword and
// vigenere table from the struct - the resulting plaintext will have no spaces.
func (v *vigenere) Decrypt(cipher, keyword string) string {
key := formatEncryptionKeyword(keyword, cipher)
str := strings.Builder{}
for i := 0; i < len(cipher); i++ {
c := rune(cipher[i])
idx := slices.Index(v.table[0][:], rune(key[i]))
for _, row := range v.table {
if row[idx] == c {
str.WriteRune(row[0])
break
}
}
}
return str.String()
}