diff options
Diffstat (limited to 'inform/crypto.go')
-rw-r--r-- | inform/crypto.go | 50 |
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 | ||
71 | func Decrypt(payload, iv []byte, key string) ([]byte, error) { | 72 | func 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 | |||
86 | func 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 | |||
98 | func 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 | |||
119 | func 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) |