mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-10-05 16:26:50 +08:00
116 lines
2.7 KiB
Go
116 lines
2.7 KiB
Go
package iot
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/md5"
|
|
"encoding/binary"
|
|
"errors"
|
|
"hash/crc32"
|
|
)
|
|
|
|
// key - convert timestamp to key
|
|
func (c *Codec) key(timestamp uint32) []byte {
|
|
const salt = "TXdfu$jyZ#TZHsg4"
|
|
key := md5.Sum([]byte(encodeTimestamp(timestamp) + c.devKey + salt))
|
|
return key[:]
|
|
}
|
|
|
|
func (c *Codec) Decrypt(cipherText []byte) ([]byte, error) {
|
|
if len(cipherText) < 32 || string(cipherText[:3]) != "1.0" {
|
|
return nil, errors.New("wrong message prefix")
|
|
}
|
|
|
|
i := len(cipherText) - 4
|
|
if binary.BigEndian.Uint32(cipherText[i:]) != crc32.ChecksumIEEE(cipherText[:i]) {
|
|
return nil, errors.New("wrong message checksum")
|
|
}
|
|
|
|
if proto := binary.BigEndian.Uint16(cipherText[15:]); proto != 102 {
|
|
return nil, nil
|
|
}
|
|
|
|
timestamp := binary.BigEndian.Uint32(cipherText[11:])
|
|
return decryptECB(cipherText[19:i], c.key(timestamp)), nil
|
|
}
|
|
|
|
func (c *Codec) Encrypt(plainText []byte, seq, random, timestamp uint32) []byte {
|
|
const proto = 101
|
|
|
|
cipherText := encryptECB(plainText, c.key(timestamp))
|
|
|
|
size := uint16(len(cipherText))
|
|
|
|
msg := make([]byte, 23+size)
|
|
copy(msg, "1.0")
|
|
binary.BigEndian.PutUint32(msg[3:], seq)
|
|
binary.BigEndian.PutUint32(msg[7:], random)
|
|
binary.BigEndian.PutUint32(msg[11:], timestamp)
|
|
binary.BigEndian.PutUint16(msg[15:], proto)
|
|
binary.BigEndian.PutUint16(msg[17:], size)
|
|
copy(msg[19:], cipherText)
|
|
|
|
crc := crc32.ChecksumIEEE(msg[:19+size])
|
|
|
|
binary.BigEndian.PutUint32(msg[19+size:], crc)
|
|
return msg
|
|
}
|
|
|
|
func encodeTimestamp(i uint32) string {
|
|
const hextable = "0123456789abcdef"
|
|
b := []byte{
|
|
hextable[i>>8&0xF], hextable[i>>4&0xF],
|
|
hextable[i>>16&0xF], hextable[i&0xF],
|
|
hextable[i>>24&0xF], hextable[i>>20&0xF],
|
|
hextable[i>>28&0xF], hextable[i>>12&0xF],
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
func pad(plainText []byte, blockSize int) []byte {
|
|
b0 := byte(blockSize - len(plainText)%blockSize)
|
|
for i := byte(0); i < b0; i++ {
|
|
plainText = append(plainText, b0)
|
|
}
|
|
return plainText
|
|
}
|
|
|
|
func unpad(paddedText []byte) []byte {
|
|
padSize := int(paddedText[len(paddedText)-1])
|
|
return paddedText[:len(paddedText)-padSize]
|
|
}
|
|
|
|
func encryptECB(plainText, key []byte) []byte {
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
blockSize := block.BlockSize()
|
|
plainText = pad(plainText, blockSize)
|
|
cipherText := plainText
|
|
|
|
for len(plainText) > 0 {
|
|
block.Encrypt(plainText, plainText)
|
|
plainText = plainText[blockSize:]
|
|
}
|
|
|
|
return cipherText
|
|
}
|
|
|
|
func decryptECB(cipherText, key []byte) []byte {
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
blockSize := block.BlockSize()
|
|
paddedText := cipherText
|
|
|
|
for len(cipherText) > 0 {
|
|
block.Decrypt(cipherText, cipherText)
|
|
cipherText = cipherText[blockSize:]
|
|
}
|
|
|
|
return unpad(paddedText)
|
|
}
|