aboutsummaryrefslogtreecommitdiff
path: root/inform/crypto.go
diff options
context:
space:
mode:
Diffstat (limited to 'inform/crypto.go')
-rw-r--r--inform/crypto.go50
1 files changed, 49 insertions, 1 deletions
diff --git a/inform/crypto.go b/inform/crypto.go
index 90118c1..4e82741 100644
--- a/inform/crypto.go
+++ b/inform/crypto.go
@@ -5,6 +5,7 @@ import (
5 "crypto/aes" 5 "crypto/aes"
6 "crypto/cipher" 6 "crypto/cipher"
7 "crypto/rand" 7 "crypto/rand"
8 "encoding/binary"
8 "encoding/hex" 9 "encoding/hex"
9 "errors" 10 "errors"
10) 11)
@@ -68,7 +69,54 @@ func Encrypt(payload []byte, key string) ([]byte, []byte, error) {
68 return ct, iv, nil 69 return ct, iv, nil
69} 70}
70 71
71func Decrypt(payload, iv []byte, key string) ([]byte, error) { 72func Decrypt(payload, iv []byte, key string, w *InformWrapper) ([]byte, error) {
73 if !w.IsEncrypted() {
74 return nil, errors.New("payload is not encrypted")
75 }
76
77 if w.IsGCMEncrypted() {
78 return decryptGCM(payload, iv, key, w)
79 } else {
80 return decryptCBC(payload, iv, key)
81 }
82
83 return nil, nil
84}
85
86func buildAuthData(w *InformWrapper, iv []byte) []byte {
87 ad := &bytes.Buffer{}
88 binary.Write(ad, binary.BigEndian, int32(PROTOCOL_MAGIC))
89 binary.Write(ad, binary.BigEndian, int32(w.Version))
90 ad.Write(w.MacAddr)
91 binary.Write(ad, binary.BigEndian, int16(w.Flags))
92 ad.Write(iv)
93 binary.Write(ad, binary.BigEndian, int32(w.DataVersion))
94 binary.Write(ad, binary.BigEndian, int32(w.DataLength))
95 return ad.Bytes()
96}
97
98func decryptGCM(payload, iv []byte, key string, w *InformWrapper) ([]byte, error) {
99 block, err := decodeHexKey(key)
100 if err != nil {
101 return nil, err
102 }
103
104 mode, err := cipher.NewGCMWithNonceSize(block, 16)
105 if err != nil {
106 return nil, err
107 }
108
109 _, err = mode.Open(payload[:0], iv, payload, buildAuthData(w, iv))
110 if err != nil {
111 return nil, err
112 }
113
114 // The last block always seems to be garbage, maybe it's padding or
115 // something else. I have not looked carefully at it.
116 return payload[:len(payload)-aes.BlockSize], nil
117}
118
119func decryptCBC(payload, iv []byte, key string) ([]byte, error) {
72 b := make([]byte, len(payload)) 120 b := make([]byte, len(payload))
73 121
74 block, err := decodeHexKey(key) 122 block, err := decodeHexKey(key)