This repository has been archived by the owner on Apr 16, 2024. It is now read-only.
/
aead_cipher.go
74 lines (65 loc) · 1.75 KB
/
aead_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
package ciphers
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"io"
"github.com/mzz2017/softwind/pool"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/hkdf"
)
type CipherConf struct {
KeyLen int
SaltLen int
NonceLen int
TagLen int
NewCipher func(key []byte) (cipher.AEAD, error)
}
const (
MaxNonceSize = 12
ATypeIpv4 = 1
ATypeDomain = 3
ATypeIpv6 = 4
)
var (
AeadCiphersConf = map[string]*CipherConf{
"chacha20-ietf-poly1305": {KeyLen: 32, SaltLen: 32, NonceLen: 12, TagLen: 16, NewCipher: chacha20poly1305.New},
"chacha20-poly1305": {KeyLen: 32, SaltLen: 32, NonceLen: 12, TagLen: 16, NewCipher: chacha20poly1305.New},
"aes-256-gcm": {KeyLen: 32, SaltLen: 32, NonceLen: 12, TagLen: 16, NewCipher: NewGcm},
"aes-128-gcm": {KeyLen: 16, SaltLen: 16, NonceLen: 12, TagLen: 16, NewCipher: NewGcm},
}
ZeroNonce [MaxNonceSize]byte
ReusedInfo = []byte("ss-subkey")
)
func NewGcm(key []byte) (cipher.AEAD, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
}
func (conf *CipherConf) Verify(buf []byte, masterKey []byte, salt []byte, cipherText []byte, subKey *[]byte) ([]byte, bool) {
var sk []byte
if subKey != nil && len(*subKey) == conf.KeyLen {
sk = *subKey
} else {
sk = pool.Get(conf.KeyLen)
defer pool.Put(sk)
kdf := hkdf.New(
sha1.New,
masterKey,
salt,
ReusedInfo,
)
io.ReadFull(kdf, sk)
if subKey != nil && cap(*subKey) >= conf.KeyLen {
*subKey = (*subKey)[:conf.KeyLen]
copy(*subKey, sk)
}
}
ciph, _ := conf.NewCipher(sk)
if _, err := ciph.Open(buf[:0], ZeroNonce[:conf.NonceLen], cipherText, nil); err != nil {
return nil, false
}
return buf[:len(cipherText)-ciph.Overhead()], true
}