-
Notifications
You must be signed in to change notification settings - Fork 1
/
symmetric_stream.go
113 lines (81 loc) · 3.03 KB
/
symmetric_stream.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
package ecies
import (
"crypto/cipher"
"io"
)
var (
CTRCipherMode = SymmetricCipherMode{
Encryptor: CTREncrypt,
Decryptor: CTRDecrypt,
}
CFBCipherMode = SymmetricCipherMode{
Encryptor: CFBEncrypt,
Decryptor: CFBDecrypt,
}
)
// CTREncrypt carries out CTR encryption using the block cipher specified in the
// parameters.
func CTREncrypt(rand io.Reader, params *ECIESParams, key, plaintext, authenticationData []byte) ([]byte, error) {
stream, err := params.Cipher(key)
if err != nil {
return nil, err
}
iv, err := GenerateIV(params.BlockSize, rand)
if err != nil {
return nil, err
}
return SymmetricStreamEncrypt(cipher.NewCTR, stream, iv, key, plaintext), nil
}
// CTRDecrypt carries out CTR decryption using the block cipher specified in
// the parameters
func CTRDecrypt(rand io.Reader, params *ECIESParams, key, ciphertext, authenticationData []byte) ([]byte, error) {
stream, err := params.Cipher(key)
if err != nil {
return nil, err
}
return SymmetricStreamDecrypt(cipher.NewCTR, stream, ciphertext[:params.BlockSize], key, ciphertext[params.BlockSize:]), nil
}
// CFBEncrypt performs Cipher Feedback (CFB) encryption using the block cipher specified in
// the parameters
func CFBEncrypt(rand io.Reader, params *ECIESParams, key, plaintext, authenticationData []byte) ([]byte, error) {
blockCipher, err := params.Cipher(key)
if err != nil {
return nil, err
}
iv, err := GenerateIV(params.BlockSize, rand)
if err != nil {
return nil, err
}
return SymmetricStreamEncrypt(cipher.NewCFBEncrypter, blockCipher, iv, key, plaintext), nil
}
// CFBDecrypt performs Cipher Feedback (CFB) decryption using the block cipher specified in
// the parameters
func CFBDecrypt(rand io.Reader, params *ECIESParams, key, ciphertext, authenticationData []byte) ([]byte, error) {
blockCipher, err := params.Cipher(key)
if err != nil {
return nil, err
}
return SymmetricStreamDecrypt(cipher.NewCFBDecrypter, blockCipher, ciphertext[:params.BlockSize], key, ciphertext[params.BlockSize:]), nil
}
// Performs sysmmetric encrypion using the specified stream cipher
func SymmetricStreamEncrypt(str func(cipher.Block, []byte) cipher.Stream, blockCipher cipher.Block, iv []byte, key, plaintext []byte) (ciphertext []byte) {
// Initialize the cipher
streamCipher := str(blockCipher, iv)
// Creates a byte sink the size of plaintext plus iv
ciphertext = make([]byte, len(plaintext)+len(iv))
// First params.BlockSize bytes are filled with the iv
copy(ciphertext, iv)
// The remaining bytes are filled with the encrypted message
streamCipher.XORKeyStream(ciphertext[len(iv):], plaintext)
return
}
// Performs sysmmetric decryption using the specified stream cipher
func SymmetricStreamDecrypt(str func(cipher.Block, []byte) cipher.Stream, blockCipher cipher.Block, iv []byte, key, ciphertext []byte) (plaintext []byte) {
// Initialize the cipher
streamCipher := str(blockCipher, iv)
// Prepare the byte sink
plaintext = make([]byte, len(ciphertext))
// Decrypt the ciphertext
streamCipher.XORKeyStream(plaintext, ciphertext)
return
}