diff options
| author | Russ Cox <rsc@golang.org> | 2012-01-25 15:31:12 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2012-01-25 15:31:12 -0500 |
| commit | 470549d5029af744f2f91c2c66a10efc5bc871f8 (patch) | |
| tree | 3c25ee1ef3ee3355419b275ecec84cf848771b7e /ssh/cipher.go | |
| parent | f61fbb80d2fc0f581f66365e8907f07a4d7506b0 (diff) | |
| download | go-x-crypto-470549d5029af744f2f91c2c66a10efc5bc871f8.tar.xz | |
go.crypto: initial code
Manual edits to README.
Moved from main Go repository, deleted Makefiles, ran gofix -r go1rename.
Tested with: go test code.google.com/p/go.crypto/...
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5564059
Diffstat (limited to 'ssh/cipher.go')
| -rw-r--r-- | ssh/cipher.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/ssh/cipher.go b/ssh/cipher.go new file mode 100644 index 0000000..d91929a --- /dev/null +++ b/ssh/cipher.go @@ -0,0 +1,88 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssh + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rc4" +) + +// streamDump is used to dump the initial keystream for stream ciphers. It is a +// a write-only buffer, and not intended for reading so do not require a mutex. +var streamDump [512]byte + +// noneCipher implements cipher.Stream and provides no encryption. It is used +// by the transport before the first key-exchange. +type noneCipher struct{} + +func (c noneCipher) XORKeyStream(dst, src []byte) { + copy(dst, src) +} + +func newAESCTR(key, iv []byte) (cipher.Stream, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewCTR(c, iv), nil +} + +func newRC4(key, iv []byte) (cipher.Stream, error) { + return rc4.NewCipher(key) +} + +type cipherMode struct { + keySize int + ivSize int + skip int + createFn func(key, iv []byte) (cipher.Stream, error) +} + +func (c *cipherMode) createCipher(key, iv []byte) (cipher.Stream, error) { + if len(key) < c.keySize { + panic("ssh: key length too small for cipher") + } + if len(iv) < c.ivSize { + panic("ssh: iv too small for cipher") + } + + stream, err := c.createFn(key[:c.keySize], iv[:c.ivSize]) + if err != nil { + return nil, err + } + + for remainingToDump := c.skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + return stream, nil +} + +// Specifies a default set of ciphers and a preference order. This is based on +// OpenSSH's default client preference order, minus algorithms that are not +// implemented. +var DefaultCipherOrder = []string{ + "aes128-ctr", "aes192-ctr", "aes256-ctr", + "arcfour256", "arcfour128", +} + +var cipherModes = map[string]*cipherMode{ + // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms + // are defined in the order specified in the RFC. + "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, + "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, + "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, + + // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. + // They are defined in the order specified in the RFC. + "arcfour128": {16, 0, 1536, newRC4}, + "arcfour256": {32, 0, 1536, newRC4}, +} |
