forked from bougou/go-ipmi
/
helpers_hmac.go
133 lines (109 loc) · 3.38 KB
/
helpers_hmac.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
package ipmi
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/md5"
"crypto/rc4"
"crypto/sha1"
"crypto/sha256"
"fmt"
)
// generate_hmac generates message authentication code.
// Currently supported algorithms are: "md5", "sha1", "sha256"
//
// hmac, hash-based message authentication code
// mac, message authentication code
// md, message digest
func generate_hmac(alg string, data []byte, key []byte) ([]byte, error) {
switch alg {
case "md5":
h := hmac.New(md5.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac md5 failed, err: %s", err)
}
return h.Sum(nil), nil
case "sha1":
h := hmac.New(sha1.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac sha1 failed, err: %s", err)
}
return h.Sum(nil), nil
case "sha256":
h := hmac.New(sha256.New, key)
_, err := h.Write(data)
if err != nil {
return nil, fmt.Errorf("hmac sha256 failed, err: %s", err)
}
return h.Sum(nil), nil
default:
return nil, fmt.Errorf("not support for hmac algorithm %s", alg)
}
}
func generate_auth_hmac(authAlg AuthAlg, data []byte, key []byte) ([]byte, error) {
switch authAlg {
case AuthAlgRAKP_None:
return []byte{}, nil
case AuthAlgRAKP_HMAC_MD5:
return generate_hmac("md5", data, key)
case AuthAlgRAKP_HMAC_SHA1:
return generate_hmac("sha1", data, key)
case AuthAlgRAKP_HMAC_SHA256:
return generate_hmac("sha256", data, key)
default:
return nil, fmt.Errorf("not support for authentication algorithm %x", authAlg)
}
}
// The plainText must be already padded.
// The cipherKey length is either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
func encryptAES(plainText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
if len(plainText)%aes.BlockSize != 0 {
return nil, fmt.Errorf("input plainText must be mutiple of aes block size (16)")
}
l := len(cipherKey)
if l != 16 && l != 24 && l != 32 {
return nil, fmt.Errorf("cipherKey length must be either 16, 24, 32")
}
cipherBlock, err := aes.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %s", err)
}
cipherText := make([]byte, len(plainText))
mode := cipher.NewCBCEncrypter(cipherBlock, iv)
mode.CryptBlocks(cipherText, plainText)
return cipherText, nil
}
func decryptAES(cipherText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
l := len(cipherKey)
if l != 16 && l != 24 && l != 32 {
return nil, fmt.Errorf("cipherKey length must be either 16, 24, 32")
}
cipherBlock, err := aes.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %s", err)
}
plainText := make([]byte, len(cipherText))
mode := cipher.NewCBCDecrypter(cipherBlock, iv)
mode.CryptBlocks(plainText, cipherText)
return plainText, nil
}
func encryptRC4(plainText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
rc4Cipher, err := rc4.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %s", err)
}
cipherText := make([]byte, len(plainText))
rc4Cipher.XORKeyStream(cipherText, plainText)
return cipherText, nil
}
func decryptRC4(cipherText []byte, cipherKey []byte, iv []byte) ([]byte, error) {
rc4Cipher, err := rc4.NewCipher(cipherKey)
if err != nil {
return nil, fmt.Errorf("NewCipher failed, err: %s", err)
}
plainText := make([]byte, len(cipherText))
rc4Cipher.XORKeyStream(plainText, cipherText)
return plainText, nil
}