Files
kcp-go/crypt.go
T
2016-06-29 22:18:39 +08:00

156 lines
3.9 KiB
Go

package kcp
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/tea"
)
var (
initialVector = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}
saltxor = `sH3CIVoF#rWLtJo6`
)
// BlockCrypt defines encryption/decryption methods for a given byte slice
type BlockCrypt interface {
// Encrypt encrypts the whole block in src into dst.
// Dst and src may point at the same memory.
Encrypt(dst, src []byte)
// Decrypt decrypts the whole block in src into dst.
// Dst and src may point at the same memory.
Decrypt(dst, src []byte)
}
// AESBlockCrypt implements BlockCrypt with AES
type AESBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
// NewAESBlockCrypt initates AES BlockCrypt by the given key
func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
c := new(AESBlockCrypt)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
c.block = block
c.encbuf = make([]byte, aes.BlockSize)
c.decbuf = make([]byte, 2*aes.BlockSize)
return c, nil
}
// Encrypt implements Encrypt interface
func (c *AESBlockCrypt) Encrypt(dst, src []byte) {
encrypt(c.block, dst, src, c.encbuf)
}
// Decrypt implements Decrypt interface
func (c *AESBlockCrypt) Decrypt(dst, src []byte) {
decrypt(c.block, dst, src, c.decbuf)
}
// TEABlockCrypt implements BlockCrypt with TEA
type TEABlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
// NewTEABlockCrypt initate TEA BlockCrypt by the given key
func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
c := new(TEABlockCrypt)
block, err := tea.NewCipherWithRounds(key, 16)
if err != nil {
return nil, err
}
c.block = block
c.encbuf = make([]byte, tea.BlockSize)
c.decbuf = make([]byte, 2*tea.BlockSize)
return c, nil
}
// Encrypt implements Encrypt interface
func (c *TEABlockCrypt) Encrypt(dst, src []byte) {
encrypt(c.block, dst, src, c.encbuf)
}
// Decrypt implements Decrypt interface
func (c *TEABlockCrypt) Decrypt(dst, src []byte) {
decrypt(c.block, dst, src, c.decbuf)
}
// SimpleXORBlockCrypt implements BlockCrypt with simple xor to a table
type SimpleXORBlockCrypt struct {
xortbl []byte
}
// NewSimpleXORBlockCrypt initate SimpleXORBlockCrypt by the given key
func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
c := new(SimpleXORBlockCrypt)
c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
return c, nil
}
// Encrypt implements Encrypt interface
func (c *SimpleXORBlockCrypt) Encrypt(dst, src []byte) {
xorBytes(dst, src, c.xortbl)
}
// Decrypt implements Decrypt interface
func (c *SimpleXORBlockCrypt) Decrypt(dst, src []byte) {
xorBytes(dst, src, c.xortbl)
}
// NoneBlockCrypt simple returns the plaintext
type NoneBlockCrypt struct {
xortbl []byte
}
// NewNoneBlockCrypt initate NoneBlockCrypt by the given key
func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
return new(NoneBlockCrypt), nil
}
// Encrypt implements Encrypt interface
func (c *NoneBlockCrypt) Encrypt(dst, src []byte) {}
// Decrypt implements Decrypt interface
func (c *NoneBlockCrypt) Decrypt(dst, src []byte) {}
// packet encryption with local CFB mode
func encrypt(block cipher.Block, dst, src, buf []byte) {
blocksize := block.BlockSize()
tbl := buf[:blocksize]
block.Encrypt(tbl, initialVector)
n := len(src) / blocksize
base := 0
for i := 0; i < n; i++ {
xorWords(dst[base:], src[base:], tbl)
block.Encrypt(tbl, dst[base:])
base += blocksize
}
xorBytes(dst[base:], src[base:], tbl)
}
func decrypt(block cipher.Block, dst, src, buf []byte) {
blocksize := block.BlockSize()
tbl := buf[:blocksize]
next := buf[blocksize:]
block.Encrypt(tbl, initialVector)
n := len(src) / blocksize
base := 0
for i := 0; i < n; i++ {
block.Encrypt(next, src[base:])
xorWords(dst[base:], src[base:], tbl)
tbl, next = next, tbl
base += blocksize
}
xorBytes(dst[base:], src[base:], tbl)
}