package crypto import ( "crypto/rc4" "encoding/binary" ) type Ciphers struct { client *rc4.Cipher // For decryption (client->server) server *rc4.Cipher // For encryption (server->client) } // NewCiphers returns a new pair of ciphers based on the given key func NewCiphers(key int64) (*Ciphers, error) { // Encryption only when key > 0 if key <= 0 { return &Ciphers{}, nil } // key (little-endian bytes) keyBytes := make([]byte, 8) binary.LittleEndian.PutUint64(keyBytes, uint64(key)) // ~key (little-endian bytes) notKeyBytes := make([]byte, 8) binary.LittleEndian.PutUint64(notKeyBytes, uint64(^key)) clientCipher, err := rc4.NewCipher(notKeyBytes) if err != nil { return nil, err } serverCipher, err := rc4.NewCipher(keyBytes) if err != nil { return nil, err } // Burn first 20 bytes on both streams drop := make([]byte, 20) clientCipher.XORKeyStream(drop, drop) serverCipher.XORKeyStream(drop, drop) return &Ciphers{client: clientCipher, server: serverCipher}, nil } // Decrypt decrypts data received from the client func (c *Ciphers) Decrypt(data []byte) { if c.client != nil { c.client.XORKeyStream(data, data) } } // Encrypt encrypts data to be sent to the client func (c *Ciphers) Encrypt(data []byte) { if c.server != nil { c.server.XORKeyStream(data, data) } } // IsEncrypted returns true if encryption is active func (c *Ciphers) IsEncrypted() bool { return c != nil && c.server != nil }