mirror of
https://gogs.blitter.com/RLabs/xs
synced 2024-08-14 10:26:42 +00:00
786 lines
19 KiB
Go
786 lines
19 KiB
Go
|
package kcp
|
||
|
|
||
|
import (
|
||
|
"crypto/aes"
|
||
|
"crypto/cipher"
|
||
|
"crypto/des"
|
||
|
"crypto/sha1"
|
||
|
|
||
|
"github.com/templexxx/xor"
|
||
|
"github.com/tjfoc/gmsm/sm4"
|
||
|
|
||
|
"golang.org/x/crypto/blowfish"
|
||
|
"golang.org/x/crypto/cast5"
|
||
|
"golang.org/x/crypto/pbkdf2"
|
||
|
"golang.org/x/crypto/salsa20"
|
||
|
"golang.org/x/crypto/tea"
|
||
|
"golang.org/x/crypto/twofish"
|
||
|
"golang.org/x/crypto/xtea"
|
||
|
)
|
||
|
|
||
|
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.
|
||
|
// Notes on implementing: the data to be encrypted contains a builtin
|
||
|
// nonce at the first 16 bytes
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
type salsa20BlockCrypt struct {
|
||
|
key [32]byte
|
||
|
}
|
||
|
|
||
|
// NewSalsa20BlockCrypt https://en.wikipedia.org/wiki/Salsa20
|
||
|
func NewSalsa20BlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(salsa20BlockCrypt)
|
||
|
copy(c.key[:], key)
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) {
|
||
|
salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
|
||
|
copy(dst[:8], src[:8])
|
||
|
}
|
||
|
func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) {
|
||
|
salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
|
||
|
copy(dst[:8], src[:8])
|
||
|
}
|
||
|
|
||
|
type sm4BlockCrypt struct {
|
||
|
encbuf [sm4.BlockSize]byte
|
||
|
decbuf [2 * sm4.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewSM4BlockCrypt https://github.com/tjfoc/gmsm/tree/master/sm4
|
||
|
func NewSM4BlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(sm4BlockCrypt)
|
||
|
block, err := sm4.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *sm4BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *sm4BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type twofishBlockCrypt struct {
|
||
|
encbuf [twofish.BlockSize]byte
|
||
|
decbuf [2 * twofish.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish
|
||
|
func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(twofishBlockCrypt)
|
||
|
block, err := twofish.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type tripleDESBlockCrypt struct {
|
||
|
encbuf [des.BlockSize]byte
|
||
|
decbuf [2 * des.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES
|
||
|
func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(tripleDESBlockCrypt)
|
||
|
block, err := des.NewTripleDESCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type cast5BlockCrypt struct {
|
||
|
encbuf [cast5.BlockSize]byte
|
||
|
decbuf [2 * cast5.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewCast5BlockCrypt https://en.wikipedia.org/wiki/CAST-128
|
||
|
func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(cast5BlockCrypt)
|
||
|
block, err := cast5.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type blowfishBlockCrypt struct {
|
||
|
encbuf [blowfish.BlockSize]byte
|
||
|
decbuf [2 * blowfish.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher)
|
||
|
func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(blowfishBlockCrypt)
|
||
|
block, err := blowfish.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type aesBlockCrypt struct {
|
||
|
encbuf [aes.BlockSize]byte
|
||
|
decbuf [2 * aes.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewAESBlockCrypt https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||
|
func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(aesBlockCrypt)
|
||
|
block, err := aes.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *aesBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *aesBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type teaBlockCrypt struct {
|
||
|
encbuf [tea.BlockSize]byte
|
||
|
decbuf [2 * tea.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewTEABlockCrypt https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
|
||
|
func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(teaBlockCrypt)
|
||
|
block, err := tea.NewCipherWithRounds(key, 16)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type xteaBlockCrypt struct {
|
||
|
encbuf [xtea.BlockSize]byte
|
||
|
decbuf [2 * xtea.BlockSize]byte
|
||
|
block cipher.Block
|
||
|
}
|
||
|
|
||
|
// NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA
|
||
|
func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(xteaBlockCrypt)
|
||
|
block, err := xtea.NewCipher(key)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
c.block = block
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
|
||
|
func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
|
||
|
|
||
|
type simpleXORBlockCrypt struct {
|
||
|
xortbl []byte
|
||
|
}
|
||
|
|
||
|
// NewSimpleXORBlockCrypt simple xor with key expanding
|
||
|
func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
c := new(simpleXORBlockCrypt)
|
||
|
c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (c *simpleXORBlockCrypt) Encrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) }
|
||
|
func (c *simpleXORBlockCrypt) Decrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) }
|
||
|
|
||
|
type noneBlockCrypt struct{}
|
||
|
|
||
|
// NewNoneBlockCrypt does nothing but copying
|
||
|
func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
|
||
|
return new(noneBlockCrypt), nil
|
||
|
}
|
||
|
|
||
|
func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) }
|
||
|
func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) }
|
||
|
|
||
|
// packet encryption with local CFB mode
|
||
|
func encrypt(block cipher.Block, dst, src, buf []byte) {
|
||
|
switch block.BlockSize() {
|
||
|
case 8:
|
||
|
encrypt8(block, dst, src, buf)
|
||
|
case 16:
|
||
|
encrypt16(block, dst, src, buf)
|
||
|
default:
|
||
|
encryptVariant(block, dst, src, buf)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// optimized encryption for the ciphers which works in 8-bytes
|
||
|
func encrypt8(block cipher.Block, dst, src, buf []byte) {
|
||
|
tbl := buf[:8]
|
||
|
block.Encrypt(tbl, initialVector)
|
||
|
n := len(src) / 8
|
||
|
base := 0
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
s := src[base:][0:64]
|
||
|
d := dst[base:][0:64]
|
||
|
// 1
|
||
|
xor.BytesSrc1(d[0:8], s[0:8], tbl)
|
||
|
block.Encrypt(tbl, d[0:8])
|
||
|
// 2
|
||
|
xor.BytesSrc1(d[8:16], s[8:16], tbl)
|
||
|
block.Encrypt(tbl, d[8:16])
|
||
|
// 3
|
||
|
xor.BytesSrc1(d[16:24], s[16:24], tbl)
|
||
|
block.Encrypt(tbl, d[16:24])
|
||
|
// 4
|
||
|
xor.BytesSrc1(d[24:32], s[24:32], tbl)
|
||
|
block.Encrypt(tbl, d[24:32])
|
||
|
// 5
|
||
|
xor.BytesSrc1(d[32:40], s[32:40], tbl)
|
||
|
block.Encrypt(tbl, d[32:40])
|
||
|
// 6
|
||
|
xor.BytesSrc1(d[40:48], s[40:48], tbl)
|
||
|
block.Encrypt(tbl, d[40:48])
|
||
|
// 7
|
||
|
xor.BytesSrc1(d[48:56], s[48:56], tbl)
|
||
|
block.Encrypt(tbl, d[48:56])
|
||
|
// 8
|
||
|
xor.BytesSrc1(d[56:64], s[56:64], tbl)
|
||
|
block.Encrypt(tbl, d[56:64])
|
||
|
base += 64
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// optimized encryption for the ciphers which works in 16-bytes
|
||
|
func encrypt16(block cipher.Block, dst, src, buf []byte) {
|
||
|
tbl := buf[:16]
|
||
|
block.Encrypt(tbl, initialVector)
|
||
|
n := len(src) / 16
|
||
|
base := 0
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
s := src[base:][0:128]
|
||
|
d := dst[base:][0:128]
|
||
|
// 1
|
||
|
xor.BytesSrc1(d[0:16], s[0:16], tbl)
|
||
|
block.Encrypt(tbl, d[0:16])
|
||
|
// 2
|
||
|
xor.BytesSrc1(d[16:32], s[16:32], tbl)
|
||
|
block.Encrypt(tbl, d[16:32])
|
||
|
// 3
|
||
|
xor.BytesSrc1(d[32:48], s[32:48], tbl)
|
||
|
block.Encrypt(tbl, d[32:48])
|
||
|
// 4
|
||
|
xor.BytesSrc1(d[48:64], s[48:64], tbl)
|
||
|
block.Encrypt(tbl, d[48:64])
|
||
|
// 5
|
||
|
xor.BytesSrc1(d[64:80], s[64:80], tbl)
|
||
|
block.Encrypt(tbl, d[64:80])
|
||
|
// 6
|
||
|
xor.BytesSrc1(d[80:96], s[80:96], tbl)
|
||
|
block.Encrypt(tbl, d[80:96])
|
||
|
// 7
|
||
|
xor.BytesSrc1(d[96:112], s[96:112], tbl)
|
||
|
block.Encrypt(tbl, d[96:112])
|
||
|
// 8
|
||
|
xor.BytesSrc1(d[112:128], s[112:128], tbl)
|
||
|
block.Encrypt(tbl, d[112:128])
|
||
|
base += 128
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func encryptVariant(block cipher.Block, dst, src, buf []byte) {
|
||
|
blocksize := block.BlockSize()
|
||
|
tbl := buf[:blocksize]
|
||
|
block.Encrypt(tbl, initialVector)
|
||
|
n := len(src) / blocksize
|
||
|
base := 0
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
// 1
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 2
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 3
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 4
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 5
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 6
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 7
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
|
||
|
// 8
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
block.Encrypt(tbl, dst[base:])
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// decryption
|
||
|
func decrypt(block cipher.Block, dst, src, buf []byte) {
|
||
|
switch block.BlockSize() {
|
||
|
case 8:
|
||
|
decrypt8(block, dst, src, buf)
|
||
|
case 16:
|
||
|
decrypt16(block, dst, src, buf)
|
||
|
default:
|
||
|
decryptVariant(block, dst, src, buf)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func decrypt8(block cipher.Block, dst, src, buf []byte) {
|
||
|
tbl := buf[0:8]
|
||
|
next := buf[8:16]
|
||
|
block.Encrypt(tbl, initialVector)
|
||
|
n := len(src) / 8
|
||
|
base := 0
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
s := src[base:][0:64]
|
||
|
d := dst[base:][0:64]
|
||
|
// 1
|
||
|
block.Encrypt(next, s[0:8])
|
||
|
xor.BytesSrc1(d[0:8], s[0:8], tbl)
|
||
|
// 2
|
||
|
block.Encrypt(tbl, s[8:16])
|
||
|
xor.BytesSrc1(d[8:16], s[8:16], next)
|
||
|
// 3
|
||
|
block.Encrypt(next, s[16:24])
|
||
|
xor.BytesSrc1(d[16:24], s[16:24], tbl)
|
||
|
// 4
|
||
|
block.Encrypt(tbl, s[24:32])
|
||
|
xor.BytesSrc1(d[24:32], s[24:32], next)
|
||
|
// 5
|
||
|
block.Encrypt(next, s[32:40])
|
||
|
xor.BytesSrc1(d[32:40], s[32:40], tbl)
|
||
|
// 6
|
||
|
block.Encrypt(tbl, s[40:48])
|
||
|
xor.BytesSrc1(d[40:48], s[40:48], next)
|
||
|
// 7
|
||
|
block.Encrypt(next, s[48:56])
|
||
|
xor.BytesSrc1(d[48:56], s[48:56], tbl)
|
||
|
// 8
|
||
|
block.Encrypt(tbl, s[56:64])
|
||
|
xor.BytesSrc1(d[56:64], s[56:64], next)
|
||
|
base += 64
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 8
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func decrypt16(block cipher.Block, dst, src, buf []byte) {
|
||
|
tbl := buf[0:16]
|
||
|
next := buf[16:32]
|
||
|
block.Encrypt(tbl, initialVector)
|
||
|
n := len(src) / 16
|
||
|
base := 0
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
s := src[base:][0:128]
|
||
|
d := dst[base:][0:128]
|
||
|
// 1
|
||
|
block.Encrypt(next, s[0:16])
|
||
|
xor.BytesSrc1(d[0:16], s[0:16], tbl)
|
||
|
// 2
|
||
|
block.Encrypt(tbl, s[16:32])
|
||
|
xor.BytesSrc1(d[16:32], s[16:32], next)
|
||
|
// 3
|
||
|
block.Encrypt(next, s[32:48])
|
||
|
xor.BytesSrc1(d[32:48], s[32:48], tbl)
|
||
|
// 4
|
||
|
block.Encrypt(tbl, s[48:64])
|
||
|
xor.BytesSrc1(d[48:64], s[48:64], next)
|
||
|
// 5
|
||
|
block.Encrypt(next, s[64:80])
|
||
|
xor.BytesSrc1(d[64:80], s[64:80], tbl)
|
||
|
// 6
|
||
|
block.Encrypt(tbl, s[80:96])
|
||
|
xor.BytesSrc1(d[80:96], s[80:96], next)
|
||
|
// 7
|
||
|
block.Encrypt(next, s[96:112])
|
||
|
xor.BytesSrc1(d[96:112], s[96:112], tbl)
|
||
|
// 8
|
||
|
block.Encrypt(tbl, s[112:128])
|
||
|
xor.BytesSrc1(d[112:128], s[112:128], next)
|
||
|
base += 128
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += 16
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func decryptVariant(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
|
||
|
repeat := n / 8
|
||
|
left := n % 8
|
||
|
for i := 0; i < repeat; i++ {
|
||
|
// 1
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
base += blocksize
|
||
|
|
||
|
// 2
|
||
|
block.Encrypt(tbl, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], next)
|
||
|
base += blocksize
|
||
|
|
||
|
// 3
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
base += blocksize
|
||
|
|
||
|
// 4
|
||
|
block.Encrypt(tbl, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], next)
|
||
|
base += blocksize
|
||
|
|
||
|
// 5
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
base += blocksize
|
||
|
|
||
|
// 6
|
||
|
block.Encrypt(tbl, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], next)
|
||
|
base += blocksize
|
||
|
|
||
|
// 7
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
base += blocksize
|
||
|
|
||
|
// 8
|
||
|
block.Encrypt(tbl, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], next)
|
||
|
base += blocksize
|
||
|
}
|
||
|
|
||
|
switch left {
|
||
|
case 7:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 6:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 5:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 4:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 3:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 2:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 1:
|
||
|
block.Encrypt(next, src[base:])
|
||
|
xor.BytesSrc1(dst[base:], src[base:], tbl)
|
||
|
tbl, next = next, tbl
|
||
|
base += blocksize
|
||
|
fallthrough
|
||
|
case 0:
|
||
|
xor.BytesSrc0(dst[base:], src[base:], tbl)
|
||
|
}
|
||
|
}
|