Commit 405ca104 by Ian Lance Taylor

libgo: Update to current Go library.

From-SVN: r172106
parent a751005d
342e3b11f21a f618e5e0991d
The first line of this file holds the Mercurial revision number of the The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -177,10 +177,10 @@ toolexeclibgocryptodir = $(toolexeclibgodir)/crypto ...@@ -177,10 +177,10 @@ toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \ toolexeclibgocrypto_DATA = \
crypto/aes.gox \ crypto/aes.gox \
crypto/block.gox \
crypto/blowfish.gox \ crypto/blowfish.gox \
crypto/cast5.gox \ crypto/cast5.gox \
crypto/cipher.gox \ crypto/cipher.gox \
crypto/des.gox \
crypto/dsa.gox \ crypto/dsa.gox \
crypto/ecdsa.gox \ crypto/ecdsa.gox \
crypto/elliptic.gox \ crypto/elliptic.gox \
...@@ -727,9 +727,12 @@ go_os_files = \ ...@@ -727,9 +727,12 @@ go_os_files = \
go/os/env.go \ go/os/env.go \
go/os/env_unix.go \ go/os/env_unix.go \
go/os/error.go \ go/os/error.go \
go/os/error_posix.go \
go/os/exec.go \ go/os/exec.go \
go/os/exec_posix.go \
go/os/exec_unix.go \ go/os/exec_unix.go \
go/os/file.go \ go/os/file.go \
go/os/file_posix.go \
go/os/file_unix.go \ go/os/file_unix.go \
go/os/getwd.go \ go/os/getwd.go \
go/os/path.go \ go/os/path.go \
...@@ -932,16 +935,6 @@ go_crypto_aes_files = \ ...@@ -932,16 +935,6 @@ go_crypto_aes_files = \
go/crypto/aes/block.go \ go/crypto/aes/block.go \
go/crypto/aes/cipher.go \ go/crypto/aes/cipher.go \
go/crypto/aes/const.go go/crypto/aes/const.go
go_crypto_block_files = \
go/crypto/block/cbc.go \
go/crypto/block/cfb.go \
go/crypto/block/cmac.go \
go/crypto/block/cipher.go \
go/crypto/block/ctr.go \
go/crypto/block/eax.go \
go/crypto/block/ecb.go \
go/crypto/block/ofb.go \
go/crypto/block/xor.go
go_crypto_blowfish_files = \ go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \ go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \ go/crypto/blowfish/const.go \
...@@ -956,6 +949,10 @@ go_crypto_cipher_files = \ ...@@ -956,6 +949,10 @@ go_crypto_cipher_files = \
go/crypto/cipher/io.go \ go/crypto/cipher/io.go \
go/crypto/cipher/ocfb.go \ go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go go/crypto/cipher/ofb.go
go_crypto_des_files = \
go/crypto/des/block.go \
go/crypto/des/cipher.go \
go/crypto/des/const.go
go_crypto_dsa_files = \ go_crypto_dsa_files = \
go/crypto/dsa/dsa.go go/crypto/dsa/dsa.go
go_crypto_ecdsa_files = \ go_crypto_ecdsa_files = \
...@@ -1428,10 +1425,10 @@ libgo_go_objs = \ ...@@ -1428,10 +1425,10 @@ libgo_go_objs = \
container/ring.lo \ container/ring.lo \
container/vector.lo \ container/vector.lo \
crypto/aes.lo \ crypto/aes.lo \
crypto/block.lo \
crypto/blowfish.lo \ crypto/blowfish.lo \
crypto/cast5.lo \ crypto/cast5.lo \
crypto/cipher.lo \ crypto/cipher.lo \
crypto/des.lo \
crypto/dsa.lo \ crypto/dsa.lo \
crypto/ecdsa.lo \ crypto/ecdsa.lo \
crypto/elliptic.lo \ crypto/elliptic.lo \
...@@ -2026,13 +2023,6 @@ crypto/aes/check: $(CHECK_DEPS) ...@@ -2026,13 +2023,6 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: crypto/aes/check .PHONY: crypto/aes/check
crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
$(BUILDPACKAGE)
crypto/block/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/block
@$(CHECK)
.PHONY: crypto/block/check
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS) crypto/blowfish/check: $(CHECK_DEPS)
...@@ -2054,6 +2044,13 @@ crypto/cipher/check: $(CHECK_DEPS) ...@@ -2054,6 +2044,13 @@ crypto/cipher/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: crypto/cipher/check .PHONY: crypto/cipher/check
crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
$(BUILDPACKAGE)
crypto/des/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/des
@$(CHECK)
.PHONY: crypto/des/check
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS) crypto/dsa/check: $(CHECK_DEPS)
...@@ -2139,7 +2136,8 @@ crypto/ripemd160/check: $(CHECK_DEPS) ...@@ -2139,7 +2136,8 @@ crypto/ripemd160/check: $(CHECK_DEPS)
.PHONY: crypto/ripemd160/check .PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \ crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
sync.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS) crypto/rsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rsa @$(MKDIR_P) crypto/rsa
...@@ -2475,8 +2473,8 @@ http/cgi/check: $(CHECK_DEPS) ...@@ -2475,8 +2473,8 @@ http/cgi/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: http/cgi/check .PHONY: http/cgi/check
http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \ http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
net.gox os.gox crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
http/httptest/check: $(CHECK_DEPS) http/httptest/check: $(CHECK_DEPS)
@$(MKDIR_P) http/httptest @$(MKDIR_P) http/httptest
...@@ -2767,14 +2765,14 @@ container/vector.gox: container/vector.lo ...@@ -2767,14 +2765,14 @@ container/vector.gox: container/vector.lo
crypto/aes.gox: crypto/aes.lo crypto/aes.gox: crypto/aes.lo
$(BUILDGOX) $(BUILDGOX)
crypto/block.gox: crypto/block.lo
$(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX) $(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX) $(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX) $(BUILDGOX)
crypto/des.gox: crypto/des.lo
$(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX) $(BUILDGOX)
crypto/ecdsa.gox: crypto/ecdsa.lo crypto/ecdsa.gox: crypto/ecdsa.lo
...@@ -3002,10 +3000,10 @@ TEST_PACKAGES = \ ...@@ -3002,10 +3000,10 @@ TEST_PACKAGES = \
container/ring/check \ container/ring/check \
container/vector/check \ container/vector/check \
crypto/aes/check \ crypto/aes/check \
crypto/block/check \
crypto/blowfish/check \ crypto/blowfish/check \
crypto/cast5/check \ crypto/cast5/check \
crypto/cipher/check \ crypto/cipher/check \
crypto/des/check \
crypto/dsa/check \ crypto/dsa/check \
crypto/ecdsa/check \ crypto/ecdsa/check \
crypto/elliptic/check \ crypto/elliptic/check \
......
...@@ -140,31 +140,30 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \ ...@@ -140,31 +140,30 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
archive/zip.lo compress/bzip2.lo compress/flate.lo \ archive/zip.lo compress/bzip2.lo compress/flate.lo \
compress/gzip.lo compress/lzw.lo compress/zlib.lo \ compress/gzip.lo compress/lzw.lo compress/zlib.lo \
container/heap.lo container/list.lo container/ring.lo \ container/heap.lo container/list.lo container/ring.lo \
container/vector.lo crypto/aes.lo crypto/block.lo \ container/vector.lo crypto/aes.lo crypto/blowfish.lo \
crypto/blowfish.lo crypto/cast5.lo crypto/cipher.lo \ crypto/cast5.lo crypto/cipher.lo crypto/des.lo crypto/dsa.lo \
crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \ crypto/ecdsa.lo crypto/elliptic.lo crypto/hmac.lo \
crypto/hmac.lo crypto/md4.lo crypto/md5.lo crypto/ocsp.lo \ crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/openpgp.lo \
crypto/openpgp.lo crypto/rand.lo crypto/rc4.lo \ crypto/rand.lo crypto/rc4.lo crypto/ripemd160.lo crypto/rsa.lo \
crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \ crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \
crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \ crypto/subtle.lo crypto/tls.lo crypto/twofish.lo \
crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \ crypto/x509.lo crypto/xtea.lo crypto/openpgp/armor.lo \
crypto/openpgp/armor.lo crypto/openpgp/error.lo \ crypto/openpgp/error.lo crypto/openpgp/packet.lo \
crypto/openpgp/packet.lo crypto/openpgp/s2k.lo debug/dwarf.lo \ crypto/openpgp/s2k.lo debug/dwarf.lo debug/elf.lo \
debug/elf.lo debug/gosym.lo debug/macho.lo debug/pe.lo \ debug/gosym.lo debug/macho.lo debug/pe.lo debug/proc.lo \
debug/proc.lo encoding/ascii85.lo encoding/base32.lo \ encoding/ascii85.lo encoding/base32.lo encoding/base64.lo \
encoding/base64.lo encoding/binary.lo encoding/git85.lo \ encoding/binary.lo encoding/git85.lo encoding/hex.lo \
encoding/hex.lo encoding/line.lo encoding/pem.lo \ encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \
exp/datafmt.lo exp/draw.lo exp/eval.lo go/ast.lo go/doc.lo \ exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \
go/parser.lo go/printer.lo go/scanner.lo go/token.lo \ go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \
go/typechecker.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \ hash/crc32.lo hash/crc64.lo hash/fnv.lo http/cgi.lo \
hash/fnv.lo http/cgi.lo http/httptest.lo http/pprof.lo \ http/httptest.lo http/pprof.lo image/jpeg.lo image/png.lo \
image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \ index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
mime/multipart.lo net/dict.lo net/textproto.lo \ net/dict.lo net/textproto.lo $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) os/signal.lo path/filepath.lo \ os/signal.lo path/filepath.lo rpc/jsonrpc.lo runtime/debug.lo \
rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \ runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \ syscalls/syscall.lo syscalls/errno.lo testing/testing.lo \
syscalls/errno.lo testing/testing.lo testing/iotest.lo \ testing/iotest.lo testing/quick.lo testing/script.lo
testing/quick.lo testing/script.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
...@@ -624,10 +623,10 @@ toolexeclibgocontainer_DATA = \ ...@@ -624,10 +623,10 @@ toolexeclibgocontainer_DATA = \
toolexeclibgocryptodir = $(toolexeclibgodir)/crypto toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \ toolexeclibgocrypto_DATA = \
crypto/aes.gox \ crypto/aes.gox \
crypto/block.gox \
crypto/blowfish.gox \ crypto/blowfish.gox \
crypto/cast5.gox \ crypto/cast5.gox \
crypto/cipher.gox \ crypto/cipher.gox \
crypto/des.gox \
crypto/dsa.gox \ crypto/dsa.gox \
crypto/ecdsa.gox \ crypto/ecdsa.gox \
crypto/elliptic.gox \ crypto/elliptic.gox \
...@@ -1087,9 +1086,12 @@ go_os_files = \ ...@@ -1087,9 +1086,12 @@ go_os_files = \
go/os/env.go \ go/os/env.go \
go/os/env_unix.go \ go/os/env_unix.go \
go/os/error.go \ go/os/error.go \
go/os/error_posix.go \
go/os/exec.go \ go/os/exec.go \
go/os/exec_posix.go \
go/os/exec_unix.go \ go/os/exec_unix.go \
go/os/file.go \ go/os/file.go \
go/os/file_posix.go \
go/os/file_unix.go \ go/os/file_unix.go \
go/os/getwd.go \ go/os/getwd.go \
go/os/path.go \ go/os/path.go \
...@@ -1279,17 +1281,6 @@ go_crypto_aes_files = \ ...@@ -1279,17 +1281,6 @@ go_crypto_aes_files = \
go/crypto/aes/cipher.go \ go/crypto/aes/cipher.go \
go/crypto/aes/const.go go/crypto/aes/const.go
go_crypto_block_files = \
go/crypto/block/cbc.go \
go/crypto/block/cfb.go \
go/crypto/block/cmac.go \
go/crypto/block/cipher.go \
go/crypto/block/ctr.go \
go/crypto/block/eax.go \
go/crypto/block/ecb.go \
go/crypto/block/ofb.go \
go/crypto/block/xor.go
go_crypto_blowfish_files = \ go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \ go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \ go/crypto/blowfish/const.go \
...@@ -1307,6 +1298,11 @@ go_crypto_cipher_files = \ ...@@ -1307,6 +1298,11 @@ go_crypto_cipher_files = \
go/crypto/cipher/ocfb.go \ go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go go/crypto/cipher/ofb.go
go_crypto_des_files = \
go/crypto/des/block.go \
go/crypto/des/cipher.go \
go/crypto/des/const.go
go_crypto_dsa_files = \ go_crypto_dsa_files = \
go/crypto/dsa/dsa.go go/crypto/dsa/dsa.go
...@@ -1766,10 +1762,10 @@ libgo_go_objs = \ ...@@ -1766,10 +1762,10 @@ libgo_go_objs = \
container/ring.lo \ container/ring.lo \
container/vector.lo \ container/vector.lo \
crypto/aes.lo \ crypto/aes.lo \
crypto/block.lo \
crypto/blowfish.lo \ crypto/blowfish.lo \
crypto/cast5.lo \ crypto/cast5.lo \
crypto/cipher.lo \ crypto/cipher.lo \
crypto/des.lo \
crypto/dsa.lo \ crypto/dsa.lo \
crypto/ecdsa.lo \ crypto/ecdsa.lo \
crypto/elliptic.lo \ crypto/elliptic.lo \
...@@ -2008,10 +2004,10 @@ TEST_PACKAGES = \ ...@@ -2008,10 +2004,10 @@ TEST_PACKAGES = \
container/ring/check \ container/ring/check \
container/vector/check \ container/vector/check \
crypto/aes/check \ crypto/aes/check \
crypto/block/check \
crypto/blowfish/check \ crypto/blowfish/check \
crypto/cast5/check \ crypto/cast5/check \
crypto/cipher/check \ crypto/cipher/check \
crypto/des/check \
crypto/dsa/check \ crypto/dsa/check \
crypto/ecdsa/check \ crypto/ecdsa/check \
crypto/elliptic/check \ crypto/elliptic/check \
...@@ -4436,13 +4432,6 @@ crypto/aes/check: $(CHECK_DEPS) ...@@ -4436,13 +4432,6 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: crypto/aes/check .PHONY: crypto/aes/check
crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
$(BUILDPACKAGE)
crypto/block/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/block
@$(CHECK)
.PHONY: crypto/block/check
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS) crypto/blowfish/check: $(CHECK_DEPS)
...@@ -4464,6 +4453,13 @@ crypto/cipher/check: $(CHECK_DEPS) ...@@ -4464,6 +4453,13 @@ crypto/cipher/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: crypto/cipher/check .PHONY: crypto/cipher/check
crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
$(BUILDPACKAGE)
crypto/des/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/des
@$(CHECK)
.PHONY: crypto/des/check
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS) crypto/dsa/check: $(CHECK_DEPS)
...@@ -4549,7 +4545,8 @@ crypto/ripemd160/check: $(CHECK_DEPS) ...@@ -4549,7 +4545,8 @@ crypto/ripemd160/check: $(CHECK_DEPS)
.PHONY: crypto/ripemd160/check .PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \ crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
sync.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS) crypto/rsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rsa @$(MKDIR_P) crypto/rsa
...@@ -4885,8 +4882,8 @@ http/cgi/check: $(CHECK_DEPS) ...@@ -4885,8 +4882,8 @@ http/cgi/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: http/cgi/check .PHONY: http/cgi/check
http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \ http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
net.gox os.gox crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
http/httptest/check: $(CHECK_DEPS) http/httptest/check: $(CHECK_DEPS)
@$(MKDIR_P) http/httptest @$(MKDIR_P) http/httptest
...@@ -5172,14 +5169,14 @@ container/vector.gox: container/vector.lo ...@@ -5172,14 +5169,14 @@ container/vector.gox: container/vector.lo
crypto/aes.gox: crypto/aes.lo crypto/aes.gox: crypto/aes.lo
$(BUILDGOX) $(BUILDGOX)
crypto/block.gox: crypto/block.lo
$(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX) $(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX) $(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX) $(BUILDGOX)
crypto/des.gox: crypto/des.lo
$(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX) $(BUILDGOX)
crypto/ecdsa.gox: crypto/ecdsa.lo crypto/ecdsa.gox: crypto/ecdsa.lo
......
...@@ -95,7 +95,7 @@ func (tr *Reader) skipUnread() { ...@@ -95,7 +95,7 @@ func (tr *Reader) skipUnread() {
nr := tr.nb + tr.pad // number of bytes to skip nr := tr.nb + tr.pad // number of bytes to skip
tr.nb, tr.pad = 0, 0 tr.nb, tr.pad = 0, 0
if sr, ok := tr.r.(io.Seeker); ok { if sr, ok := tr.r.(io.Seeker); ok {
if _, err := sr.Seek(nr, 1); err == nil { if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
return return
} }
} }
......
...@@ -113,7 +113,7 @@ var untarTests = []*untarTest{ ...@@ -113,7 +113,7 @@ var untarTests = []*untarTest{
func TestReader(t *testing.T) { func TestReader(t *testing.T) {
testLoop: testLoop:
for i, test := range untarTests { for i, test := range untarTests {
f, err := os.Open(test.file, os.O_RDONLY, 0444) f, err := os.Open(test.file)
if err != nil { if err != nil {
t.Errorf("test %d: Unexpected error: %v", i, err) t.Errorf("test %d: Unexpected error: %v", i, err)
continue continue
...@@ -143,7 +143,7 @@ testLoop: ...@@ -143,7 +143,7 @@ testLoop:
} }
func TestPartialRead(t *testing.T) { func TestPartialRead(t *testing.T) {
f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444) f, err := os.Open("testdata/gnu.tar")
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -181,7 +181,7 @@ func TestPartialRead(t *testing.T) { ...@@ -181,7 +181,7 @@ func TestPartialRead(t *testing.T) {
func TestIncrementalRead(t *testing.T) { func TestIncrementalRead(t *testing.T) {
test := gnuTarTest test := gnuTarTest
f, err := os.Open(test.file, os.O_RDONLY, 0444) f, err := os.Open(test.file)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -235,7 +235,7 @@ func TestIncrementalRead(t *testing.T) { ...@@ -235,7 +235,7 @@ func TestIncrementalRead(t *testing.T) {
func TestNonSeekable(t *testing.T) { func TestNonSeekable(t *testing.T) {
test := gnuTarTest test := gnuTarTest
f, err := os.Open(test.file, os.O_RDONLY, 0444) f, err := os.Open(test.file)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
......
...@@ -49,7 +49,7 @@ func (f *File) hasDataDescriptor() bool { ...@@ -49,7 +49,7 @@ func (f *File) hasDataDescriptor() bool {
// OpenReader will open the Zip file specified by name and return a Reader. // OpenReader will open the Zip file specified by name and return a Reader.
func OpenReader(name string) (*Reader, os.Error) { func OpenReader(name string) (*Reader, os.Error) {
f, err := os.Open(name, os.O_RDONLY, 0644) f, err := os.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -73,7 +73,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) { ...@@ -73,7 +73,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
Comment: end.comment, Comment: end.comment,
} }
rs := io.NewSectionReader(r, 0, size) rs := io.NewSectionReader(r, 0, size)
if _, err = rs.Seek(int64(end.directoryOffset), 0); err != nil { if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
return nil, err return nil, err
} }
buf := bufio.NewReader(rs) buf := bufio.NewReader(rs)
...@@ -94,7 +94,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) { ...@@ -94,7 +94,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
if err = readFileHeader(f, r); err != nil { if err = readFileHeader(f, r); err != nil {
return return
} }
if f.bodyOffset, err = r.Seek(0, 1); err != nil { if f.bodyOffset, err = r.Seek(0, os.SEEK_CUR); err != nil {
return return
} }
} }
......
...@@ -415,38 +415,27 @@ func (b *Writer) Buffered() int { return b.n } ...@@ -415,38 +415,27 @@ func (b *Writer) Buffered() int { return b.n }
// If nn < len(p), it also returns an error explaining // If nn < len(p), it also returns an error explaining
// why the write is short. // why the write is short.
func (b *Writer) Write(p []byte) (nn int, err os.Error) { func (b *Writer) Write(p []byte) (nn int, err os.Error) {
if b.err != nil { for len(p) > b.Available() && b.err == nil {
return 0, b.err var n int
} if b.Buffered() == 0 {
nn = 0
for len(p) > 0 {
n := b.Available()
if n <= 0 {
if b.Flush(); b.err != nil {
break
}
n = b.Available()
}
if b.Buffered() == 0 && len(p) >= len(b.buf) {
// Large write, empty buffer. // Large write, empty buffer.
// Write directly from p to avoid copy. // Write directly from p to avoid copy.
n, b.err = b.wr.Write(p) n, b.err = b.wr.Write(p)
nn += n } else {
p = p[n:] n = copy(b.buf[b.n:], p)
if b.err != nil { b.n += n
break b.Flush()
}
continue
}
if n > len(p) {
n = len(p)
} }
copy(b.buf[b.n:b.n+n], p[0:n])
b.n += n
nn += n nn += n
p = p[n:] p = p[n:]
} }
return nn, b.err if b.err != nil {
return nn, b.err
}
n := copy(b.buf[b.n:], p)
b.n += n
nn += n
return nn, nil
} }
// WriteByte writes a single byte. // WriteByte writes a single byte.
...@@ -496,24 +485,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) { ...@@ -496,24 +485,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
// If the count is less than len(s), it also returns an error explaining // If the count is less than len(s), it also returns an error explaining
// why the write is short. // why the write is short.
func (b *Writer) WriteString(s string) (int, os.Error) { func (b *Writer) WriteString(s string) (int, os.Error) {
if b.err != nil { nn := 0
return 0, b.err for len(s) > b.Available() && b.err == nil {
} n := copy(b.buf[b.n:], s)
// Common case, worth making fast. b.n += n
if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil { nn += n
for i := 0; i < len(s); i++ { // loop over bytes, not runes. s = s[n:]
b.buf[b.n] = s[i] b.Flush()
b.n++
}
return len(s), nil
} }
for i := 0; i < len(s); i++ { // loop over bytes, not runes. if b.err != nil {
b.WriteByte(s[i]) return nn, b.err
if b.err != nil {
return i, b.err
}
} }
return len(s), nil n := copy(b.buf[b.n:], s)
b.n += n
nn += n
return nn, nil
} }
// buffered input and output // buffered input and output
......
...@@ -21,7 +21,7 @@ var filenames = []string{ ...@@ -21,7 +21,7 @@ var filenames = []string{
// the given options yields equivalent bytes to the original file. // the given options yields equivalent bytes to the original file.
func testFile(t *testing.T, fn string, order Order, litWidth int) { func testFile(t *testing.T, fn string, order Order, litWidth int) {
// Read the file, as golden output. // Read the file, as golden output.
golden, err := os.Open(fn, os.O_RDONLY, 0400) golden, err := os.Open(fn)
if err != nil { if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err) t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return return
...@@ -29,7 +29,7 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) { ...@@ -29,7 +29,7 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) {
defer golden.Close() defer golden.Close()
// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end. // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
raw, err := os.Open(fn, os.O_RDONLY, 0400) raw, err := os.Open(fn)
if err != nil { if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err) t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return return
......
...@@ -20,7 +20,7 @@ var filenames = []string{ ...@@ -20,7 +20,7 @@ var filenames = []string{
// yields equivalent bytes to the original file. // yields equivalent bytes to the original file.
func testFileLevel(t *testing.T, fn string, level int) { func testFileLevel(t *testing.T, fn string, level int) {
// Read the file, as golden output. // Read the file, as golden output.
golden, err := os.Open(fn, os.O_RDONLY, 0444) golden, err := os.Open(fn)
if err != nil { if err != nil {
t.Errorf("%s (level=%d): %v", fn, level, err) t.Errorf("%s (level=%d): %v", fn, level, err)
return return
...@@ -28,7 +28,7 @@ func testFileLevel(t *testing.T, fn string, level int) { ...@@ -28,7 +28,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
defer golden.Close() defer golden.Close()
// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end. // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
raw, err := os.Open(fn, os.O_RDONLY, 0444) raw, err := os.Open(fn)
if err != nil { if err != nil {
t.Errorf("%s (level=%d): %v", fn, level, err) t.Errorf("%s (level=%d): %v", fn, level, err)
return return
......
// Copyright 2009 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.
// Cipher block chaining (CBC) mode.
// CBC provides confidentiality by xoring (chaining) each plaintext block
// with the previous ciphertext block before applying the block cipher.
// See NIST SP 800-38A, pp 10-11
package block
import (
"io"
)
type cbcCipher struct {
c Cipher
blockSize int
iv []byte
tmp []byte
}
func newCBC(c Cipher, iv []byte) *cbcCipher {
n := c.BlockSize()
x := new(cbcCipher)
x.c = c
x.blockSize = n
x.iv = dup(iv)
x.tmp = make([]byte, n)
return x
}
func (x *cbcCipher) BlockSize() int { return x.blockSize }
func (x *cbcCipher) Encrypt(dst, src []byte) {
for i := 0; i < x.blockSize; i++ {
x.iv[i] ^= src[i]
}
x.c.Encrypt(x.iv, x.iv)
for i := 0; i < x.blockSize; i++ {
dst[i] = x.iv[i]
}
}
func (x *cbcCipher) Decrypt(dst, src []byte) {
x.c.Decrypt(x.tmp, src)
for i := 0; i < x.blockSize; i++ {
x.tmp[i] ^= x.iv[i]
x.iv[i] = src[i]
dst[i] = x.tmp[i]
}
}
// NewCBCDecrypter returns a reader that reads data from r and decrypts it using c
// in cipher block chaining (CBC) mode with the initialization vector iv.
// The returned Reader does not buffer or read ahead except
// as required by the cipher's block size.
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
return NewECBDecrypter(newCBC(c, iv), r)
}
// NewCBCEncrypter returns a writer that encrypts data using c
// in cipher block chaining (CBC) mode with the initialization vector iv
// and writes the encrypted data to w.
// The returned Writer does no buffering except as required
// by the cipher's block size, so there is no need for a Flush method.
func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer {
return NewECBEncrypter(newCBC(c, iv), w)
}
// Copyright 2009 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.
// Cipher feedback (CFB) mode.
// CFB provides confidentiality by feeding a fraction of
// the previous ciphertext in as the plaintext for the next
// block operation.
// See NIST SP 800-38A, pp 11-13
package block
import (
"io"
)
type cfbCipher struct {
c Cipher
blockSize int // our block size (s/8)
cipherSize int // underlying cipher block size
iv []byte
tmp []byte
}
func newCFB(c Cipher, s int, iv []byte) *cfbCipher {
if s == 0 || s%8 != 0 {
panic("crypto/block: invalid CFB mode")
}
b := c.BlockSize()
x := new(cfbCipher)
x.c = c
x.blockSize = s / 8
x.cipherSize = b
x.iv = dup(iv)
x.tmp = make([]byte, b)
return x
}
func (x *cfbCipher) BlockSize() int { return x.blockSize }
func (x *cfbCipher) Encrypt(dst, src []byte) {
// Encrypt old IV and xor prefix with src to make dst.
x.c.Encrypt(x.tmp, x.iv)
for i := 0; i < x.blockSize; i++ {
dst[i] = src[i] ^ x.tmp[i]
}
// Slide unused IV pieces down and insert dst at end.
for i := 0; i < x.cipherSize-x.blockSize; i++ {
x.iv[i] = x.iv[i+x.blockSize]
}
off := x.cipherSize - x.blockSize
for i := off; i < x.cipherSize; i++ {
x.iv[i] = dst[i-off]
}
}
func (x *cfbCipher) Decrypt(dst, src []byte) {
// Encrypt [sic] old IV and xor prefix with src to make dst.
x.c.Encrypt(x.tmp, x.iv)
for i := 0; i < x.blockSize; i++ {
dst[i] = src[i] ^ x.tmp[i]
}
// Slide unused IV pieces down and insert src at top.
for i := 0; i < x.cipherSize-x.blockSize; i++ {
x.iv[i] = x.iv[i+x.blockSize]
}
off := x.cipherSize - x.blockSize
for i := off; i < x.cipherSize; i++ {
// Reconstruct src = dst ^ x.tmp
// in case we overwrote src (src == dst).
x.iv[i] = dst[i-off] ^ x.tmp[i-off]
}
}
// NewCFBDecrypter returns a reader that reads data from r and decrypts it using c
// in s-bit cipher feedback (CFB) mode with the initialization vector iv.
// The returned Reader does not buffer or read ahead except
// as required by the cipher's block size.
// Modes for s not a multiple of 8 are unimplemented.
func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
return NewECBDecrypter(newCFB(c, s, iv), r)
}
// NewCFBEncrypter returns a writer that encrypts data using c
// in s-bit cipher feedback (CFB) mode with the initialization vector iv
// and writes the encrypted data to w.
// The returned Writer does no buffering except as required
// by the cipher's block size, so there is no need for a Flush method.
// Modes for s not a multiple of 8 are unimplemented.
func NewCFBEncrypter(c Cipher, s int, iv []byte, w io.Writer) io.Writer {
return NewECBEncrypter(newCFB(c, s, iv), w)
}
// Copyright 2009 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.
// CFB AES test vectors.
// See U.S. National Institute of Standards and Technology (NIST)
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 29-52.
package block
import (
"bytes"
"crypto/aes"
"io"
"testing"
)
type cfbTest struct {
name string
s int
key []byte
iv []byte
in []byte
out []byte
}
var cfbAESTests = []cfbTest{
{
"CFB1-AES128",
1,
commonKey128,
commonIV,
[]byte{
0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
},
[]byte{
0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
1<<7 | 0<<6 | 1<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
},
},
{
"CFB1-AES192",
1,
commonKey192,
commonIV,
[]byte{
0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
},
[]byte{
1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
0<<7 | 1<<6 | 0<<5 | 1<<4 | 1<<3 | 0<<2 | 0<<1,
},
},
{
"CFB1-AES256",
1,
commonKey256,
commonIV,
[]byte{
0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
},
[]byte{
1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 0<<1,
0<<7 | 0<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
},
},
{
"CFB8-AES128",
8,
commonKey128,
commonIV,
[]byte{
0x6b,
0xc1,
0xbe,
0xe2,
0x2e,
0x40,
0x9f,
0x96,
0xe9,
0x3d,
0x7e,
0x11,
0x73,
0x93,
0x17,
0x2a,
0xae,
0x2d,
},
[]byte{
0x3b,
0x79,
0x42,
0x4c,
0x9c,
0x0d,
0xd4,
0x36,
0xba,
0xce,
0x9e,
0x0e,
0xd4,
0x58,
0x6a,
0x4f,
0x32,
0xb9,
},
},
{
"CFB8-AES192",
8,
commonKey192,
commonIV,
[]byte{
0x6b,
0xc1,
0xbe,
0xe2,
0x2e,
0x40,
0x9f,
0x96,
0xe9,
0x3d,
0x7e,
0x11,
0x73,
0x93,
0x17,
0x2a,
0xae,
0x2d,
},
[]byte{
0xcd,
0xa2,
0x52,
0x1e,
0xf0,
0xa9,
0x05,
0xca,
0x44,
0xcd,
0x05,
0x7c,
0xbf,
0x0d,
0x47,
0xa0,
0x67,
0x8a,
},
},
{
"CFB8-AES256",
8,
commonKey256,
commonIV,
[]byte{
0x6b,
0xc1,
0xbe,
0xe2,
0x2e,
0x40,
0x9f,
0x96,
0xe9,
0x3d,
0x7e,
0x11,
0x73,
0x93,
0x17,
0x2a,
0xae,
0x2d,
},
[]byte{
0xdc,
0x1f,
0x1a,
0x85,
0x20,
0xa6,
0x4d,
0xb5,
0x5f,
0xcc,
0x8a,
0xc5,
0x54,
0x84,
0x4e,
0x88,
0x97,
0x00,
},
},
{
"CFB128-AES128",
128,
commonKey128,
commonIV,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{
0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6,
},
},
{
"CFB128-AES192",
128,
commonKey192,
commonIV,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{
0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a,
0x2e, 0x1e, 0x8a, 0x1d, 0xd5, 0x9b, 0x88, 0xb1, 0xc8, 0xe6, 0x0f, 0xed, 0x1e, 0xfa, 0xc4, 0xc9,
0xc0, 0x5f, 0x9f, 0x9c, 0xa9, 0x83, 0x4f, 0xa0, 0x42, 0xae, 0x8f, 0xba, 0x58, 0x4b, 0x09, 0xff,
},
},
{
"CFB128-AES256",
128,
commonKey256,
commonIV,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{
0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71,
},
},
}
func TestCFB_AES(t *testing.T) {
for _, tt := range cfbAESTests {
test := tt.name
if tt.s == 1 {
// 1-bit CFB not implemented
continue
}
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
continue
}
var crypt bytes.Buffer
w := NewCFBEncrypter(c, tt.s, tt.iv, &crypt)
var r io.Reader = bytes.NewBuffer(tt.in)
n, err := io.Copy(w, r)
if n != int64(len(tt.in)) || err != nil {
t.Errorf("%s: CFBEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
} else if d := crypt.Bytes(); !same(tt.out, d) {
t.Errorf("%s: CFBEncrypter\nhave %x\nwant %x", test, d, tt.out)
}
var plain bytes.Buffer
r = NewCFBDecrypter(c, tt.s, tt.iv, bytes.NewBuffer(tt.out))
w = &plain
n, err = io.Copy(w, r)
if n != int64(len(tt.out)) || err != nil {
t.Errorf("%s: CFBDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
} else if d := plain.Bytes(); !same(tt.in, d) {
t.Errorf("%s: CFBDecrypter\nhave %x\nwant %x", test, d, tt.in)
}
if t.Failed() {
break
}
}
}
// Copyright 2009 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.
// The block package is deprecated, use cipher instead.
// The block package implements standard block cipher modes
// that can be wrapped around low-level block cipher implementations.
// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
// and NIST Special Publication 800-38A.
package block
// A Cipher represents an implementation of block cipher
// using a given key. It provides the capability to encrypt
// or decrypt individual blocks. The mode implementations
// extend that capability to streams of blocks.
type Cipher interface {
// BlockSize returns the cipher's block size.
BlockSize() int
// Encrypt encrypts the first block in src into dst.
// Src and dst may point at the same memory.
Encrypt(dst, src []byte)
// Decrypt decrypts the first block in src into dst.
// Src and dst may point at the same memory.
Decrypt(dst, src []byte)
}
// Utility routines
func shift1(dst, src []byte) byte {
var b byte
for i := len(src) - 1; i >= 0; i-- {
bb := src[i] >> 7
dst[i] = src[i]<<1 | b
b = bb
}
return b
}
func same(p, q []byte) bool {
if len(p) != len(q) {
return false
}
for i := 0; i < len(p); i++ {
if p[i] != q[i] {
return false
}
}
return true
}
func dup(p []byte) []byte {
q := make([]byte, len(p))
copy(q, p)
return q
}
// Copyright 2009 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.
// CMAC message authentication code, defined in
// NIST Special Publication SP 800-38B.
package block
import (
"hash"
"os"
)
const (
// minimal irreducible polynomial of degree b
r64 = 0x1b
r128 = 0x87
)
type cmac struct {
k1, k2, ci, digest []byte
p int // position in ci
c Cipher
}
// TODO(rsc): Should this return an error instead of panic?
// NewCMAC returns a new instance of a CMAC message authentication code
// digest using the given Cipher.
func NewCMAC(c Cipher) hash.Hash {
var r byte
n := c.BlockSize()
switch n {
case 64 / 8:
r = r64
case 128 / 8:
r = r128
default:
panic("crypto/block: NewCMAC: invalid cipher block size")
}
d := new(cmac)
d.c = c
d.k1 = make([]byte, n)
d.k2 = make([]byte, n)
d.ci = make([]byte, n)
d.digest = make([]byte, n)
// Subkey generation, p. 7
c.Encrypt(d.k1, d.k1)
if shift1(d.k1, d.k1) != 0 {
d.k1[n-1] ^= r
}
if shift1(d.k2, d.k1) != 0 {
d.k2[n-1] ^= r
}
return d
}
// Reset clears the digest state, starting a new digest.
func (d *cmac) Reset() {
for i := range d.ci {
d.ci[i] = 0
}
d.p = 0
}
// Write adds the given data to the digest state.
func (d *cmac) Write(p []byte) (n int, err os.Error) {
// Xor input into ci.
for _, c := range p {
// If ci is full, encrypt and start over.
if d.p >= len(d.ci) {
d.c.Encrypt(d.ci, d.ci)
d.p = 0
}
d.ci[d.p] ^= c
d.p++
}
return len(p), nil
}
// Sum returns the CMAC digest, one cipher block in length,
// of the data written with Write.
func (d *cmac) Sum() []byte {
// Finish last block, mix in key, encrypt.
// Don't edit ci, in case caller wants
// to keep digesting after call to Sum.
k := d.k1
if d.p < len(d.digest) {
k = d.k2
}
for i := 0; i < len(d.ci); i++ {
d.digest[i] = d.ci[i] ^ k[i]
}
if d.p < len(d.digest) {
d.digest[d.p] ^= 0x80
}
d.c.Encrypt(d.digest, d.digest)
return d.digest
}
func (d *cmac) Size() int { return len(d.digest) }
// Copyright 2009 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.
// CMAC test vectors. See NIST SP 800-38B, Appendix D.
package block
import (
"crypto/aes"
"testing"
)
type cmacAESTest struct {
key []byte
in []byte
digest []byte
}
var cmacAESTests = []cmacAESTest{
{
commonKey128,
nil,
[]byte{0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46},
},
{
commonKey128,
[]byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
[]byte{0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c},
},
{
commonKey128,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
},
[]byte{0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27},
},
{
commonKey128,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe},
},
{
commonKey192,
nil,
[]byte{0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67},
},
{
commonKey192,
[]byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
[]byte{0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84},
},
{
commonKey192,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
},
[]byte{0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e},
},
{
commonKey192,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11},
},
{
commonKey256,
nil,
[]byte{0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83},
},
{
commonKey256,
[]byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
[]byte{0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c},
},
{
commonKey256,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
},
[]byte{0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6},
},
{
commonKey256,
[]byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
},
[]byte{0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10},
},
}
func TestCMAC_AES(t *testing.T) {
for i, tt := range cmacAESTests {
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Errorf("test %d: NewCipher: %s", i, err)
continue
}
d := NewCMAC(c)
n, err := d.Write(tt.in)
if err != nil || n != len(tt.in) {
t.Errorf("test %d: Write %d: %d, %s", i, len(tt.in), n, err)
continue
}
sum := d.Sum()
if !same(sum, tt.digest) {
x := d.(*cmac)
t.Errorf("test %d: digest mismatch\n\twant %x\n\thave %x\n\tk1 %x\n\tk2 %x", i, tt.digest, sum, x.k1, x.k2)
continue
}
}
}
// Copyright 2009 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.
// Counter (CTR) mode.
// CTR converts a block cipher into a stream cipher by
// repeatedly encrypting an incrementing counter and
// xoring the resulting stream of data with the input.
// See NIST SP 800-38A, pp 13-15
package block
import (
"io"
)
type ctrStream struct {
c Cipher
ctr []byte
out []byte
}
func newCTRStream(c Cipher, ctr []byte) *ctrStream {
x := new(ctrStream)
x.c = c
x.ctr = dup(ctr)
x.out = make([]byte, len(ctr))
return x
}
func (x *ctrStream) Next() []byte {
// Next block is encryption of counter.
x.c.Encrypt(x.out, x.ctr)
// Increment counter
for i := len(x.ctr) - 1; i >= 0; i-- {
x.ctr[i]++
if x.ctr[i] != 0 {
break
}
}
return x.out
}
// NewCTRReader returns a reader that reads data from r, decrypts (or encrypts)
// it using c in counter (CTR) mode with the initialization vector iv.
// The returned Reader does not buffer and has no block size.
// In CTR mode, encryption and decryption are the same operation:
// a CTR reader applied to an encrypted stream produces a decrypted
// stream and vice versa.
func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
return newXorReader(newCTRStream(c, iv), r)
}
// NewCTRWriter returns a writer that encrypts (or decrypts) data using c
// in counter (CTR) mode with the initialization vector iv
// and writes the encrypted data to w.
// The returned Writer does not buffer and has no block size.
// In CTR mode, encryption and decryption are the same operation:
// a CTR writer applied to an decrypted stream produces an encrypted
// stream and vice versa.
func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
return newXorWriter(newCTRStream(c, iv), w)
}
// Copyright 2009 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.
// EAX mode, not a NIST standard (yet).
// EAX provides encryption and authentication.
// EAX targets the same uses as NIST's CCM mode,
// but EAX adds the ability to run in streaming mode.
// See
// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
// http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
// What those papers call OMAC is now called CMAC.
package block
import (
"fmt"
"hash"
"io"
"os"
)
// An EAXTagError is returned when the message has failed to authenticate,
// because the tag at the end of the message stream (Read) does not match
// the tag computed from the message itself (Computed).
type EAXTagError struct {
Read []byte
Computed []byte
}
func (e *EAXTagError) String() string {
return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed)
}
func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
n := len(iv)
if n != c.BlockSize() {
panic(fmt.Sprintln("crypto/block: EAX: iv length", n, "!=", c.BlockSize()))
}
buf := make([]byte, n) // zeroed
// tag = CMAC(0 + iv) ^ CMAC(1 + hdr) ^ CMAC(2 + data)
cmac = NewCMAC(c)
cmac.Write(buf) // 0
cmac.Write(iv)
sum := cmac.Sum()
ctrIV = dup(sum)
tag = dup(sum[0:tagBytes])
cmac.Reset()
buf[n-1] = 1
cmac.Write(buf) // 1
cmac.Write(hdr)
sum = cmac.Sum()
for i := 0; i < tagBytes; i++ {
tag[i] ^= sum[i]
}
cmac.Reset()
buf[n-1] = 2 // 2
cmac.Write(buf)
return
}
func finishEAX(tag []byte, cmac hash.Hash) {
// Finish CMAC #2 and xor into tag.
sum := cmac.Sum()
for i := range tag {
tag[i] ^= sum[i]
}
}
// Writer adapter. Tees writes into both w and cmac.
// Knows that cmac never returns write errors.
type cmacWriter struct {
w io.Writer
cmac hash.Hash
}
func (cw *cmacWriter) Write(p []byte) (n int, err os.Error) {
n, err = cw.w.Write(p)
cw.cmac.Write(p[0:n])
return
}
// An eaxEncrypter implements the EAX encryption mode.
type eaxEncrypter struct {
ctr io.Writer // CTR encrypter
cw cmacWriter // CTR's output stream
tag []byte
}
// NewEAXEncrypter creates and returns a new EAX encrypter
// using the given cipher c, initialization vector iv, associated data hdr,
// and tag length tagBytes. The encrypter's Write method encrypts
// the data it receives and writes that data to w.
// The encrypter's Close method writes a final authenticating tag to w.
func NewEAXEncrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, w io.Writer) io.WriteCloser {
x := new(eaxEncrypter)
// Create new CTR instance writing to both
// w for encrypted output and cmac for digesting.
x.cw.w = w
var ctrIV []byte
ctrIV, x.tag, x.cw.cmac = setupEAX(c, iv, hdr, tagBytes)
x.ctr = NewCTRWriter(c, ctrIV, &x.cw)
return x
}
func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
return x.ctr.Write(p)
}
func (x *eaxEncrypter) Close() os.Error {
x.ctr = nil // crash if Write is called again
// Write tag.
finishEAX(x.tag, x.cw.cmac)
n, err := x.cw.w.Write(x.tag)
if n != len(x.tag) && err == nil {
err = io.ErrShortWrite
}
return err
}
// Reader adapter. Returns data read from r but hangs
// on to the last len(tag) bytes for itself (returns EOF len(tag)
// bytes early). Also tees all data returned from Read into
// the cmac digest. The "don't return the last t bytes"
// and the "tee into digest" functionality could be separated,
// but the latter half is trivial.
type cmacReader struct {
r io.Reader
cmac hash.Hash
tag []byte
tmp []byte
}
func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
// TODO(rsc): Maybe fall back to simpler code if
// we recognize the underlying r as a ByteBuffer
// or ByteReader. Then we can just take the last piece
// off at the start.
// First, read a tag-sized chunk.
// It's probably not the tag (unless there's no data).
tag := cr.tag
if len(tag) < cap(tag) {
nt := len(tag)
nn, err1 := io.ReadFull(cr.r, tag[nt:cap(tag)])
tag = tag[0 : nt+nn]
cr.tag = tag
if err1 != nil {
return 0, err1
}
}
tagBytes := len(tag)
if len(p) > 4*tagBytes {
// If p is big, try to read directly into p to avoid a copy.
n, err = cr.r.Read(p[tagBytes:])
if n == 0 {
goto out
}
// copy old tag into p
for i := 0; i < tagBytes; i++ {
p[i] = tag[i]
}
// copy new tag out of p
for i := 0; i < tagBytes; i++ {
tag[i] = p[n+i]
}
goto out
}
// Otherwise, read into p and then slide data
n, err = cr.r.Read(p)
if n == 0 {
goto out
}
// copy tag+p into p+tmp and then swap tmp, tag
tmp := cr.tmp
for i := n + tagBytes - 1; i >= 0; i-- {
var c byte
if i < tagBytes {
c = tag[i]
} else {
c = p[i-tagBytes]
}
if i < n {
p[i] = c
} else {
tmp[i] = c
}
}
cr.tmp, cr.tag = tag, tmp
out:
cr.cmac.Write(p[0:n])
return
}
type eaxDecrypter struct {
ctr io.Reader
cr cmacReader
tag []byte
}
// NewEAXDecrypter creates and returns a new EAX decrypter
// using the given cipher c, initialization vector iv, associated data hdr,
// and tag length tagBytes. The encrypter's Read method decrypts and
// returns data read from r. At r's EOF, the encrypter checks the final
// authenticating tag and returns an EAXTagError if the tag is invalid.
// In that case, the message should be discarded.
// Note that the data stream returned from Read cannot be
// assumed to be valid, authenticated data until Read returns
// 0, nil to signal the end of the data.
func NewEAXDecrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, r io.Reader) io.Reader {
x := new(eaxDecrypter)
x.cr.r = r
x.cr.tag = make([]byte, 0, tagBytes)
x.cr.tmp = make([]byte, 0, tagBytes)
var ctrIV []byte
ctrIV, x.tag, x.cr.cmac = setupEAX(c, iv, hdr, tagBytes)
x.ctr = NewCTRReader(c, ctrIV, &x.cr)
return x
}
func (x *eaxDecrypter) checkTag() os.Error {
x.ctr = nil // crash if Read is called again
finishEAX(x.tag, x.cr.cmac)
if !same(x.tag, x.cr.tag) {
e := new(EAXTagError)
e.Computed = dup(x.tag)
e.Read = dup(x.cr.tag)
return e
}
return nil
}
func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
n, err = x.ctr.Read(p)
if n == 0 && err == nil {
err = x.checkTag()
}
return n, err
}
// Copyright 2009 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 block
import (
"bytes"
"crypto/aes"
"fmt"
"io"
"testing"
)
// Test vectors from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
type eaxAESTest struct {
msg []byte
key []byte
nonce []byte
header []byte
cipher []byte
}
var eaxAESTests = []eaxAESTest{
{
[]byte{},
[]byte{0x23, 0x39, 0x52, 0xDE, 0xE4, 0xD5, 0xED, 0x5F, 0x9B, 0x9C, 0x6D, 0x6F, 0xF8, 0x0F, 0xF4, 0x78},
[]byte{0x62, 0xEC, 0x67, 0xF9, 0xC3, 0xA4, 0xA4, 0x07, 0xFC, 0xB2, 0xA8, 0xC4, 0x90, 0x31, 0xA8, 0xB3},
[]byte{0x6B, 0xFB, 0x91, 0x4F, 0xD0, 0x7E, 0xAE, 0x6B},
[]byte{0xE0, 0x37, 0x83, 0x0E, 0x83, 0x89, 0xF2, 0x7B, 0x02, 0x5A, 0x2D, 0x65, 0x27, 0xE7, 0x9D, 0x01},
},
{
[]byte{0xF7, 0xFB},
[]byte{0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4},
[]byte{0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD},
[]byte{0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA},
[]byte{0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, 0x67, 0xE5},
},
{
[]byte{0x1A, 0x47, 0xCB, 0x49, 0x33},
[]byte{0x01, 0xF7, 0x4A, 0xD6, 0x40, 0x77, 0xF2, 0xE7, 0x04, 0xC0, 0xF6, 0x0A, 0xDA, 0x3D, 0xD5, 0x23},
[]byte{0x70, 0xC3, 0xDB, 0x4F, 0x0D, 0x26, 0x36, 0x84, 0x00, 0xA1, 0x0E, 0xD0, 0x5D, 0x2B, 0xFF, 0x5E},
[]byte{0x23, 0x4A, 0x34, 0x63, 0xC1, 0x26, 0x4A, 0xC6},
[]byte{0xD8, 0x51, 0xD5, 0xBA, 0xE0, 0x3A, 0x59, 0xF2, 0x38, 0xA2, 0x3E, 0x39, 0x19, 0x9D, 0xC9, 0x26, 0x66, 0x26, 0xC4, 0x0F, 0x80},
},
{
[]byte{0x48, 0x1C, 0x9E, 0x39, 0xB1},
[]byte{0xD0, 0x7C, 0xF6, 0xCB, 0xB7, 0xF3, 0x13, 0xBD, 0xDE, 0x66, 0xB7, 0x27, 0xAF, 0xD3, 0xC5, 0xE8},
[]byte{0x84, 0x08, 0xDF, 0xFF, 0x3C, 0x1A, 0x2B, 0x12, 0x92, 0xDC, 0x19, 0x9E, 0x46, 0xB7, 0xD6, 0x17},
[]byte{0x33, 0xCC, 0xE2, 0xEA, 0xBF, 0xF5, 0xA7, 0x9D},
[]byte{0x63, 0x2A, 0x9D, 0x13, 0x1A, 0xD4, 0xC1, 0x68, 0xA4, 0x22, 0x5D, 0x8E, 0x1F, 0xF7, 0x55, 0x93, 0x99, 0x74, 0xA7, 0xBE, 0xDE},
},
{
[]byte{0x40, 0xD0, 0xC0, 0x7D, 0xA5, 0xE4},
[]byte{0x35, 0xB6, 0xD0, 0x58, 0x00, 0x05, 0xBB, 0xC1, 0x2B, 0x05, 0x87, 0x12, 0x45, 0x57, 0xD2, 0xC2},
[]byte{0xFD, 0xB6, 0xB0, 0x66, 0x76, 0xEE, 0xDC, 0x5C, 0x61, 0xD7, 0x42, 0x76, 0xE1, 0xF8, 0xE8, 0x16},
[]byte{0xAE, 0xB9, 0x6E, 0xAE, 0xBE, 0x29, 0x70, 0xE9},
[]byte{0x07, 0x1D, 0xFE, 0x16, 0xC6, 0x75, 0xCB, 0x06, 0x77, 0xE5, 0x36, 0xF7, 0x3A, 0xFE, 0x6A, 0x14, 0xB7, 0x4E, 0xE4, 0x98, 0x44, 0xDD},
},
{
[]byte{0x4D, 0xE3, 0xB3, 0x5C, 0x3F, 0xC0, 0x39, 0x24, 0x5B, 0xD1, 0xFB, 0x7D},
[]byte{0xBD, 0x8E, 0x6E, 0x11, 0x47, 0x5E, 0x60, 0xB2, 0x68, 0x78, 0x4C, 0x38, 0xC6, 0x2F, 0xEB, 0x22},
[]byte{0x6E, 0xAC, 0x5C, 0x93, 0x07, 0x2D, 0x8E, 0x85, 0x13, 0xF7, 0x50, 0x93, 0x5E, 0x46, 0xDA, 0x1B},
[]byte{0xD4, 0x48, 0x2D, 0x1C, 0xA7, 0x8D, 0xCE, 0x0F},
[]byte{0x83, 0x5B, 0xB4, 0xF1, 0x5D, 0x74, 0x3E, 0x35, 0x0E, 0x72, 0x84, 0x14, 0xAB, 0xB8, 0x64, 0x4F, 0xD6, 0xCC, 0xB8, 0x69, 0x47, 0xC5, 0xE1, 0x05, 0x90, 0x21, 0x0A, 0x4F},
},
{
[]byte{0x8B, 0x0A, 0x79, 0x30, 0x6C, 0x9C, 0xE7, 0xED, 0x99, 0xDA, 0xE4, 0xF8, 0x7F, 0x8D, 0xD6, 0x16, 0x36},
[]byte{0x7C, 0x77, 0xD6, 0xE8, 0x13, 0xBE, 0xD5, 0xAC, 0x98, 0xBA, 0xA4, 0x17, 0x47, 0x7A, 0x2E, 0x7D},
[]byte{0x1A, 0x8C, 0x98, 0xDC, 0xD7, 0x3D, 0x38, 0x39, 0x3B, 0x2B, 0xF1, 0x56, 0x9D, 0xEE, 0xFC, 0x19},
[]byte{0x65, 0xD2, 0x01, 0x79, 0x90, 0xD6, 0x25, 0x28},
[]byte{0x02, 0x08, 0x3E, 0x39, 0x79, 0xDA, 0x01, 0x48, 0x12, 0xF5, 0x9F, 0x11, 0xD5, 0x26, 0x30, 0xDA, 0x30, 0x13, 0x73, 0x27, 0xD1, 0x06, 0x49, 0xB0, 0xAA, 0x6E, 0x1C, 0x18, 0x1D, 0xB6, 0x17, 0xD7, 0xF2},
},
{
[]byte{0x1B, 0xDA, 0x12, 0x2B, 0xCE, 0x8A, 0x8D, 0xBA, 0xF1, 0x87, 0x7D, 0x96, 0x2B, 0x85, 0x92, 0xDD, 0x2D, 0x56},
[]byte{0x5F, 0xFF, 0x20, 0xCA, 0xFA, 0xB1, 0x19, 0xCA, 0x2F, 0xC7, 0x35, 0x49, 0xE2, 0x0F, 0x5B, 0x0D},
[]byte{0xDD, 0xE5, 0x9B, 0x97, 0xD7, 0x22, 0x15, 0x6D, 0x4D, 0x9A, 0xFF, 0x2B, 0xC7, 0x55, 0x98, 0x26},
[]byte{0x54, 0xB9, 0xF0, 0x4E, 0x6A, 0x09, 0x18, 0x9A},
[]byte{0x2E, 0xC4, 0x7B, 0x2C, 0x49, 0x54, 0xA4, 0x89, 0xAF, 0xC7, 0xBA, 0x48, 0x97, 0xED, 0xCD, 0xAE, 0x8C, 0xC3, 0x3B, 0x60, 0x45, 0x05, 0x99, 0xBD, 0x02, 0xC9, 0x63, 0x82, 0x90, 0x2A, 0xEF, 0x7F, 0x83, 0x2A},
},
{
[]byte{0x6C, 0xF3, 0x67, 0x20, 0x87, 0x2B, 0x85, 0x13, 0xF6, 0xEA, 0xB1, 0xA8, 0xA4, 0x44, 0x38, 0xD5, 0xEF, 0x11},
[]byte{0xA4, 0xA4, 0x78, 0x2B, 0xCF, 0xFD, 0x3E, 0xC5, 0xE7, 0xEF, 0x6D, 0x8C, 0x34, 0xA5, 0x61, 0x23},
[]byte{0xB7, 0x81, 0xFC, 0xF2, 0xF7, 0x5F, 0xA5, 0xA8, 0xDE, 0x97, 0xA9, 0xCA, 0x48, 0xE5, 0x22, 0xEC},
[]byte{0x89, 0x9A, 0x17, 0x58, 0x97, 0x56, 0x1D, 0x7E},
[]byte{0x0D, 0xE1, 0x8F, 0xD0, 0xFD, 0xD9, 0x1E, 0x7A, 0xF1, 0x9F, 0x1D, 0x8E, 0xE8, 0x73, 0x39, 0x38, 0xB1, 0xE8, 0xE7, 0xF6, 0xD2, 0x23, 0x16, 0x18, 0x10, 0x2F, 0xDB, 0x7F, 0xE5, 0x5F, 0xF1, 0x99, 0x17, 0x00},
},
{
[]byte{0xCA, 0x40, 0xD7, 0x44, 0x6E, 0x54, 0x5F, 0xFA, 0xED, 0x3B, 0xD1, 0x2A, 0x74, 0x0A, 0x65, 0x9F, 0xFB, 0xBB, 0x3C, 0xEA, 0xB7},
[]byte{0x83, 0x95, 0xFC, 0xF1, 0xE9, 0x5B, 0xEB, 0xD6, 0x97, 0xBD, 0x01, 0x0B, 0xC7, 0x66, 0xAA, 0xC3},
[]byte{0x22, 0xE7, 0xAD, 0xD9, 0x3C, 0xFC, 0x63, 0x93, 0xC5, 0x7E, 0xC0, 0xB3, 0xC1, 0x7D, 0x6B, 0x44},
[]byte{0x12, 0x67, 0x35, 0xFC, 0xC3, 0x20, 0xD2, 0x5A},
[]byte{0xCB, 0x89, 0x20, 0xF8, 0x7A, 0x6C, 0x75, 0xCF, 0xF3, 0x96, 0x27, 0xB5, 0x6E, 0x3E, 0xD1, 0x97, 0xC5, 0x52, 0xD2, 0x95, 0xA7, 0xCF, 0xC4, 0x6A, 0xFC, 0x25, 0x3B, 0x46, 0x52, 0xB1, 0xAF, 0x37, 0x95, 0xB1, 0x24, 0xAB, 0x6E},
},
}
func TestEAXEncrypt_AES(t *testing.T) {
b := new(bytes.Buffer)
for i, tt := range eaxAESTests {
test := fmt.Sprintf("test %d", i)
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
}
b.Reset()
enc := NewEAXEncrypter(c, tt.nonce, tt.header, 16, b)
n, err := io.Copy(enc, bytes.NewBuffer(tt.msg))
if n != int64(len(tt.msg)) || err != nil {
t.Fatalf("%s: io.Copy into encrypter: %d, %s", test, n, err)
}
err = enc.Close()
if err != nil {
t.Fatalf("%s: enc.Close: %s", test, err)
}
if d := b.Bytes(); !same(d, tt.cipher) {
t.Fatalf("%s: got %x want %x", test, d, tt.cipher)
}
}
}
func TestEAXDecrypt_AES(t *testing.T) {
b := new(bytes.Buffer)
for i, tt := range eaxAESTests {
test := fmt.Sprintf("test %d", i)
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
}
b.Reset()
dec := NewEAXDecrypter(c, tt.nonce, tt.header, 16, bytes.NewBuffer(tt.cipher))
n, err := io.Copy(b, dec)
if n != int64(len(tt.msg)) || err != nil {
t.Fatalf("%s: io.Copy into decrypter: %d, %s", test, n, err)
}
if d := b.Bytes(); !same(d, tt.msg) {
t.Fatalf("%s: got %x want %x", test, d, tt.msg)
}
}
}
// Copyright 2009 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.
// Electronic codebook (ECB) mode.
// ECB is a fancy name for ``encrypt and decrypt each block separately.''
// It's a pretty bad thing to do for any large amount of data (more than one block),
// because the individual blocks can still be identified, duplicated, and reordered.
// The ECB implementation exists mainly to provide buffering for
// the other modes, which wrap it by providing modified Ciphers.
// See NIST SP 800-38A, pp 9-10
package block
import (
"io"
"os"
"strconv"
)
type ecbDecrypter struct {
c Cipher
r io.Reader
blockSize int // block size
// Buffered data.
// The buffer buf is used as storage for both
// plain or crypt; at least one of those is nil at any given time.
buf []byte
plain []byte // plain text waiting to be read
crypt []byte // ciphertext waiting to be decrypted
}
// Read into x.crypt until it has a full block or EOF or an error happens.
func (x *ecbDecrypter) fillCrypt() os.Error {
var err os.Error
for len(x.crypt) < x.blockSize {
off := len(x.crypt)
var m int
m, err = x.r.Read(x.crypt[off:x.blockSize])
x.crypt = x.crypt[0 : off+m]
if m == 0 {
break
}
// If an error happened but we got enough
// data to do some decryption, we can decrypt
// first and report the error (with some data) later.
// But if we don't have enough to decrypt,
// have to stop now.
if err != nil && len(x.crypt) < x.blockSize {
break
}
}
return err
}
// Read from plain text buffer into p.
func (x *ecbDecrypter) readPlain(p []byte) int {
n := len(x.plain)
if n > len(p) {
n = len(p)
}
for i := 0; i < n; i++ {
p[i] = x.plain[i]
}
if n < len(x.plain) {
x.plain = x.plain[n:]
} else {
x.plain = nil
}
return n
}
type ecbFragmentError int
func (n ecbFragmentError) String() string {
return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF"
}
func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
if len(p) == 0 {
return
}
// If there's no plaintext waiting and p is not big enough
// to hold a whole cipher block, we'll have to work in the
// cipher text buffer. Set it to non-nil so that the
// code below will fill it.
if x.plain == nil && len(p) < x.blockSize && x.crypt == nil {
x.crypt = x.buf[0:0]
}
// If there is a leftover cipher text buffer,
// try to accumulate a full block.
if x.crypt != nil {
err = x.fillCrypt()
if err != nil || len(x.crypt) == 0 {
return
}
x.c.Decrypt(x.crypt, x.crypt)
x.plain = x.crypt
x.crypt = nil
}
// If there is a leftover plain text buffer, read from it.
if x.plain != nil {
n = x.readPlain(p)
return
}
// Read and decrypt directly in caller's buffer.
n, err = io.ReadAtLeast(x.r, p, x.blockSize)
if err == os.EOF && n > 0 {
// EOF is only okay on block boundary
err = os.ErrorString("block fragment at EOF during decryption")
return
}
var i int
for i = 0; i+x.blockSize <= n; i += x.blockSize {
a := p[i : i+x.blockSize]
x.c.Decrypt(a, a)
}
// There might be an encrypted fringe remaining.
// Save it for next time.
if i < n {
p = p[i:n]
copy(x.buf, p)
x.crypt = x.buf[0:len(p)]
n = i
}
return
}
// NewECBDecrypter returns a reader that reads data from r and decrypts it using c.
// It decrypts by calling c.Decrypt on each block in sequence;
// this mode is known as electronic codebook mode, or ECB.
// The returned Reader does not buffer or read ahead except
// as required by the cipher's block size.
func NewECBDecrypter(c Cipher, r io.Reader) io.Reader {
x := new(ecbDecrypter)
x.c = c
x.r = r
x.blockSize = c.BlockSize()
x.buf = make([]byte, x.blockSize)
return x
}
type ecbEncrypter struct {
c Cipher
w io.Writer
blockSize int
// Buffered data.
// The buffer buf is used as storage for both
// plain or crypt. If both are non-nil, plain
// follows crypt in buf.
buf []byte
plain []byte // plain text waiting to be encrypted
crypt []byte // encrypted text waiting to be written
}
// Flush the x.crypt buffer to x.w.
func (x *ecbEncrypter) flushCrypt() os.Error {
if len(x.crypt) == 0 {
return nil
}
n, err := x.w.Write(x.crypt)
if n < len(x.crypt) {
x.crypt = x.crypt[n:]
if err == nil {
err = io.ErrShortWrite
}
}
if err != nil {
return err
}
x.crypt = nil
return nil
}
// Slide x.plain down to the beginning of x.buf.
// Plain is known to have less than one block of data,
// so this is cheap enough.
func (x *ecbEncrypter) slidePlain() {
if len(x.plain) == 0 {
x.plain = x.buf[0:0]
} else if cap(x.plain) < cap(x.buf) {
copy(x.buf, x.plain)
x.plain = x.buf[0:len(x.plain)]
}
}
// Fill x.plain from the data in p.
// Return the number of bytes copied.
func (x *ecbEncrypter) fillPlain(p []byte) int {
off := len(x.plain)
n := len(p)
if max := cap(x.plain) - off; n > max {
n = max
}
x.plain = x.plain[0 : off+n]
for i := 0; i < n; i++ {
x.plain[off+i] = p[i]
}
return n
}
// Encrypt x.plain; record encrypted range as x.crypt.
func (x *ecbEncrypter) encrypt() {
var i int
n := len(x.plain)
for i = 0; i+x.blockSize <= n; i += x.blockSize {
a := x.plain[i : i+x.blockSize]
x.c.Encrypt(a, a)
}
x.crypt = x.plain[0:i]
x.plain = x.plain[i:n]
}
func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
for {
// If there is data waiting to be written, write it.
// This can happen on the first iteration
// if a write failed in an earlier call.
if err = x.flushCrypt(); err != nil {
return
}
// Now that encrypted data is gone (flush ran),
// perhaps we need to slide the plaintext down.
x.slidePlain()
// Fill plaintext buffer from p.
m := x.fillPlain(p)
if m == 0 {
break
}
n += m
p = p[m:]
// Encrypt, adjusting crypt and plain.
x.encrypt()
// Write x.crypt.
if err = x.flushCrypt(); err != nil {
break
}
}
return
}
// NewECBEncrypter returns a writer that encrypts data using c and writes it to w.
// It encrypts by calling c.Encrypt on each block in sequence;
// this mode is known as electronic codebook mode, or ECB.
// The returned Writer does no buffering except as required
// by the cipher's block size, so there is no need for a Flush method.
func NewECBEncrypter(c Cipher, w io.Writer) io.Writer {
x := new(ecbEncrypter)
x.c = c
x.w = w
x.blockSize = c.BlockSize()
// Create a buffer that is an integral number of blocks.
x.buf = make([]byte, 8192/x.blockSize*x.blockSize)
return x
}
// Copyright 2009 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.
// ECB AES test vectors.
// See U.S. National Institute of Standards and Technology (NIST)
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 24-27.
package block
import (
"bytes"
"crypto/aes"
"io"
"testing"
)
type ecbTest struct {
name string
key []byte
in []byte
out []byte
}
var commonInput = []byte{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
}
var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
var commonKey192 = []byte{
0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
}
var commonKey256 = []byte{
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
}
var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
var ecbAESTests = []ecbTest{
// FIPS 197, Appendix B, C
{
"FIPS-197 Appendix B",
commonKey128,
[]byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34},
[]byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32},
},
// NIST SP 800-38A pp 24-27
{
"ECB-AES128",
commonKey128,
commonInput,
[]byte{
0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf,
0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23, 0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88,
0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f, 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4,
},
},
{
"ECB-AES192",
commonKey192,
commonInput,
[]byte{
0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef,
0xef, 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a, 0xdc, 0xe0, 0xba, 0x2f, 0xac, 0xe6, 0x44, 0x4e,
0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c, 0x72, 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e,
},
},
{
"ECB-AES256",
commonKey256,
commonInput,
[]byte{
0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70,
0xb6, 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9, 0xf1, 0x53, 0xe7, 0xb1, 0xbe, 0xaf, 0xed, 0x1d,
0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3, 0xff, 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7,
},
},
}
func TestECB_AES(t *testing.T) {
for _, tt := range ecbAESTests {
test := tt.name
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
continue
}
var crypt bytes.Buffer
w := NewECBEncrypter(c, &crypt)
var r io.Reader = bytes.NewBuffer(tt.in)
n, err := io.Copy(w, r)
if n != int64(len(tt.in)) || err != nil {
t.Errorf("%s: ECBReader io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
} else if d := crypt.Bytes(); !same(tt.out, d) {
t.Errorf("%s: ECBReader\nhave %x\nwant %x", test, d, tt.out)
}
var plain bytes.Buffer
r = NewECBDecrypter(c, bytes.NewBuffer(tt.out))
w = &plain
n, err = io.Copy(w, r)
if n != int64(len(tt.out)) || err != nil {
t.Errorf("%s: ECBWriter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
} else if d := plain.Bytes(); !same(tt.in, d) {
t.Errorf("%s: ECBWriter\nhave %x\nwant %x", test, d, tt.in)
}
if t.Failed() {
break
}
}
}
// Copyright 2009 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 block
import (
"bytes"
"fmt"
"io"
"testing"
"testing/iotest"
)
// Simple Cipher for testing: adds an incrementing amount
// to each byte in each
type IncCipher struct {
blockSize int
delta byte
encrypting bool
}
func (c *IncCipher) BlockSize() int { return c.blockSize }
func (c *IncCipher) Encrypt(dst, src []byte) {
if !c.encrypting {
panic("encrypt: not encrypting")
}
if len(src) != c.blockSize || len(dst) != c.blockSize {
panic(fmt.Sprintln("encrypt: wrong block size", c.blockSize, len(src), len(dst)))
}
c.delta++
for i, b := range src {
dst[i] = b + c.delta
}
}
func (c *IncCipher) Decrypt(dst, src []byte) {
if c.encrypting {
panic("decrypt: not decrypting")
}
if len(src) != c.blockSize || len(dst) != c.blockSize {
panic(fmt.Sprintln("decrypt: wrong block size ", c.blockSize, " ", len(src), " ", len(dst)))
}
c.delta--
for i, b := range src {
dst[i] = b + c.delta
}
}
func TestECBEncrypter(t *testing.T) {
var plain, crypt [256]byte
for i := 0; i < len(plain); i++ {
plain[i] = byte(i)
}
b := new(bytes.Buffer)
for block := 1; block <= 64; block *= 2 {
// compute encrypted version
delta := byte(0)
for i := 0; i < len(crypt); i++ {
if i%block == 0 {
delta++
}
crypt[i] = plain[i] + delta
}
for frag := 0; frag < 2; frag++ {
c := &IncCipher{block, 0, true}
b.Reset()
r := bytes.NewBuffer(plain[0:])
w := NewECBEncrypter(c, b)
// copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
// if frag != 0, move the 1 to the end to cause fragmentation.
if frag == 0 {
_, err := io.Copyn(w, r, 1)
if err != nil {
t.Errorf("block=%d frag=0: first Copyn: %s", block, err)
continue
}
}
for n := 1; n <= len(plain)/2; n *= 2 {
_, err := io.Copyn(w, r, int64(n))
if err != nil {
t.Errorf("block=%d frag=%d: Copyn %d: %s", block, frag, n, err)
}
}
if frag != 0 {
_, err := io.Copyn(w, r, 1)
if err != nil {
t.Errorf("block=%d frag=1: last Copyn: %s", block, err)
continue
}
}
// check output
data := b.Bytes()
if len(data) != len(crypt) {
t.Errorf("block=%d frag=%d: want %d bytes, got %d", block, frag, len(crypt), len(data))
continue
}
if string(data) != string(crypt[0:]) {
t.Errorf("block=%d frag=%d: want %x got %x", block, frag, data, crypt)
}
}
}
}
func testECBDecrypter(t *testing.T, maxio int) {
var readers = []func(io.Reader) io.Reader{
func(r io.Reader) io.Reader { return r },
iotest.OneByteReader,
iotest.HalfReader,
}
var plain, crypt [256]byte
for i := 0; i < len(plain); i++ {
plain[i] = byte(255 - i)
}
b := new(bytes.Buffer)
for block := 1; block <= 64 && block <= maxio; block *= 2 {
// compute encrypted version
delta := byte(0)
for i := 0; i < len(crypt); i++ {
if i%block == 0 {
delta++
}
crypt[i] = plain[i] + delta
}
for mode := 0; mode < len(readers); mode++ {
for frag := 0; frag < 2; frag++ {
test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
c := &IncCipher{block, 0, false}
b.Reset()
r := NewECBDecrypter(c, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
// read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
// if frag == 1, move the 1 to the end to cause fragmentation.
if frag == 0 {
_, err := io.Copyn(b, r, 1)
if err != nil {
t.Errorf("%s: first Copyn: %s", test, err)
continue
}
}
for n := 1; n <= maxio/2; n *= 2 {
_, err := io.Copyn(b, r, int64(n))
if err != nil {
t.Errorf("%s: Copyn %d: %s", test, n, err)
}
}
if frag != 0 {
_, err := io.Copyn(b, r, 1)
if err != nil {
t.Errorf("%s: last Copyn: %s", test, err)
continue
}
}
// check output
data := b.Bytes()
if len(data) != maxio {
t.Errorf("%s: want %d bytes, got %d", test, maxio, len(data))
continue
}
if string(data) != string(plain[0:maxio]) {
t.Errorf("%s: input=%x want %x got %x", test, crypt[0:maxio], plain[0:maxio], data)
}
}
}
}
}
func TestECBDecrypter(t *testing.T) {
// Do shorter I/O sizes first; they're easier to debug.
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
testECBDecrypter(t, n)
}
}
// Copyright 2009 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.
// Output feedback (OFB) mode.
// OFB converts a block cipher into a stream cipher by
// repeatedly encrypting an initialization vector and
// xoring the resulting stream of data with the input.
// See NIST SP 800-38A, pp 13-15
package block
import (
"fmt"
"io"
)
type ofbStream struct {
c Cipher
iv []byte
}
func newOFBStream(c Cipher, iv []byte) *ofbStream {
x := new(ofbStream)
x.c = c
n := len(iv)
if n != c.BlockSize() {
panic(fmt.Sprintln("crypto/block: newOFBStream: invalid iv size", n, "!=", c.BlockSize()))
}
x.iv = dup(iv)
return x
}
func (x *ofbStream) Next() []byte {
x.c.Encrypt(x.iv, x.iv)
return x.iv
}
// NewOFBReader returns a reader that reads data from r, decrypts (or encrypts)
// it using c in output feedback (OFB) mode with the initialization vector iv.
// The returned Reader does not buffer and has no block size.
// In OFB mode, encryption and decryption are the same operation:
// an OFB reader applied to an encrypted stream produces a decrypted
// stream and vice versa.
func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
return newXorReader(newOFBStream(c, iv), r)
}
// NewOFBWriter returns a writer that encrypts (or decrypts) data using c
// in cipher feedback (OFB) mode with the initialization vector iv
// and writes the encrypted data to w.
// The returned Writer does not buffer and has no block size.
// In OFB mode, encryption and decryption are the same operation:
// an OFB writer applied to an decrypted stream produces an encrypted
// stream and vice versa.
func NewOFBWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
return newXorWriter(newOFBStream(c, iv), w)
}
// Copyright 2009 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.
// OFB AES test vectors.
// See U.S. National Institute of Standards and Technology (NIST)
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 52-55.
package block
import (
"bytes"
"crypto/aes"
"io"
"testing"
)
type ofbTest struct {
name string
key []byte
iv []byte
in []byte
out []byte
}
var ofbAESTests = []ofbTest{
// NIST SP 800-38A pp 52-55
{
"OFB-AES128",
commonKey128,
commonIV,
commonInput,
[]byte{
0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
},
},
{
"OFB-AES192",
commonKey192,
commonIV,
commonInput,
[]byte{
0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
},
},
{
"OFB-AES256",
commonKey256,
commonIV,
commonInput,
[]byte{
0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
},
},
}
func TestOFB_AES(t *testing.T) {
for _, tt := range ofbAESTests {
test := tt.name
c, err := aes.NewCipher(tt.key)
if err != nil {
t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
continue
}
for j := 0; j <= 5; j += 5 {
var crypt bytes.Buffer
in := tt.in[0 : len(tt.in)-j]
w := NewOFBWriter(c, tt.iv, &crypt)
var r io.Reader = bytes.NewBuffer(in)
n, err := io.Copy(w, r)
if n != int64(len(in)) || err != nil {
t.Errorf("%s/%d: OFBWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
} else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
t.Errorf("%s/%d: OFBWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
}
}
for j := 0; j <= 7; j += 7 {
var plain bytes.Buffer
out := tt.out[0 : len(tt.out)-j]
r := NewOFBReader(c, tt.iv, bytes.NewBuffer(out))
w := &plain
n, err := io.Copy(w, r)
if n != int64(len(out)) || err != nil {
t.Errorf("%s/%d: OFBReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
} else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
t.Errorf("%s/%d: OFBReader\nhave %x\nwant %x", test, len(out), d, in)
}
}
if t.Failed() {
break
}
}
}
// Copyright 2009 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.
// Encrypt/decrypt data by xor with a pseudo-random data stream.
package block
import (
"io"
"os"
)
// A dataStream is an interface to an unending stream of data,
// used by XorReader and XorWriter to model a pseudo-random generator.
// Calls to Next() return sequential blocks of data from the stream.
// Each call must return at least one byte: there is no EOF.
type dataStream interface {
Next() []byte
}
type xorReader struct {
r io.Reader
rand dataStream // pseudo-random
buf []byte // data available from last call to rand
}
func newXorReader(rand dataStream, r io.Reader) io.Reader {
x := new(xorReader)
x.r = r
x.rand = rand
return x
}
func (x *xorReader) Read(p []byte) (n int, err os.Error) {
n, err = x.r.Read(p)
// xor input with stream.
bp := 0
buf := x.buf
for i := 0; i < n; i++ {
if bp >= len(buf) {
buf = x.rand.Next()
bp = 0
}
p[i] ^= buf[bp]
bp++
}
x.buf = buf[bp:]
return n, err
}
type xorWriter struct {
w io.Writer
rand dataStream // pseudo-random
buf []byte // last buffer returned by rand
extra []byte // extra random data (use before buf)
work []byte // work space
}
func newXorWriter(rand dataStream, w io.Writer) io.Writer {
x := new(xorWriter)
x.w = w
x.rand = rand
x.work = make([]byte, 4096)
return x
}
func (x *xorWriter) Write(p []byte) (n int, err os.Error) {
for len(p) > 0 {
// Determine next chunk of random data
// and xor with p into x.work.
var chunk []byte
m := len(p)
if nn := len(x.extra); nn > 0 {
// extra points into work, so edit directly
if m > nn {
m = nn
}
for i := 0; i < m; i++ {
x.extra[i] ^= p[i]
}
chunk = x.extra[0:m]
} else {
// xor p ^ buf into work, refreshing buf as needed
if nn := len(x.work); m > nn {
m = nn
}
bp := 0
buf := x.buf
for i := 0; i < m; i++ {
if bp >= len(buf) {
buf = x.rand.Next()
bp = 0
}
x.work[i] = buf[bp] ^ p[i]
bp++
}
x.buf = buf[bp:]
chunk = x.work[0:m]
}
// Write chunk.
var nn int
nn, err = x.w.Write(chunk)
if nn != len(chunk) && err == nil {
err = io.ErrShortWrite
}
if nn < len(chunk) {
// Reconstruct the random bits from the unwritten
// data and save them for next time.
for i := nn; i < m; i++ {
chunk[i] ^= p[i]
}
x.extra = chunk[nn:]
}
n += nn
if err != nil {
return
}
p = p[m:]
}
return
}
// Copyright 2009 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 block
import (
"bytes"
"fmt"
"io"
"testing"
"testing/iotest"
)
// Simple "pseudo-random" stream for testing.
type incStream struct {
buf []byte
n byte
}
func newIncStream(blockSize int) *incStream {
x := new(incStream)
x.buf = make([]byte, blockSize)
return x
}
func (x *incStream) Next() []byte {
x.n++
for i := range x.buf {
x.buf[i] = x.n
x.n++
}
return x.buf
}
func testXorWriter(t *testing.T, maxio int) {
var plain, crypt [256]byte
for i := 0; i < len(plain); i++ {
plain[i] = byte(i)
}
b := new(bytes.Buffer)
for block := 1; block <= 64 && block <= maxio; block *= 2 {
// compute encrypted version
n := byte(0)
for i := 0; i < len(crypt); i++ {
if i%block == 0 {
n++
}
crypt[i] = plain[i] ^ n
n++
}
for frag := 0; frag < 2; frag++ {
test := fmt.Sprintf("block=%d frag=%d maxio=%d", block, frag, maxio)
b.Reset()
r := bytes.NewBuffer(plain[0:])
s := newIncStream(block)
w := newXorWriter(s, b)
// copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
// if frag != 0, move the 1 to the end to cause fragmentation.
if frag == 0 {
_, err := io.Copyn(w, r, 1)
if err != nil {
t.Errorf("%s: first Copyn: %s", test, err)
continue
}
}
for n := 1; n <= len(plain)/2; n *= 2 {
_, err := io.Copyn(w, r, int64(n))
if err != nil {
t.Errorf("%s: Copyn %d: %s", test, n, err)
}
}
// check output
crypt := crypt[0 : len(crypt)-frag]
data := b.Bytes()
if len(data) != len(crypt) {
t.Errorf("%s: want %d bytes, got %d", test, len(crypt), len(data))
continue
}
if string(data) != string(crypt) {
t.Errorf("%s: want %x got %x", test, data, crypt)
}
}
}
}
func TestXorWriter(t *testing.T) {
// Do shorter I/O sizes first; they're easier to debug.
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
testXorWriter(t, n)
}
}
func testXorReader(t *testing.T, maxio int) {
var readers = []func(io.Reader) io.Reader{
func(r io.Reader) io.Reader { return r },
iotest.OneByteReader,
iotest.HalfReader,
}
var plain, crypt [256]byte
for i := 0; i < len(plain); i++ {
plain[i] = byte(255 - i)
}
b := new(bytes.Buffer)
for block := 1; block <= 64 && block <= maxio; block *= 2 {
// compute encrypted version
n := byte(0)
for i := 0; i < len(crypt); i++ {
if i%block == 0 {
n++
}
crypt[i] = plain[i] ^ n
n++
}
for mode := 0; mode < len(readers); mode++ {
for frag := 0; frag < 2; frag++ {
test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
s := newIncStream(block)
b.Reset()
r := newXorReader(s, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
// read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
// if frag == 1, move the 1 to the end to cause fragmentation.
if frag == 0 {
_, err := io.Copyn(b, r, 1)
if err != nil {
t.Errorf("%s: first Copyn: %s", test, err)
continue
}
}
for n := 1; n <= maxio/2; n *= 2 {
_, err := io.Copyn(b, r, int64(n))
if err != nil {
t.Errorf("%s: Copyn %d: %s", test, n, err)
}
}
// check output
data := b.Bytes()
crypt := crypt[0 : maxio-frag]
plain := plain[0 : maxio-frag]
if len(data) != len(plain) {
t.Errorf("%s: want %d bytes, got %d", test, len(plain), len(data))
continue
}
if string(data) != string(plain) {
t.Errorf("%s: input=%x want %x got %x", test, crypt, plain, data)
}
}
}
}
}
func TestXorReader(t *testing.T) {
// Do shorter I/O sizes first; they're easier to debug.
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
testXorReader(t, n)
}
}
// TODO(rsc): Test handling of writes after write errors.
// 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 des
import (
"encoding/binary"
)
func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
b := binary.BigEndian.Uint64(src)
b = permuteBlock(b, initialPermutation[:])
left, right := uint32(b>>32), uint32(b)
var subkey uint64
for i := 0; i < 16; i++ {
if decrypt {
subkey = subkeys[15-i]
} else {
subkey = subkeys[i]
}
left, right = right, left^feistel(right, subkey)
}
// switch left & right and perform final permutation
preOutput := (uint64(right) << 32) | uint64(left)
binary.BigEndian.PutUint64(dst, permuteBlock(preOutput, finalPermutation[:]))
}
// Encrypt one block from src into dst, using the subkeys.
func encryptBlock(subkeys []uint64, dst, src []byte) {
cryptBlock(subkeys, dst, src, false)
}
// Decrypt one block from src into dst, using the subkeys.
func decryptBlock(subkeys []uint64, dst, src []byte) {
cryptBlock(subkeys, dst, src, true)
}
// DES Feistel function
func feistel(right uint32, key uint64) (result uint32) {
sBoxLocations := key ^ permuteBlock(uint64(right), expansionFunction[:])
var sBoxResult uint32
for i := uint8(0); i < 8; i++ {
sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
sBoxLocations <<= 6
// row determined by 1st and 6th bit
row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
// column is middle four bits
column := (sBoxLocation >> 1) & 0xf
sBoxResult |= uint32(sBoxes[i][row][column]) << (4 * (7 - i))
}
return uint32(permuteBlock(uint64(sBoxResult), permutationFunction[:]))
}
// general purpose function to perform DES block permutations
func permuteBlock(src uint64, permutation []uint8) (block uint64) {
for position, n := range permutation {
bit := (src >> n) & 1
block |= bit << uint((len(permutation)-1)-position)
}
return
}
// creates 16 28-bit blocks rotated according
// to the rotation schedule
func ksRotate(in uint32) (out []uint32) {
out = make([]uint32, 16)
last := in
for i := 0; i < 16; i++ {
// 28-bit circular left shift
left := (last << (4 + ksRotations[i])) >> 4
right := (last << 4) >> (32 - ksRotations[i])
out[i] = left | right
last = out[i]
}
return
}
// creates 16 56-bit subkeys from the original key
func (c *Cipher) generateSubkeys(keyBytes []byte) {
// apply PC1 permutation to key
key := binary.BigEndian.Uint64(keyBytes)
permutedKey := permuteBlock(key, permutedChoice1[:])
// rotate halves of permuted key according to the rotation schedule
leftRotations := ksRotate(uint32(permutedKey >> 28))
rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
// generate subkeys
for i := 0; i < 16; i++ {
// combine halves to form 56-bit input to PC2
pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
// apply PC2 permutation to 7 byte input
c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
}
}
// 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 des
import (
"os"
"strconv"
)
// The DES block size in bytes.
const BlockSize = 8
type KeySizeError int
func (k KeySizeError) String() string {
return "crypto/des: invalid key size " + strconv.Itoa(int(k))
}
// Cipher is an instance of DES encryption.
type Cipher struct {
subkeys [16]uint64
}
// NewCipher creates and returns a new Cipher.
func NewCipher(key []byte) (*Cipher, os.Error) {
if len(key) != 8 {
return nil, KeySizeError(len(key))
}
c := new(Cipher)
c.generateSubkeys(key)
return c, nil
}
// BlockSize returns the DES block size, 8 bytes.
func (c *Cipher) BlockSize() int { return BlockSize }
// Encrypts the 8-byte buffer src and stores the result in dst.
// Note that for amounts of data larger than a block,
// it is not safe to just call Encrypt on successive blocks;
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
// Decrypts the 8-byte buffer src and stores the result in dst.
func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
// Reset zeros the key data, so that it will no longer
// appear in the process's memory.
func (c *Cipher) Reset() {
for i := 0; i < len(c.subkeys); i++ {
c.subkeys[i] = 0
}
}
// A TripleDESCipher is an instance of TripleDES encryption.
type TripleDESCipher struct {
cipher1, cipher2, cipher3 Cipher
}
// NewCipher creates and returns a new Cipher.
func NewTripleDESCipher(key []byte) (*TripleDESCipher, os.Error) {
if len(key) != 24 {
return nil, KeySizeError(len(key))
}
c := new(TripleDESCipher)
c.cipher1.generateSubkeys(key[:8])
c.cipher2.generateSubkeys(key[8:16])
c.cipher3.generateSubkeys(key[16:])
return c, nil
}
// BlockSize returns the TripleDES block size, 8 bytes.
// It is necessary to satisfy the Block interface in the
// package "crypto/cipher".
func (c *TripleDESCipher) BlockSize() int { return BlockSize }
// Encrypts the 8-byte buffer src and stores the result in dst.
// Note that for amounts of data larger than a block,
// it is not safe to just call Encrypt on successive blocks;
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
func (c *TripleDESCipher) Encrypt(dst, src []byte) {
c.cipher1.Encrypt(dst, src)
c.cipher2.Decrypt(dst, dst)
c.cipher3.Encrypt(dst, dst)
}
// Decrypts the 8-byte buffer src and stores the result in dst.
func (c *TripleDESCipher) Decrypt(dst, src []byte) {
c.cipher3.Decrypt(dst, src)
c.cipher2.Encrypt(dst, dst)
c.cipher1.Decrypt(dst, dst)
}
// Reset zeros the key data, so that it will no longer
// appear in the process's memory.
func (c *TripleDESCipher) Reset() {
c.cipher1.Reset()
c.cipher2.Reset()
c.cipher3.Reset()
}
// Copyright 2010 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 des implements the Data Encryption Standard (DES) and the
// Triple Data Encryption Algorithm (TDEA) as defined
// in U.S. Federal Information Processing Standards Publication 46-3.
package des
// Used to perform an initial permutation of a 64-bit input block.
var initialPermutation = [64]byte{
6, 14, 22, 30, 38, 46, 54, 62,
4, 12, 20, 28, 36, 44, 52, 60,
2, 10, 18, 26, 34, 42, 50, 58,
0, 8, 16, 24, 32, 40, 48, 56,
7, 15, 23, 31, 39, 47, 55, 63,
5, 13, 21, 29, 37, 45, 53, 61,
3, 11, 19, 27, 35, 43, 51, 59,
1, 9, 17, 25, 33, 41, 49, 57,
}
// Used to perform a final permutation of a 4-bit preoutput block. This is the
// inverse of initialPermutation
var finalPermutation = [64]byte{
24, 56, 16, 48, 8, 40, 0, 32,
25, 57, 17, 49, 9, 41, 1, 33,
26, 58, 18, 50, 10, 42, 2, 34,
27, 59, 19, 51, 11, 43, 3, 35,
28, 60, 20, 52, 12, 44, 4, 36,
29, 61, 21, 53, 13, 45, 5, 37,
30, 62, 22, 54, 14, 46, 6, 38,
31, 63, 23, 55, 15, 47, 7, 39,
}
// Used to expand an input block of 32 bits, producing an output block of 48
// bits.
var expansionFunction = [48]byte{
0, 31, 30, 29, 28, 27, 28, 27,
26, 25, 24, 23, 24, 23, 22, 21,
20, 19, 20, 19, 18, 17, 16, 15,
16, 15, 14, 13, 12, 11, 12, 11,
10, 9, 8, 7, 8, 7, 6, 5,
4, 3, 4, 3, 2, 1, 0, 31,
}
// Yields a 32-bit output from a 32-bit input
var permutationFunction = [32]byte{
16, 25, 12, 11, 3, 20, 4, 15,
31, 17, 9, 6, 27, 14, 1, 22,
30, 24, 8, 18, 0, 5, 29, 23,
13, 19, 2, 26, 10, 21, 28, 7,
}
// Used in the key schedule to select 56 bits
// from a 64-bit input.
var permutedChoice1 = [56]byte{
7, 15, 23, 31, 39, 47, 55, 63,
6, 14, 22, 30, 38, 46, 54, 62,
5, 13, 21, 29, 37, 45, 53, 61,
4, 12, 20, 28, 1, 9, 17, 25,
33, 41, 49, 57, 2, 10, 18, 26,
34, 42, 50, 58, 3, 11, 19, 27,
35, 43, 51, 59, 36, 44, 52, 60,
}
// Used in the key schedule to produce each subkey by selecting 48 bits from
// the 56-bit input
var permutedChoice2 = [48]byte{
42, 39, 45, 32, 55, 51, 53, 28,
41, 50, 35, 46, 33, 37, 44, 52,
30, 48, 40, 49, 29, 36, 43, 54,
15, 4, 25, 19, 9, 1, 26, 16,
5, 11, 23, 8, 12, 7, 17, 0,
22, 3, 10, 14, 6, 20, 27, 24,
}
// 8 S-boxes composed of 4 rows and 16 columns
// Used in the DES cipher function
var sBoxes = [8][4][16]uint8{
// S-box 1
{
{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
},
// S-box 2
{
{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
},
// S-box 3
{
{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
},
// S-box 4
{
{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
},
// S-box 5
{
{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
},
// S-box 6
{
{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
},
// S-box 7
{
{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
},
// S-box 8
{
{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11},
},
}
// Size of left rotation per round in each half of the key schedule
var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
...@@ -37,7 +37,7 @@ var one = new(big.Int).SetInt64(1) ...@@ -37,7 +37,7 @@ var one = new(big.Int).SetInt64(1)
// curve using the procedure given in [NSA] A.2.1. // curve using the procedure given in [NSA] A.2.1.
func randFieldElement(c *elliptic.Curve, rand io.Reader) (k *big.Int, err os.Error) { func randFieldElement(c *elliptic.Curve, rand io.Reader) (k *big.Int, err os.Error) {
b := make([]byte, c.BitSize/8+8) b := make([]byte, c.BitSize/8+8)
_, err = rand.Read(b) _, err = io.ReadFull(rand, b)
if err != nil { if err != nil {
return return
} }
......
...@@ -32,7 +32,7 @@ func (r *devReader) Read(b []byte) (n int, err os.Error) { ...@@ -32,7 +32,7 @@ func (r *devReader) Read(b []byte) (n int, err os.Error) {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
if r.f == nil { if r.f == nil {
f, err := os.Open(r.name, os.O_RDONLY, 0) f, err := os.Open(r.name)
if f == nil { if f == nil {
return 0, err return 0, err
} }
......
...@@ -127,7 +127,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) { ...@@ -127,7 +127,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
for s[i] == 0 { for s[i] == 0 {
_, err = rand.Read(s[i : i+1]) _, err = io.ReadFull(rand, s[i:i+1])
if err != nil { if err != nil {
return return
} }
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"hash" "hash"
"io" "io"
"os" "os"
"sync"
) )
var bigZero = big.NewInt(0) var bigZero = big.NewInt(0)
...@@ -91,15 +92,21 @@ type PublicKey struct { ...@@ -91,15 +92,21 @@ type PublicKey struct {
type PrivateKey struct { type PrivateKey struct {
PublicKey // public part. PublicKey // public part.
D *big.Int // private exponent D *big.Int // private exponent
P, Q *big.Int // prime factors of N P, Q, R *big.Int // prime factors of N (R may be nil)
rwMutex sync.RWMutex // protects the following
dP, dQ, dR *big.Int // D mod (P-1) (or mod Q-1 etc)
qInv *big.Int // q^-1 mod p
pq *big.Int // P*Q
tr *big.Int // pq·tr ≡ 1 mod r
} }
// Validate performs basic sanity checks on the key. // Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an os.Error describing a problem. // It returns nil if the key is valid, or else an os.Error describing a problem.
func (priv PrivateKey) Validate() os.Error { func (priv *PrivateKey) Validate() os.Error {
// Check that p and q are prime. Note that this is just a sanity // Check that p, q and, maybe, r are prime. Note that this is just a
// check. Since the random witnesses chosen by ProbablyPrime are // sanity check. Since the random witnesses chosen by ProbablyPrime are
// deterministic, given the candidate number, it's easy for an attack // deterministic, given the candidate number, it's easy for an attack
// to generate composites that pass this test. // to generate composites that pass this test.
if !big.ProbablyPrime(priv.P, 20) { if !big.ProbablyPrime(priv.P, 20) {
...@@ -108,16 +115,26 @@ func (priv PrivateKey) Validate() os.Error { ...@@ -108,16 +115,26 @@ func (priv PrivateKey) Validate() os.Error {
if !big.ProbablyPrime(priv.Q, 20) { if !big.ProbablyPrime(priv.Q, 20) {
return os.ErrorString("Q is composite") return os.ErrorString("Q is composite")
} }
if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
return os.ErrorString("R is composite")
}
// Check that p*q == n. // Check that p*q*r == n.
modulus := new(big.Int).Mul(priv.P, priv.Q) modulus := new(big.Int).Mul(priv.P, priv.Q)
if priv.R != nil {
modulus.Mul(modulus, priv.R)
}
if modulus.Cmp(priv.N) != 0 { if modulus.Cmp(priv.N) != 0 {
return os.ErrorString("invalid modulus") return os.ErrorString("invalid modulus")
} }
// Check that e and totient(p, q) are coprime. // Check that e and totient(p, q, r) are coprime.
pminus1 := new(big.Int).Sub(priv.P, bigOne) pminus1 := new(big.Int).Sub(priv.P, bigOne)
qminus1 := new(big.Int).Sub(priv.Q, bigOne) qminus1 := new(big.Int).Sub(priv.Q, bigOne)
totient := new(big.Int).Mul(pminus1, qminus1) totient := new(big.Int).Mul(pminus1, qminus1)
if priv.R != nil {
rminus1 := new(big.Int).Sub(priv.R, bigOne)
totient.Mul(totient, rminus1)
}
e := big.NewInt(int64(priv.E)) e := big.NewInt(int64(priv.E))
gcd := new(big.Int) gcd := new(big.Int)
x := new(big.Int) x := new(big.Int)
...@@ -126,7 +143,7 @@ func (priv PrivateKey) Validate() os.Error { ...@@ -126,7 +143,7 @@ func (priv PrivateKey) Validate() os.Error {
if gcd.Cmp(bigOne) != 0 { if gcd.Cmp(bigOne) != 0 {
return os.ErrorString("invalid public exponent E") return os.ErrorString("invalid public exponent E")
} }
// Check that de ≡ 1 (mod totient(p, q)) // Check that de ≡ 1 (mod totient(p, q, r))
de := new(big.Int).Mul(priv.D, e) de := new(big.Int).Mul(priv.D, e)
de.Mod(de, totient) de.Mod(de, totient)
if de.Cmp(bigOne) != 0 { if de.Cmp(bigOne) != 0 {
...@@ -135,7 +152,7 @@ func (priv PrivateKey) Validate() os.Error { ...@@ -135,7 +152,7 @@ func (priv PrivateKey) Validate() os.Error {
return nil return nil
} }
// GenerateKeyPair generates an RSA keypair of the given bit size. // GenerateKey generates an RSA keypair of the given bit size.
func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) { func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
priv = new(PrivateKey) priv = new(PrivateKey)
// Smaller public exponents lead to faster public key // Smaller public exponents lead to faster public key
...@@ -191,6 +208,77 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) { ...@@ -191,6 +208,77 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
return return
} }
// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
// suggested in [1]. Although the public keys are compatible (actually,
// indistinguishable) from the 2-prime case, the private keys are not. Thus it
// may not be possible to export 3-prime private keys in certain formats or to
// subsequently import them into other code.
//
// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
//
// [1] US patent 4405829 (1972, expired)
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
priv = new(PrivateKey)
priv.E = 3
pminus1 := new(big.Int)
qminus1 := new(big.Int)
rminus1 := new(big.Int)
totient := new(big.Int)
for {
p, err := randomPrime(rand, bits/3)
if err != nil {
return nil, err
}
todo := bits - p.BitLen()
q, err := randomPrime(rand, todo/2)
if err != nil {
return nil, err
}
todo -= q.BitLen()
r, err := randomPrime(rand, todo)
if err != nil {
return nil, err
}
if p.Cmp(q) == 0 ||
q.Cmp(r) == 0 ||
r.Cmp(p) == 0 {
continue
}
n := new(big.Int).Mul(p, q)
n.Mul(n, r)
pminus1.Sub(p, bigOne)
qminus1.Sub(q, bigOne)
rminus1.Sub(r, bigOne)
totient.Mul(pminus1, qminus1)
totient.Mul(totient, rminus1)
g := new(big.Int)
priv.D = new(big.Int)
y := new(big.Int)
e := big.NewInt(int64(priv.E))
big.GcdInt(g, priv.D, y, e, totient)
if g.Cmp(bigOne) == 0 {
priv.D.Add(priv.D, totient)
priv.P = p
priv.Q = q
priv.R = r
priv.N = n
break
}
}
return
}
// incCounter increments a four byte, big-endian counter. // incCounter increments a four byte, big-endian counter.
func incCounter(c *[4]byte) { func incCounter(c *[4]byte) {
if c[3]++; c[3] != 0 { if c[3]++; c[3] != 0 {
...@@ -321,6 +409,26 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { ...@@ -321,6 +409,26 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
return x, true return x, true
} }
// precompute performs some calculations that speed up private key operations
// in the future.
func (priv *PrivateKey) precompute() {
priv.dP = new(big.Int).Sub(priv.P, bigOne)
priv.dP.Mod(priv.D, priv.dP)
priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
priv.dQ.Mod(priv.D, priv.dQ)
priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
if priv.R != nil {
priv.dR = new(big.Int).Sub(priv.R, bigOne)
priv.dR.Mod(priv.D, priv.dR)
priv.pq = new(big.Int).Mul(priv.P, priv.Q)
priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
}
}
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a // decrypt performs an RSA decryption, resulting in a plaintext integer. If a
// random source is given, RSA blinding is used. // random source is given, RSA blinding is used.
func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) { func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) {
...@@ -359,7 +467,48 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E ...@@ -359,7 +467,48 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
c.Mod(c, priv.N) c.Mod(c, priv.N)
} }
m = new(big.Int).Exp(c, priv.D, priv.N) priv.rwMutex.RLock()
if priv.dP == nil && priv.P != nil {
priv.rwMutex.RUnlock()
priv.rwMutex.Lock()
if priv.dP == nil && priv.P != nil {
priv.precompute()
}
priv.rwMutex.Unlock()
priv.rwMutex.RLock()
}
if priv.dP == nil {
m = new(big.Int).Exp(c, priv.D, priv.N)
} else {
// We have the precalculated values needed for the CRT.
m = new(big.Int).Exp(c, priv.dP, priv.P)
m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
m.Sub(m, m2)
if m.Sign() < 0 {
m.Add(m, priv.P)
}
m.Mul(m, priv.qInv)
m.Mod(m, priv.P)
m.Mul(m, priv.Q)
m.Add(m, m2)
if priv.dR != nil {
// 3-prime CRT.
m2.Exp(c, priv.dR, priv.R)
m2.Sub(m2, m)
m2.Mul(m2, priv.tr)
m2.Mod(m2, priv.R)
if m2.Sign() < 0 {
m2.Add(m2, priv.R)
}
m2.Mul(m2, priv.pq)
m.Add(m, m2)
}
}
priv.rwMutex.RUnlock()
if ir != nil { if ir != nil {
// Unblind. // Unblind.
......
...@@ -13,28 +13,48 @@ import ( ...@@ -13,28 +13,48 @@ import (
) )
func TestKeyGeneration(t *testing.T) { func TestKeyGeneration(t *testing.T) {
random := rand.Reader
size := 1024 size := 1024
if testing.Short() { if testing.Short() {
size = 128 size = 128
} }
priv, err := GenerateKey(random, size) priv, err := GenerateKey(rand.Reader, size)
if err != nil {
t.Errorf("failed to generate key")
}
testKeyBasics(t, priv)
}
func Test3PrimeKeyGeneration(t *testing.T) {
if testing.Short() {
return
}
size := 768
priv, err := Generate3PrimeKey(rand.Reader, size)
if err != nil { if err != nil {
t.Errorf("failed to generate key") t.Errorf("failed to generate key")
} }
testKeyBasics(t, priv)
}
func testKeyBasics(t *testing.T, priv *PrivateKey) {
if err := priv.Validate(); err != nil {
t.Errorf("Validate() failed: %s", err)
}
pub := &priv.PublicKey pub := &priv.PublicKey
m := big.NewInt(42) m := big.NewInt(42)
c := encrypt(new(big.Int), pub, m) c := encrypt(new(big.Int), pub, m)
m2, err := decrypt(nil, priv, c) m2, err := decrypt(nil, priv, c)
if err != nil { if err != nil {
t.Errorf("error while decrypting: %s", err) t.Errorf("error while decrypting: %s", err)
return
} }
if m.Cmp(m2) != 0 { if m.Cmp(m2) != 0 {
t.Errorf("got:%v, want:%v (%s)", m2, m, priv) t.Errorf("got:%v, want:%v (%+v)", m2, m, priv)
} }
m3, err := decrypt(random, priv, c) m3, err := decrypt(rand.Reader, priv, c)
if err != nil { if err != nil {
t.Errorf("error while decrypting (blind): %s", err) t.Errorf("error while decrypting (blind): %s", err)
} }
...@@ -43,6 +63,57 @@ func TestKeyGeneration(t *testing.T) { ...@@ -43,6 +63,57 @@ func TestKeyGeneration(t *testing.T) {
} }
} }
func fromBase10(base10 string) *big.Int {
i := new(big.Int)
i.SetString(base10, 10)
return i
}
func BenchmarkRSA2048Decrypt(b *testing.B) {
b.StopTimer()
priv := &PrivateKey{
PublicKey: PublicKey{
N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
E: 3,
},
D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
}
priv.precompute()
c := fromBase10("1000")
b.StartTimer()
for i := 0; i < b.N; i++ {
decrypt(nil, priv, c)
}
}
func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
b.StopTimer()
priv := &PrivateKey{
PublicKey: PublicKey{
N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
E: 3,
},
D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
}
priv.precompute()
c := fromBase10("1000")
b.StartTimer()
for i := 0; i < b.N; i++ {
decrypt(nil, priv, c)
}
}
type testEncryptOAEPMessage struct { type testEncryptOAEPMessage struct {
in []byte in []byte
seed []byte seed []byte
...@@ -85,10 +156,12 @@ func TestDecryptOAEP(t *testing.T) { ...@@ -85,10 +156,12 @@ func TestDecryptOAEP(t *testing.T) {
for i, test := range testEncryptOAEPData { for i, test := range testEncryptOAEPData {
n.SetString(test.modulus, 16) n.SetString(test.modulus, 16)
d.SetString(test.d, 16) d.SetString(test.d, 16)
private := PrivateKey{PublicKey{n, test.e}, d, nil, nil} private := new(PrivateKey)
private.PublicKey = PublicKey{n, test.e}
private.D = d
for j, message := range test.msgs { for j, message := range test.msgs {
out, err := DecryptOAEP(sha1, nil, &private, message.out, nil) out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
if err != nil { if err != nil {
t.Errorf("#%d,%d error: %s", i, j, err) t.Errorf("#%d,%d error: %s", i, j, err)
} else if bytes.Compare(out, message.in) != 0 { } else if bytes.Compare(out, message.in) != 0 {
...@@ -96,7 +169,7 @@ func TestDecryptOAEP(t *testing.T) { ...@@ -96,7 +169,7 @@ func TestDecryptOAEP(t *testing.T) {
} }
// Decrypt with blinding. // Decrypt with blinding.
out, err = DecryptOAEP(sha1, random, &private, message.out, nil) out, err = DecryptOAEP(sha1, random, private, message.out, nil)
if err != nil { if err != nil {
t.Errorf("#%d,%d (blind) error: %s", i, j, err) t.Errorf("#%d,%d (blind) error: %s", i, j, err)
} else if bytes.Compare(out, message.in) != 0 { } else if bytes.Compare(out, message.in) != 0 {
......
...@@ -50,7 +50,7 @@ func main() { ...@@ -50,7 +50,7 @@ func main() {
return return
} }
certOut, err := os.Open("cert.pem", os.O_WRONLY|os.O_CREAT, 0644) certOut, err := os.Create("cert.pem")
if err != nil { if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s", err) log.Fatalf("failed to open cert.pem for writing: %s", err)
return return
...@@ -59,7 +59,7 @@ func main() { ...@@ -59,7 +59,7 @@ func main() {
certOut.Close() certOut.Close()
log.Print("written cert.pem\n") log.Print("written cert.pem\n")
keyOut, err := os.Open("key.pem", os.O_WRONLY|os.O_CREAT, 0600) keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0600)
if err != nil { if err != nil {
log.Print("failed to open key.pem for writing:", err) log.Print("failed to open key.pem for writing:", err)
return return
......
...@@ -124,7 +124,16 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os. ...@@ -124,7 +124,16 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
if err != nil { if err != nil {
return return
} }
keyPEMBlock, err := ioutil.ReadFile(keyFile)
if err != nil {
return
}
return X509KeyPair(certPEMBlock, keyPEMBlock)
}
// X509KeyPair parses a public/private key pair from a pair of
// PEM encoded data.
func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Error) {
var certDERBlock *pem.Block var certDERBlock *pem.Block
for { for {
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
...@@ -141,11 +150,6 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os. ...@@ -141,11 +150,6 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
return return
} }
keyPEMBlock, err := ioutil.ReadFile(keyFile)
if err != nil {
return
}
keyDERBlock, _ := pem.Decode(keyPEMBlock) keyDERBlock, _ := pem.Decode(keyPEMBlock)
if keyDERBlock == nil { if keyDERBlock == nil {
err = os.ErrorString("crypto/tls: failed to parse key PEM data") err = os.ErrorString("crypto/tls: failed to parse key PEM data")
......
...@@ -54,20 +54,21 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) { ...@@ -54,20 +54,21 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
return return
} }
key = &rsa.PrivateKey{ key = new(rsa.PrivateKey)
PublicKey: rsa.PublicKey{ key.PublicKey = rsa.PublicKey{
E: priv.E, E: priv.E,
N: new(big.Int).SetBytes(priv.N.Bytes), N: new(big.Int).SetBytes(priv.N.Bytes),
},
D: new(big.Int).SetBytes(priv.D.Bytes),
P: new(big.Int).SetBytes(priv.P.Bytes),
Q: new(big.Int).SetBytes(priv.Q.Bytes),
} }
key.D = new(big.Int).SetBytes(priv.D.Bytes)
key.P = new(big.Int).SetBytes(priv.P.Bytes)
key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
err = key.Validate() err = key.Validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return return
} }
......
...@@ -11,7 +11,6 @@ import ( ...@@ -11,7 +11,6 @@ import (
"crypto/rsa" "crypto/rsa"
"encoding/hex" "encoding/hex"
"encoding/pem" "encoding/pem"
"reflect"
"testing" "testing"
"time" "time"
) )
...@@ -22,7 +21,11 @@ func TestParsePKCS1PrivateKey(t *testing.T) { ...@@ -22,7 +21,11 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Failed to parse private key: %s", err) t.Errorf("Failed to parse private key: %s", err)
} }
if !reflect.DeepEqual(priv, rsaPrivateKey) { if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
priv.D.Cmp(rsaPrivateKey.D) != 0 ||
priv.P.Cmp(rsaPrivateKey.P) != 0 ||
priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey) t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
} }
} }
......
...@@ -144,7 +144,7 @@ func (e *FormatError) String() string { ...@@ -144,7 +144,7 @@ func (e *FormatError) String() string {
// Open opens the named file using os.Open and prepares it for use as an ELF binary. // Open opens the named file using os.Open and prepares it for use as an ELF binary.
func Open(name string) (*File, os.Error) { func Open(name string) (*File, os.Error) {
f, err := os.Open(name, os.O_RDONLY, 0) f, err := os.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -228,7 +228,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -228,7 +228,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
switch f.Class { switch f.Class {
case ELFCLASS32: case ELFCLASS32:
hdr := new(Header32) hdr := new(Header32)
sr.Seek(0, 0) sr.Seek(0, os.SEEK_SET)
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
return nil, err return nil, err
} }
...@@ -243,7 +243,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -243,7 +243,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
shstrndx = int(hdr.Shstrndx) shstrndx = int(hdr.Shstrndx)
case ELFCLASS64: case ELFCLASS64:
hdr := new(Header64) hdr := new(Header64)
sr.Seek(0, 0) sr.Seek(0, os.SEEK_SET)
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
return nil, err return nil, err
} }
...@@ -269,7 +269,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -269,7 +269,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
names := make([]uint32, shnum) names := make([]uint32, shnum)
for i := 0; i < shnum; i++ { for i := 0; i < shnum; i++ {
off := shoff + int64(i)*int64(shentsize) off := shoff + int64(i)*int64(shentsize)
sr.Seek(off, 0) sr.Seek(off, os.SEEK_SET)
s := new(Section) s := new(Section)
switch f.Class { switch f.Class {
case ELFCLASS32: case ELFCLASS32:
......
...@@ -159,7 +159,7 @@ func (e *FormatError) String() string { ...@@ -159,7 +159,7 @@ func (e *FormatError) String() string {
// Open opens the named file using os.Open and prepares it for use as a Mach-O binary. // Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
func Open(name string) (*File, os.Error) { func Open(name string) (*File, os.Error) {
f, err := os.Open(name, os.O_RDONLY, 0) f, err := os.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -87,7 +87,7 @@ func (e *FormatError) String() string { ...@@ -87,7 +87,7 @@ func (e *FormatError) String() string {
// Open opens the named file using os.Open and prepares it for use as a PE binary. // Open opens the named file using os.Open and prepares it for use as a PE binary.
func Open(name string) (*File, os.Error) { func Open(name string) (*File, os.Error) {
f, err := os.Open(name, os.O_RDONLY, 0) f, err := os.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -132,7 +132,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -132,7 +132,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
} else { } else {
base = int64(0) base = int64(0)
} }
sr.Seek(base, 0) sr.Seek(base, os.SEEK_SET)
if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil { if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
return nil, err return nil, err
} }
...@@ -140,7 +140,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -140,7 +140,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
return nil, os.NewError("Invalid PE File Format.") return nil, os.NewError("Invalid PE File Format.")
} }
// get symbol string table // get symbol string table
sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), 0) sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
var l uint32 var l uint32
if err := binary.Read(sr, binary.LittleEndian, &l); err != nil { if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
return nil, err return nil, err
...@@ -149,9 +149,9 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { ...@@ -149,9 +149,9 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil { if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
return nil, err return nil, err
} }
sr.Seek(base, 0) sr.Seek(base, os.SEEK_SET)
binary.Read(sr, binary.LittleEndian, &f.FileHeader) binary.Read(sr, binary.LittleEndian, &f.FileHeader)
sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), 1) //Skip OptionalHeader sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
f.Sections = make([]*Section, f.FileHeader.NumberOfSections) f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
for i := 0; i < int(f.FileHeader.NumberOfSections); i++ { for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
sh := new(SectionHeader32) sh := new(SectionHeader32)
......
...@@ -1184,7 +1184,7 @@ func (p *process) attachThread(tid int) (*thread, os.Error) { ...@@ -1184,7 +1184,7 @@ func (p *process) attachThread(tid int) (*thread, os.Error) {
// attachAllThreads attaches to all threads in a process. // attachAllThreads attaches to all threads in a process.
func (p *process) attachAllThreads() os.Error { func (p *process) attachAllThreads() os.Error {
taskPath := "/proc/" + strconv.Itoa(p.pid) + "/task" taskPath := "/proc/" + strconv.Itoa(p.pid) + "/task"
taskDir, err := os.Open(taskPath, os.O_RDONLY, 0) taskDir, err := os.Open(taskPath)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -2,9 +2,13 @@ ...@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// The exec package runs external commands. // The exec package runs external commands. It wraps os.StartProcess
// to make it easier to remap stdin and stdout, connect I/O with pipes,
// and do other adjustments.
package exec package exec
// BUG(r): This package should be made even easier to use or merged into os.
import ( import (
"os" "os"
"strconv" "strconv"
...@@ -49,7 +53,7 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) { ...@@ -49,7 +53,7 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
if fd == 0 { if fd == 0 {
rw = os.O_RDONLY rw = os.O_RDONLY
} }
f, err := os.Open(os.DevNull, rw, 0) f, err := os.OpenFile(os.DevNull, rw, 0)
return f, nil, err return f, nil, err
case PassThrough: case PassThrough:
switch fd { switch fd {
......
...@@ -53,7 +53,7 @@ func readAuth(displayStr string) (name, data string, err os.Error) { ...@@ -53,7 +53,7 @@ func readAuth(displayStr string) (name, data string, err os.Error) {
} }
fn = home + "/.Xauthority" fn = home + "/.Xauthority"
} }
r, err := os.Open(fn, os.O_RDONLY, 0444) r, err := os.Open(fn)
if err != nil { if err != nil {
return return
} }
......
...@@ -170,7 +170,7 @@ func cmdLoad(args []byte) os.Error { ...@@ -170,7 +170,7 @@ func cmdLoad(args []byte) os.Error {
} }
// Get symbols // Get symbols
f, err := os.Open(fname, os.O_RDONLY, 0) f, err := os.Open(fname)
if err != nil { if err != nil {
tproc.Detach() tproc.Detach()
return err return err
......
...@@ -139,7 +139,17 @@ var fmttests = []struct { ...@@ -139,7 +139,17 @@ var fmttests = []struct {
{"%5s", "abc", " abc"}, {"%5s", "abc", " abc"},
{"%2s", "\u263a", " \u263a"}, {"%2s", "\u263a", " \u263a"},
{"%-5s", "abc", "abc "}, {"%-5s", "abc", "abc "},
{"%-8q", "abc", `"abc" `},
{"%05s", "abc", "00abc"}, {"%05s", "abc", "00abc"},
{"%08q", "abc", `000"abc"`},
{"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
{"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
{"%.5s", "日本語日本語", "日本語日本"},
{"%.5s", []byte("日本語日本語"), "日本語日本"},
{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
{"%.3q", "日本語日本語", `"\u65e5\u672c\u8a9e"`},
{"%.3q", []byte("日本語日本語"), `"\u65e5\u672c\u8a9e"`},
{"%10.1q", "日本語日本語", ` "\u65e5"`},
// integers // integers
{"%d", 12345, "12345"}, {"%d", 12345, "12345"},
......
...@@ -235,13 +235,24 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { ...@@ -235,13 +235,24 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
f.pad(buf[i:]) f.pad(buf[i:])
} }
// fmt_s formats a string. // truncate truncates the string to the specified precision, if present.
func (f *fmt) fmt_s(s string) { func (f *fmt) truncate(s string) string {
if f.precPresent { if f.precPresent && f.prec < utf8.RuneCountInString(s) {
if f.prec < len(s) { n := f.prec
s = s[0:f.prec] for i := range s {
if n == 0 {
s = s[:i]
break
}
n--
} }
} }
return s
}
// fmt_s formats a string.
func (f *fmt) fmt_s(s string) {
s = f.truncate(s)
f.padString(s) f.padString(s)
} }
...@@ -275,6 +286,7 @@ func (f *fmt) fmt_sX(s string) { ...@@ -275,6 +286,7 @@ func (f *fmt) fmt_sX(s string) {
// fmt_q formats a string as a double-quoted, escaped Go string constant. // fmt_q formats a string as a double-quoted, escaped Go string constant.
func (f *fmt) fmt_q(s string) { func (f *fmt) fmt_q(s string) {
s = f.truncate(s)
var quoted string var quoted string
if f.sharp && strconv.CanBackquote(s) { if f.sharp && strconv.CanBackquote(s) {
quoted = "`" + s + "`" quoted = "`" + s + "`"
......
...@@ -520,12 +520,14 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf ...@@ -520,12 +520,14 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf
} }
func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) { func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) {
v, ok := value.(uintptrGetter) var u uintptr
if !ok { // reflect.PtrValue is a uintptrGetter, so failure means it's not a pointer at all. switch value.(type) {
case *reflect.ChanValue, *reflect.FuncValue, *reflect.MapValue, *reflect.PtrValue, *reflect.SliceValue, *reflect.UnsafePointerValue:
u = value.(uintptrGetter).Get()
default:
p.badVerb(verb, field) p.badVerb(verb, field)
return return
} }
u := v.Get()
if goSyntax { if goSyntax {
p.add('(') p.add('(')
p.buf.WriteString(reflect.Typeof(field).String()) p.buf.WriteString(reflect.Typeof(field).String())
...@@ -534,7 +536,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt ...@@ -534,7 +536,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
if u == 0 { if u == 0 {
p.buf.Write(nilBytes) p.buf.Write(nilBytes)
} else { } else {
p.fmt0x64(uint64(v.Get()), true) p.fmt0x64(uint64(u), true)
} }
p.add(')') p.add(')')
} else { } else {
...@@ -811,7 +813,7 @@ BigSwitch: ...@@ -811,7 +813,7 @@ BigSwitch:
break break
} }
p.fmt0x64(uint64(v), true) p.fmt0x64(uint64(v), true)
case uintptrGetter: case *reflect.ChanValue, *reflect.FuncValue, *reflect.UnsafePointerValue:
p.fmtPointer(field, value, verb, goSyntax) p.fmtPointer(field, value, verb, goSyntax)
default: default:
p.unknownType(f) p.unknownType(f)
......
...@@ -183,7 +183,7 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st ...@@ -183,7 +183,7 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st
// error are returned. // error are returned.
// //
func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) { func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
fd, err := os.Open(path, os.O_RDONLY, 0) fd, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -332,7 +332,7 @@ func (p *parser) next() { ...@@ -332,7 +332,7 @@ func (p *parser) next() {
var endline int var endline int
if p.file.Line(p.pos) == line { if p.file.Line(p.pos) == line {
// The comment is on same line as previous token; it // The comment is on same line as the previous token; it
// cannot be a lead comment but may be a line comment. // cannot be a lead comment but may be a line comment.
comment, endline = p.consumeCommentGroup() comment, endline = p.consumeCommentGroup()
if p.file.Line(p.pos) != endline { if p.file.Line(p.pos) != endline {
...@@ -2016,16 +2016,18 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { ...@@ -2016,16 +2016,18 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
} }
ident := p.parseIdent() ident := p.parseIdent()
typ := p.parseType()
p.expectSemi() // call before accessing p.linecomment
// Go spec: The scope of a type identifier declared inside a function begins // Go spec: The scope of a type identifier declared inside a function begins
// at the identifier in the TypeSpec and ends at the end of the innermost // at the identifier in the TypeSpec and ends at the end of the innermost
// containing block. // containing block.
// (Global identifiers are resolved in a separate phase after parsing.) // (Global identifiers are resolved in a separate phase after parsing.)
spec := &ast.TypeSpec{doc, ident, typ, p.lineComment} spec := &ast.TypeSpec{doc, ident, nil, nil}
p.declare(spec, p.topScope, ast.Typ, ident) p.declare(spec, p.topScope, ast.Typ, ident)
spec.Type = p.parseType()
p.expectSemi() // call before accessing p.linecomment
spec.Comment = p.lineComment
return spec return spec
} }
...@@ -2207,6 +2209,9 @@ func (p *parser) parseFile() *ast.File { ...@@ -2207,6 +2209,9 @@ func (p *parser) parseFile() *ast.File {
// Go spec: The package clause is not a declaration; // Go spec: The package clause is not a declaration;
// the package name does not appear in any scope. // the package name does not appear in any scope.
ident := p.parseIdent() ident := p.parseIdent()
if ident.Name == "_" {
p.error(p.pos, "invalid package name _")
}
p.expectSemi() p.expectSemi()
var decls []ast.Decl var decls []ast.Decl
......
...@@ -28,7 +28,7 @@ func pipeErr(err os.Error) io.Reader { ...@@ -28,7 +28,7 @@ func pipeErr(err os.Error) io.Reader {
} }
func readDat(filename string, c chan io.Reader) { func readDat(filename string, c chan io.Reader) {
f, err := os.Open("testdata/webkit/"+filename, os.O_RDONLY, 0600) f, err := os.Open("testdata/webkit/" + filename)
if err != nil { if err != nil {
c <- pipeErr(err) c <- pipeErr(err)
return return
......
...@@ -72,7 +72,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { ...@@ -72,7 +72,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
return return
} }
f, err := os.Open(name, os.O_RDONLY, 0) f, err := os.Open(name)
if err != nil { if err != nil {
// TODO expose actual error? // TODO expose actual error?
NotFound(w, r) NotFound(w, r)
...@@ -113,7 +113,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { ...@@ -113,7 +113,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
// use contents of index.html for directory, if present // use contents of index.html for directory, if present
if d.IsDirectory() { if d.IsDirectory() {
index := name + filepath.FromSlash(indexPage) index := name + filepath.FromSlash(indexPage)
ff, err := os.Open(index, os.O_RDONLY, 0) ff, err := os.Open(index)
if err == nil { if err == nil {
defer ff.Close() defer ff.Close()
dd, err := ff.Stat() dd, err := ff.Stat()
...@@ -134,21 +134,23 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { ...@@ -134,21 +134,23 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
size := d.Size size := d.Size
code := StatusOK code := StatusOK
// use extension to find content type. // If Content-Type isn't set, use the file's extension to find it.
ext := filepath.Ext(name) if w.Header().Get("Content-Type") == "" {
if ctype := mime.TypeByExtension(ext); ctype != "" { ctype := mime.TypeByExtension(filepath.Ext(name))
w.Header().Set("Content-Type", ctype) if ctype == "" {
} else { // read a chunk to decide between utf-8 text and binary
// read first chunk to decide between utf-8 text and binary var buf [1024]byte
var buf [1024]byte n, _ := io.ReadFull(f, buf[:])
n, _ := io.ReadFull(f, buf[:]) b := buf[:n]
b := buf[:n] if isText(b) {
if isText(b) { ctype = "text-plain; charset=utf-8"
w.Header().Set("Content-Type", "text-plain; charset=utf-8") } else {
} else { // generic binary
w.Header().Set("Content-Type", "application/octet-stream") // generic binary ctype = "application/octet-stream"
}
f.Seek(0, os.SEEK_SET) // rewind to output whole file
} }
f.Seek(0, 0) // rewind to output whole file w.Header().Set("Content-Type", ctype)
} }
// handle Content-Range header. // handle Content-Range header.
...@@ -163,7 +165,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { ...@@ -163,7 +165,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
} }
if len(ranges) == 1 { if len(ranges) == 1 {
ra := ranges[0] ra := ranges[0]
if _, err := f.Seek(ra.start, 0); err != nil { if _, err := f.Seek(ra.start, os.SEEK_SET); err != nil {
Error(w, err.String(), StatusRequestedRangeNotSatisfiable) Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
return return
} }
......
...@@ -85,6 +85,30 @@ func TestServeFile(t *testing.T) { ...@@ -85,6 +85,30 @@ func TestServeFile(t *testing.T) {
} }
} }
func TestServeFileContentType(t *testing.T) {
const ctype = "icecream/chocolate"
override := false
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if override {
w.Header().Set("Content-Type", ctype)
}
ServeFile(w, r, "testdata/file")
}))
defer ts.Close()
get := func(want string) {
resp, _, err := Get(ts.URL)
if err != nil {
t.Fatal(err)
}
if h := resp.Header.Get("Content-Type"); h != want {
t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
}
}
get("text-plain; charset=utf-8")
override = true
get(ctype)
}
func getBody(t *testing.T, req Request) (*Response, []byte) { func getBody(t *testing.T, req Request) (*Response, []byte) {
r, err := DefaultClient.Do(&req) r, err := DefaultClient.Do(&req)
if err != nil { if err != nil {
......
...@@ -7,10 +7,13 @@ ...@@ -7,10 +7,13 @@
package httptest package httptest
import ( import (
"crypto/rand"
"crypto/tls"
"fmt" "fmt"
"http" "http"
"os"
"net" "net"
"os"
"time"
) )
// A Server is an HTTP server listening on a system-chosen port on the // A Server is an HTTP server listening on a system-chosen port on the
...@@ -18,6 +21,7 @@ import ( ...@@ -18,6 +21,7 @@ import (
type Server struct { type Server struct {
URL string // base URL of form http://ipaddr:port with no trailing slash URL string // base URL of form http://ipaddr:port with no trailing slash
Listener net.Listener Listener net.Listener
TLS *tls.Config // nil if not using using TLS
} }
// historyListener keeps track of all connections that it's ever // historyListener keeps track of all connections that it's ever
...@@ -35,16 +39,21 @@ func (hs *historyListener) Accept() (c net.Conn, err os.Error) { ...@@ -35,16 +39,21 @@ func (hs *historyListener) Accept() (c net.Conn, err os.Error) {
return return
} }
// NewServer starts and returns a new Server. func newLocalListener() net.Listener {
// The caller should call Close when finished, to shut it down.
func NewServer(handler http.Handler) *Server {
ts := new(Server)
l, err := net.Listen("tcp", "127.0.0.1:0") l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil { if err != nil {
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil { if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err)) panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
} }
} }
return l
}
// NewServer starts and returns a new Server.
// The caller should call Close when finished, to shut it down.
func NewServer(handler http.Handler) *Server {
ts := new(Server)
l := newLocalListener()
ts.Listener = &historyListener{l, make([]net.Conn, 0)} ts.Listener = &historyListener{l, make([]net.Conn, 0)}
ts.URL = "http://" + l.Addr().String() ts.URL = "http://" + l.Addr().String()
server := &http.Server{Handler: handler} server := &http.Server{Handler: handler}
...@@ -52,6 +61,32 @@ func NewServer(handler http.Handler) *Server { ...@@ -52,6 +61,32 @@ func NewServer(handler http.Handler) *Server {
return ts return ts
} }
// NewTLSServer starts and returns a new Server using TLS.
// The caller should call Close when finished, to shut it down.
func NewTLSServer(handler http.Handler) *Server {
l := newLocalListener()
ts := new(Server)
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
if err != nil {
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
}
ts.TLS = &tls.Config{
Rand: rand.Reader,
Time: time.Seconds,
NextProtos: []string{"http/1.1"},
Certificates: []tls.Certificate{cert},
}
tlsListener := tls.NewListener(l, ts.TLS)
ts.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
ts.URL = "https://" + l.Addr().String()
server := &http.Server{Handler: handler}
go server.Serve(ts.Listener)
return ts
}
// Close shuts down the server. // Close shuts down the server.
func (s *Server) Close() { func (s *Server) Close() {
s.Listener.Close() s.Listener.Close()
...@@ -68,3 +103,34 @@ func (s *Server) CloseClientConnections() { ...@@ -68,3 +103,34 @@ func (s *Server) CloseClientConnections() {
conn.Close() conn.Close()
} }
} }
// localhostCert is a PEM-encoded TLS cert with SAN DNS names
// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
// of ASN.1 time).
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBwTCCASugAwIBAgIBADALBgkqhkiG9w0BAQUwADAeFw0xMTAzMzEyMDI1MDda
Fw00OTEyMzEyMzU5NTlaMAAwggCdMAsGCSqGSIb3DQEBAQOCAIwAMIIAhwKCAIB6
oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZLKq2sM3gRaimsktIw
nNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0SjdZ7vTPnFDPNsHGe
KBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBA6NPME0wDgYDVR0PAQH/
BAQDAgCgMA0GA1UdDgQGBAQBAgMEMA8GA1UdIwQIMAaABAECAwQwGwYDVR0RBBQw
EoIJMTI3LjAuMC4xggVbOjoxXTALBgkqhkiG9w0BAQUDggCBAHC3gbdvc44vs+wD
g2kONiENnx8WKc0UTGg/TOXS3gaRb+CUIQtHWja65l8rAfclEovjHgZ7gx8brO0W
JuC6p3MUAKsgOssIrrRIx2rpnfcmFVMzguCmrMNVmKUAalw18Yp0F72xYAIitVQl
kJrLdIhBajcJRYu/YGltHQRaXuVt
-----END CERTIFICATE-----
`)
// localhostKey is the private key for localhostCert.
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIBkgIBAQKCAIB6oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZL
Kq2sM3gRaimsktIwnNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0S
jdZ7vTPnFDPNsHGeKBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBAwKC
AIBRwh7Bil5Z8cYpZZv7jdQxDvbim7Z7ocRdeDmzZuF2I9RW04QyHHPIIlALnBvI
YeF1veASz1gEFGUjzmbUGqKYSbCoTzXoev+F4bmbRxcX9sOmtslqvhMSHRSzA5NH
aDVI3Hn4wvBVD8gePu8ACWqvPGbCiql11OKCMfjlPn2uuwJAx/24/F5DjXZ6hQQ7
HxScOxKrpx5WnA9r1wZTltOTZkhRRzuLc21WJeE3M15QUdWi3zZxCKRFoth65HEs
jy9YHQJAnPueRI44tz79b5QqVbeaOMUr7ZCb1Kp0uo6G+ANPLdlfliAupwij2eIz
mHRJOWk0jBtXfRft1McH2H51CpXAyw==
-----END RSA PRIVATE KEY-----
`)
...@@ -164,6 +164,28 @@ var respTests = []respTest{ ...@@ -164,6 +164,28 @@ var respTests = []respTest{
"Body here\n", "Body here\n",
}, },
// Chunked response in response to a HEAD request (the "chunked" should
// be ignored, as HEAD responses never have bodies)
{
"HTTP/1.0 200 OK\r\n" +
"Transfer-Encoding: chunked\r\n" +
"\r\n",
Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
RequestMethod: "HEAD",
Header: Header{},
Close: true,
ContentLength: 0,
},
"",
},
// Status line without a Reason-Phrase, but trailing space. // Status line without a Reason-Phrase, but trailing space.
// (permitted by RFC 2616) // (permitted by RFC 2616)
{ {
......
...@@ -507,3 +507,30 @@ func TestHeadResponses(t *testing.T) { ...@@ -507,3 +507,30 @@ func TestHeadResponses(t *testing.T) {
t.Errorf("got unexpected body %q", string(body)) t.Errorf("got unexpected body %q", string(body))
} }
} }
func TestTLSServer(t *testing.T) {
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "tls=%v", r.TLS != nil)
}))
defer ts.Close()
if !strings.HasPrefix(ts.URL, "https://") {
t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
}
res, _, err := Get(ts.URL)
if err != nil {
t.Error(err)
}
if res == nil {
t.Fatalf("got nil Response")
}
if res.Body == nil {
t.Fatalf("got nil Response.Body")
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Error(err)
}
if e, g := "tls=true", string(body); e != g {
t.Errorf("expected body %q; got %q", e, g)
}
}
...@@ -215,7 +215,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { ...@@ -215,7 +215,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
} }
// Transfer encoding, content length // Transfer encoding, content length
t.TransferEncoding, err = fixTransferEncoding(t.Header) t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
if err != nil { if err != nil {
return err return err
} }
...@@ -289,13 +289,20 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { ...@@ -289,13 +289,20 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" } func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
// Sanitize transfer encoding // Sanitize transfer encoding
func fixTransferEncoding(header Header) ([]string, os.Error) { func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Error) {
raw, present := header["Transfer-Encoding"] raw, present := header["Transfer-Encoding"]
if !present { if !present {
return nil, nil return nil, nil
} }
header["Transfer-Encoding"] = nil, false header["Transfer-Encoding"] = nil, false
// Head responses have no bodies, so the transfer encoding
// should be ignored.
if requestMethod == "HEAD" {
return nil, nil
}
encodings := strings.Split(raw[0], ",", -1) encodings := strings.Split(raw[0], ",", -1)
te := make([]string, 0, len(encodings)) te := make([]string, 0, len(encodings))
// TODO: Even though we only support "identity" and "chunked" // TODO: Even though we only support "identity" and "chunked"
......
...@@ -24,6 +24,10 @@ import ( ...@@ -24,6 +24,10 @@ import (
// environment variables. // environment variables.
var DefaultTransport RoundTripper = &Transport{} var DefaultTransport RoundTripper = &Transport{}
// DefaultMaxIdleConnsPerHost is the default value of Transport's
// MaxIdleConnsPerHost.
const DefaultMaxIdleConnsPerHost = 2
// Transport is an implementation of RoundTripper that supports http, // Transport is an implementation of RoundTripper that supports http,
// https, and http proxies (for either http or https with CONNECT). // https, and http proxies (for either http or https with CONNECT).
// Transport can also cache connections for future re-use. // Transport can also cache connections for future re-use.
...@@ -31,11 +35,17 @@ type Transport struct { ...@@ -31,11 +35,17 @@ type Transport struct {
lk sync.Mutex lk sync.Mutex
idleConn map[string][]*persistConn idleConn map[string][]*persistConn
// TODO: tunables on max cached connections (total, per-server), duration // TODO: tunable on global max cached connections
// TODO: tunable on timeout on cached connections
// TODO: optional pipelining // TODO: optional pipelining
IgnoreEnvironment bool // don't look at environment variables for proxy configuration IgnoreEnvironment bool // don't look at environment variables for proxy configuration
DisableKeepAlives bool DisableKeepAlives bool
// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
// (keep-alive) to keep to keep per-host. If zero,
// DefaultMaxIdleConnsPerHost is used.
MaxIdleConnsPerHost int
} }
// RoundTrip implements the RoundTripper interface. // RoundTrip implements the RoundTripper interface.
...@@ -147,7 +157,7 @@ func (cm *connectMethod) proxyAuth() string { ...@@ -147,7 +157,7 @@ func (cm *connectMethod) proxyAuth() string {
func (t *Transport) putIdleConn(pconn *persistConn) { func (t *Transport) putIdleConn(pconn *persistConn) {
t.lk.Lock() t.lk.Lock()
defer t.lk.Unlock() defer t.lk.Unlock()
if t.DisableKeepAlives { if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
pconn.close() pconn.close()
return return
} }
...@@ -155,6 +165,14 @@ func (t *Transport) putIdleConn(pconn *persistConn) { ...@@ -155,6 +165,14 @@ func (t *Transport) putIdleConn(pconn *persistConn) {
return return
} }
key := pconn.cacheKey key := pconn.cacheKey
max := t.MaxIdleConnsPerHost
if max == 0 {
max = DefaultMaxIdleConnsPerHost
}
if len(t.idleConn[key]) >= max {
pconn.close()
return
}
t.idleConn[key] = append(t.idleConn[key], pconn) t.idleConn[key] = append(t.idleConn[key], pconn)
} }
...@@ -406,24 +424,37 @@ func (pc *persistConn) readLoop() { ...@@ -406,24 +424,37 @@ func (pc *persistConn) readLoop() {
rc := <-pc.reqch rc := <-pc.reqch
resp, err := pc.cc.Read(rc.req) resp, err := pc.cc.Read(rc.req)
if err == nil && !rc.req.Close {
pc.t.putIdleConn(pc)
}
if err == ErrPersistEOF { if err == ErrPersistEOF {
// Succeeded, but we can't send any more // Succeeded, but we can't send any more
// persistent connections on this again. We // persistent connections on this again. We
// hide this error to upstream callers. // hide this error to upstream callers.
alive = false alive = false
err = nil err = nil
} else if err != nil { } else if err != nil || rc.req.Close {
alive = false alive = false
} }
hasBody := resp != nil && resp.ContentLength != 0
var waitForBodyRead chan bool
if alive {
if hasBody {
waitForBodyRead = make(chan bool)
resp.Body.(*bodyEOFSignal).fn = func() {
pc.t.putIdleConn(pc)
waitForBodyRead <- true
}
} else {
pc.t.putIdleConn(pc)
}
}
rc.ch <- responseAndError{resp, err} rc.ch <- responseAndError{resp, err}
// Wait for the just-returned response body to be fully consumed // Wait for the just-returned response body to be fully consumed
// before we race and peek on the underlying bufio reader. // before we race and peek on the underlying bufio reader.
if alive { if waitForBodyRead != nil {
<-resp.Body.(*bodyEOFSignal).ch <-waitForBodyRead
} }
} }
} }
...@@ -494,34 +525,34 @@ func responseIsKeepAlive(res *Response) bool { ...@@ -494,34 +525,34 @@ func responseIsKeepAlive(res *Response) bool {
// the response body with a bodyEOFSignal-wrapped version. // the response body with a bodyEOFSignal-wrapped version.
func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) { func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
resp, err = ReadResponse(r, requestMethod) resp, err = ReadResponse(r, requestMethod)
if err == nil { if err == nil && resp.ContentLength != 0 {
resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false} resp.Body = &bodyEOFSignal{resp.Body, nil}
} }
return return
} }
// bodyEOFSignal wraps a ReadCloser but sends on ch once once // bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
// the wrapped ReadCloser is fully consumed (including on Close) // once, right before the final Read() or Close() call returns, but after
// EOF has been seen.
type bodyEOFSignal struct { type bodyEOFSignal struct {
body io.ReadCloser body io.ReadCloser
ch chan bool fn func()
done bool
} }
func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) { func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
n, err = es.body.Read(p) n, err = es.body.Read(p)
if err == os.EOF && !es.done { if err == os.EOF && es.fn != nil {
es.ch <- true es.fn()
es.done = true es.fn = nil
} }
return return
} }
func (es *bodyEOFSignal) Close() (err os.Error) { func (es *bodyEOFSignal) Close() (err os.Error) {
err = es.body.Close() err = es.body.Close()
if err == nil && !es.done { if err == nil && es.fn != nil {
es.ch <- true es.fn()
es.done = true es.fn = nil
} }
return return
} }
...@@ -85,6 +85,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) { ...@@ -85,6 +85,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
} }
body, err := ioutil.ReadAll(res.Body) body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil { if err != nil {
t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
} }
...@@ -154,9 +155,11 @@ func TestTransportIdleCacheKeys(t *testing.T) { ...@@ -154,9 +155,11 @@ func TestTransportIdleCacheKeys(t *testing.T) {
t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
} }
if _, _, err := c.Get(ts.URL); err != nil { resp, _, err := c.Get(ts.URL)
if err != nil {
t.Error(err) t.Error(err)
} }
ioutil.ReadAll(resp.Body)
keys := tr.IdleConnKeysForTesting() keys := tr.IdleConnKeysForTesting()
if e, g := 1, len(keys); e != g { if e, g := 1, len(keys); e != g {
...@@ -164,7 +167,7 @@ func TestTransportIdleCacheKeys(t *testing.T) { ...@@ -164,7 +167,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
} }
if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e { if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
t.Logf("Expected idle cache key %q; got %q", e, keys[0]) t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
} }
tr.CloseIdleConnections() tr.CloseIdleConnections()
...@@ -173,6 +176,62 @@ func TestTransportIdleCacheKeys(t *testing.T) { ...@@ -173,6 +176,62 @@ func TestTransportIdleCacheKeys(t *testing.T) {
} }
} }
func TestTransportMaxPerHostIdleConns(t *testing.T) {
ch := make(chan string)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "%s", <-ch)
}))
defer ts.Close()
maxIdleConns := 2
tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
c := &Client{Transport: tr}
// Start 3 outstanding requests (will hang until we write to
// ch)
donech := make(chan bool)
doReq := func() {
resp, _, err := c.Get(ts.URL)
if err != nil {
t.Error(err)
}
ioutil.ReadAll(resp.Body)
donech <- true
}
go doReq()
go doReq()
go doReq()
if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
}
ch <- "res1"
<-donech
keys := tr.IdleConnKeysForTesting()
if e, g := 1, len(keys); e != g {
t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
}
cacheKey := "|http|" + ts.Listener.Addr().String()
if keys[0] != cacheKey {
t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
}
if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
t.Errorf("after first response, expected %d idle conns; got %d", e, g)
}
ch <- "res2"
<-donech
if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
t.Errorf("after second response, expected %d idle conns; got %d", e, g)
}
ch <- "res3"
<-donech
if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
}
}
func TestTransportServerClosingUnexpectedly(t *testing.T) { func TestTransportServerClosingUnexpectedly(t *testing.T) {
ts := httptest.NewServer(hostPortHandler) ts := httptest.NewServer(hostPortHandler)
defer ts.Close() defer ts.Close()
...@@ -209,6 +268,63 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) { ...@@ -209,6 +268,63 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
} }
} }
// TestTransportHeadResponses verifies that we deal with Content-Lengths
// with no bodies properly
func TestTransportHeadResponses(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Method != "HEAD" {
panic("expected HEAD; got " + r.Method)
}
w.Header().Set("Content-Length", "123")
w.WriteHeader(200)
}))
defer ts.Close()
tr := &Transport{DisableKeepAlives: false}
c := &Client{Transport: tr}
for i := 0; i < 2; i++ {
res, err := c.Head(ts.URL)
if err != nil {
t.Errorf("error on loop %d: %v", i, err)
}
if e, g := "123", res.Header.Get("Content-Length"); e != g {
t.Errorf("loop %d: expected Content-Length header of %q, got %q", e, g)
}
if e, g := int64(0), res.ContentLength; e != g {
t.Errorf("loop %d: expected res.ContentLength of %v, got %v", e, g)
}
}
}
// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
// on responses to HEAD requests.
func TestTransportHeadChunkedResponse(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Method != "HEAD" {
panic("expected HEAD; got " + r.Method)
}
w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
w.Header().Set("x-client-ipport", r.RemoteAddr)
w.WriteHeader(200)
}))
defer ts.Close()
tr := &Transport{DisableKeepAlives: false}
c := &Client{Transport: tr}
res1, err := c.Head(ts.URL)
if err != nil {
t.Fatalf("request 1 error: %v", err)
}
res2, err := c.Head(ts.URL)
if err != nil {
t.Fatalf("request 2 error: %v", err)
}
if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
}
}
func TestTransportNilURL(t *testing.T) { func TestTransportNilURL(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "Hi") fmt.Fprintf(w, "Hi")
......
...@@ -213,8 +213,8 @@ func urlEscape(s string, mode encoding) string { ...@@ -213,8 +213,8 @@ func urlEscape(s string, mode encoding) string {
j++ j++
case shouldEscape(c, mode): case shouldEscape(c, mode):
t[j] = '%' t[j] = '%'
t[j+1] = "0123456789abcdef"[c>>4] t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789abcdef"[c&15] t[j+2] = "0123456789ABCDEF"[c&15]
j += 3 j += 3
default: default:
t[j] = s[i] t[j] = s[i]
......
...@@ -490,7 +490,7 @@ var escapeTests = []URLEscapeTest{ ...@@ -490,7 +490,7 @@ var escapeTests = []URLEscapeTest{
}, },
{ {
" ?&=#+%!<>#\"{}|\\^[]`☺\t", " ?&=#+%!<>#\"{}|\\^[]`☺\t",
"+%3f%26%3d%23%2b%25!%3c%3e%23%22%7b%7d%7c%5c%5e%5b%5d%60%e2%98%ba%09", "+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
nil, nil,
}, },
} }
...@@ -519,7 +519,7 @@ type UserinfoTest struct { ...@@ -519,7 +519,7 @@ type UserinfoTest struct {
var userinfoTests = []UserinfoTest{ var userinfoTests = []UserinfoTest{
{"user", "password", "user:password"}, {"user", "password", "user:password"},
{"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./", {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
"foo%3abar:~!%40%23$%25%5e&*()_+%7b%7d%7c%5b%5d%5c-=%60%3a;'%22%3c%3e?,.%2f"}, "foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
} }
func TestEscapeUserinfo(t *testing.T) { func TestEscapeUserinfo(t *testing.T) {
......
...@@ -34,7 +34,7 @@ var imageTests = []imageTest{ ...@@ -34,7 +34,7 @@ var imageTests = []imageTest{
} }
func decode(filename string) (image.Image, string, os.Error) { func decode(filename string) (image.Image, string, os.Error) {
f, err := os.Open(filename, os.O_RDONLY, 0400) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
......
...@@ -41,7 +41,7 @@ var filenamesShort = []string{ ...@@ -41,7 +41,7 @@ var filenamesShort = []string{
} }
func readPng(filename string) (image.Image, os.Error) { func readPng(filename string) (image.Image, os.Error) {
f, err := os.Open(filename, os.O_RDONLY, 0444) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -191,7 +191,7 @@ func TestReader(t *testing.T) { ...@@ -191,7 +191,7 @@ func TestReader(t *testing.T) {
defer piper.Close() defer piper.Close()
// Read the .sng file. // Read the .sng file.
sf, err := os.Open("testdata/pngsuite/"+fn+".sng", os.O_RDONLY, 0444) sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
if err != nil { if err != nil {
t.Error(fn, err) t.Error(fn, err)
continue continue
......
...@@ -28,7 +28,7 @@ func ReadAll(r io.Reader) ([]byte, os.Error) { ...@@ -28,7 +28,7 @@ func ReadAll(r io.Reader) ([]byte, os.Error) {
// ReadFile reads the file named by filename and returns the contents. // ReadFile reads the file named by filename and returns the contents.
func ReadFile(filename string) ([]byte, os.Error) { func ReadFile(filename string) ([]byte, os.Error) {
f, err := os.Open(filename, os.O_RDONLY, 0) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -52,7 +52,7 @@ func ReadFile(filename string) ([]byte, os.Error) { ...@@ -52,7 +52,7 @@ func ReadFile(filename string) ([]byte, os.Error) {
// If the file does not exist, WriteFile creates it with permissions perm; // If the file does not exist, WriteFile creates it with permissions perm;
// otherwise WriteFile truncates it before writing. // otherwise WriteFile truncates it before writing.
func WriteFile(filename string, data []byte, perm uint32) os.Error { func WriteFile(filename string, data []byte, perm uint32) os.Error {
f, err := os.Open(filename, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, perm) f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil { if err != nil {
return err return err
} }
...@@ -74,7 +74,7 @@ func (f fileInfoList) Swap(i, j int) { f[i], f[j] = f[j], f[i] } ...@@ -74,7 +74,7 @@ func (f fileInfoList) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
// ReadDir reads the directory named by dirname and returns // ReadDir reads the directory named by dirname and returns
// a list of sorted directory entries. // a list of sorted directory entries.
func ReadDir(dirname string) ([]*os.FileInfo, os.Error) { func ReadDir(dirname string) ([]*os.FileInfo, os.Error) {
f, err := os.Open(dirname, os.O_RDONLY, 0) f, err := os.Open(dirname)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -48,7 +48,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) { ...@@ -48,7 +48,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) {
nconflict := 0 nconflict := 0
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix()) name := filepath.Join(dir, prefix+nextSuffix())
f, err = os.Open(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST { if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST {
if nconflict++; nconflict > 10 { if nconflict++; nconflict > 10 {
rand = reseed() rand = reseed()
......
...@@ -28,11 +28,12 @@ const ( ...@@ -28,11 +28,12 @@ const (
// order they appear (the order listed here) or the format they present (as // order they appear (the order listed here) or the format they present (as
// described in the comments). A colon appears after these items: // described in the comments). A colon appears after these items:
// 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message // 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // the date: 2009/0123 Ldate = 1 << iota // the date: 2009/0123
Ltime // the time: 01:23:23 Ltime // the time: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23 Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LstdFlags = Ldate | Ltime // initial values for the standard logger
) )
// A Logger represents an active logging object that generates lines of // A Logger represents an active logging object that generates lines of
...@@ -40,10 +41,11 @@ const ( ...@@ -40,10 +41,11 @@ const (
// the Writer's Write method. A Logger can be used simultaneously from // the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer. // multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct { type Logger struct {
mu sync.Mutex // ensures atomic writes prefix string // prefix to write at beginning of each line
out io.Writer // destination for output flag int // properties
prefix string // prefix to write at beginning of each line mu sync.Mutex // ensures atomic writes; protects the following fields
flag int // properties out io.Writer // destination for output
buf bytes.Buffer // for accumulating text to write
} }
// New creates a new Logger. The out variable sets the // New creates a new Logger. The out variable sets the
...@@ -54,7 +56,7 @@ func New(out io.Writer, prefix string, flag int) *Logger { ...@@ -54,7 +56,7 @@ func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, flag: flag} return &Logger{out: out, prefix: prefix, flag: flag}
} }
var std = New(os.Stderr, "", Ldate|Ltime) var std = New(os.Stderr, "", LstdFlags)
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
// Knows the buffer has capacity. // Knows the buffer has capacity.
...@@ -81,7 +83,7 @@ func itoa(buf *bytes.Buffer, i int, wid int) { ...@@ -81,7 +83,7 @@ func itoa(buf *bytes.Buffer, i int, wid int) {
} }
} }
func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int) {
buf.WriteString(l.prefix) buf.WriteString(l.prefix)
if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 { if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
t := time.SecondsToLocalTime(ns / 1e9) t := time.SecondsToLocalTime(ns / 1e9)
...@@ -107,21 +109,15 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { ...@@ -107,21 +109,15 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
} }
} }
if l.flag&(Lshortfile|Llongfile) != 0 { if l.flag&(Lshortfile|Llongfile) != 0 {
_, file, line, ok := runtime.Caller(calldepth) if l.flag&Lshortfile != 0 {
if ok { short := file
if l.flag&Lshortfile != 0 { for i := len(file) - 1; i > 0; i-- {
short := file if file[i] == '/' {
for i := len(file) - 1; i > 0; i-- { short = file[i+1:]
if file[i] == '/' { break
short = file[i+1:]
break
}
} }
file = short
} }
} else { file = short
file = "???"
line = 0
} }
buf.WriteString(file) buf.WriteString(file)
buf.WriteByte(':') buf.WriteByte(':')
...@@ -138,15 +134,26 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { ...@@ -138,15 +134,26 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
// paths it will be 2. // paths it will be 2.
func (l *Logger) Output(calldepth int, s string) os.Error { func (l *Logger) Output(calldepth int, s string) os.Error {
now := time.Nanoseconds() // get this early. now := time.Nanoseconds() // get this early.
buf := new(bytes.Buffer) // get caller info (if required) before locking - it's expensive.
l.formatHeader(buf, now, calldepth+1) var file string
buf.WriteString(s) var line int
if len(s) > 0 && s[len(s)-1] != '\n' { if l.flag&(Lshortfile|Llongfile) != 0 {
buf.WriteByte('\n') var ok bool
_, file, line, ok = runtime.Caller(calldepth)
if !ok {
file = "???"
line = 0
}
} }
l.mu.Lock() l.mu.Lock()
defer l.mu.Unlock() defer l.mu.Unlock()
_, err := l.out.Write(buf.Bytes()) l.buf.Reset()
l.formatHeader(&l.buf, now, file, line)
l.buf.WriteString(s)
if len(s) > 0 && s[len(s)-1] != '\n' {
l.buf.WriteByte('\n')
}
_, err := l.out.Write(l.buf.Bytes())
return err return err
} }
...@@ -203,19 +210,49 @@ func (l *Logger) Panicln(v ...interface{}) { ...@@ -203,19 +210,49 @@ func (l *Logger) Panicln(v ...interface{}) {
panic(s) panic(s)
} }
// Flags returns the output flags for the logger.
func (l *Logger) Flags() int {
return l.flag
}
// SetFlags sets the output flags for the logger.
func (l *Logger) SetFlags(flag int) {
l.flag = flag
}
// Prefix returns the output prefix for the logger.
func (l *Logger) Prefix() string {
return l.prefix
}
// SetPrefix sets the output prefix for the logger.
func (l *Logger) SetPrefix(prefix string) {
l.prefix = prefix
}
// SetOutput sets the output destination for the standard logger. // SetOutput sets the output destination for the standard logger.
func SetOutput(w io.Writer) { func SetOutput(w io.Writer) {
std.out = w std.out = w
} }
// Flags returns the output flags for the standard logger.
func Flags() int {
return std.Flags()
}
// SetFlags sets the output flags for the standard logger. // SetFlags sets the output flags for the standard logger.
func SetFlags(flag int) { func SetFlags(flag int) {
std.flag = flag std.SetFlags(flag)
}
// Prefix returns the output prefix for the standard logger.
func Prefix() string {
return std.Prefix()
} }
// SetPrefix sets the output prefix for the standard logger. // SetPrefix sets the output prefix for the standard logger.
func SetPrefix(prefix string) { func SetPrefix(prefix string) {
std.prefix = prefix std.SetPrefix(prefix)
} }
// These functions write to the standard logger. // These functions write to the standard logger.
......
...@@ -84,3 +84,36 @@ func TestOutput(t *testing.T) { ...@@ -84,3 +84,36 @@ func TestOutput(t *testing.T) {
t.Errorf("log output should match %q is %q", expect, b.String()) t.Errorf("log output should match %q is %q", expect, b.String())
} }
} }
func TestFlagAndPrefixSetting(t *testing.T) {
var b bytes.Buffer
l := New(&b, "Test:", LstdFlags)
f := l.Flags()
if f != LstdFlags {
t.Errorf("Flags 1: expected %x got %x", LstdFlags, f)
}
l.SetFlags(f | Lmicroseconds)
f = l.Flags()
if f != LstdFlags|Lmicroseconds {
t.Errorf("Flags 2: expected %x got %x", LstdFlags|Lmicroseconds, f)
}
p := l.Prefix()
if p != "Test:" {
t.Errorf(`Prefix: expected "Test:" got %q`, p)
}
l.SetPrefix("Reality:")
p = l.Prefix()
if p != "Reality:" {
t.Errorf(`Prefix: expected "Reality:" got %q`, p)
}
// Verify a log message looks right, with our prefix and microseconds present.
l.Print("hello")
pattern := "^Reality:" + Rdate + " " + Rtime + Rmicroseconds + " hello\n"
matched, err := regexp.Match(pattern, b.Bytes())
if err != nil {
t.Fatalf("pattern %q did not compile: %s", pattern, err)
}
if !matched {
t.Error("message did not match pattern")
}
}
...@@ -33,7 +33,7 @@ var mimeTypes = map[string]string{ ...@@ -33,7 +33,7 @@ var mimeTypes = map[string]string{
var mimeLock sync.RWMutex var mimeLock sync.RWMutex
func loadMimeFile(filename string) { func loadMimeFile(filename string) {
f, err := os.Open(filename, os.O_RDONLY, 0666) f, err := os.Open(filename)
if err != nil { if err != nil {
return return
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment