-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfenam_cipher.go
131 lines (115 loc) · 3.9 KB
/
fenam_cipher.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
package fenam_cipher
import (
"fmt"
cycle_string "github.com/cryptography-research-lab/go-cycle-string"
if_expression "github.com/golang-infrastructure/go-if-expression"
stack "github.com/golang-infrastructure/go-stack"
variable_parameter "github.com/golang-infrastructure/go-variable-parameter"
"math"
"strings"
)
// ------------------------------------------------- --------------------------------------------------------------------
// 当不指定秘钥时默认的秘钥
var defaultSecurityKey = "CC"
// Encrypt 对文本使用费娜姆加密
func Encrypt(asciiText string, securityKey ...string) (string, error) {
securityKey = variable_parameter.SetDefaultParam(securityKey, defaultSecurityKey)
plaintextBinaryString, err := convertAsciiStringToBinaryString(asciiText)
if err != nil {
return "", err
}
securityBinaryString, err := convertAsciiStringToBinaryString(securityKey[0])
if err != nil {
return "", err
}
return binaryStringXOR(plaintextBinaryString, securityBinaryString), nil
}
// 把ascii字符串转为二进制字符串
func convertAsciiStringToBinaryString(asciiText string) (string, error) {
result := strings.Builder{}
for _, char := range asciiText {
if !(char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z') {
return "", ErrEncryptText
}
binaryString := intToBinaryString(int(char))
result.WriteString(binaryString)
}
return result.String(), nil
}
// 不使用内置库了,自己写一下
func intToBinaryString(number int) string {
// 除2取余,逆序排列
stack := stack.NewStack[int]()
for number > 0 {
stack.Push(number % 2)
number /= 2
}
// 补前缀零
for stack.Size() < 7 {
stack.Push('0')
}
// 转为字符串
result := strings.Builder{}
for stack.IsNotEmpty() {
result.WriteString(fmt.Sprintf("%d", stack.Pop()))
}
return result.String()
}
// 使用秘钥再进行一次加密
func binaryStringXOR(binaryStringA, binaryStringB string) string {
cycleBinaryString := cycle_string.NewCycleString(binaryStringB)
result := make([]rune, len(binaryStringA))
for index, charA := range binaryStringA {
charB := cycleBinaryString.RuneAt(index)
// 异或运算
if charA == charB {
result[index] = '0'
} else {
result[index] = '1'
}
}
return string(result)
}
// ------------------------------------------------- --------------------------------------------------------------------
// Decrypt 对文本进行费娜姆解密
func Decrypt(encryptBinaryText string, securityKey ...string) (string, error) {
securityKey = variable_parameter.SetDefaultParam(securityKey, defaultSecurityKey)
// 把秘钥也转为二进制字符串的形式
securityKeyBinaryString, err := convertAsciiStringToBinaryString(securityKey[0])
if err != nil {
return "", err
}
// 然后xor解密
plaintextBinaryString := binaryStringXOR(encryptBinaryText, securityKeyBinaryString)
// 转为可读的ascii形式
return convertBinaryStringToAsciiString(plaintextBinaryString)
}
func convertBinaryStringToAsciiString(binaryString string) (string, error) {
result := strings.Builder{}
index := 0
for index < len(binaryString) {
nextIndex := index + 7
if nextIndex > len(binaryString) {
return "", fmt.Errorf("binary string not mod 7: %s", binaryString)
}
groupBinaryString := binaryString[index:nextIndex]
char := fromBinaryString(groupBinaryString)
if !(char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z') {
return "", ErrEncryptText
}
result.WriteRune(rune(char))
index = nextIndex
}
return result.String(), nil
}
// 把二进制字符转为十进制数字
func fromBinaryString(binaryString string) int {
result := 0
weight := 0
for index := len(binaryString) - 1; index >= 0; index-- {
result += int(math.Pow(float64(2), float64(weight))) * if_expression.Return(binaryString[index] == '0', 0, 1)
weight++
}
return result
}
// ------------------------------------------------- --------------------------------------------------------------------