mirror of
https://github.com/golang/go.git
synced 2025-05-15 12:24:37 +00:00
crypto/...: changes to address some of bug 2841.
This change addresses a subset of the issues raised in bug 2841. R=rsc CC=golang-dev https://golang.org/cl/5629044
This commit is contained in:
parent
1f565e7d20
commit
005686ff97
@ -56,7 +56,7 @@ type cbcDecrypter cbc
|
|||||||
|
|
||||||
// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
|
// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
|
||||||
// mode, using the given Block. The length of iv must be the same as the
|
// mode, using the given Block. The length of iv must be the same as the
|
||||||
// Block's block size as must match the iv used to encrypt the data.
|
// Block's block size and must match the iv used to encrypt the data.
|
||||||
func NewCBCDecrypter(b Block, iv []byte) BlockMode {
|
func NewCBCDecrypter(b Block, iv []byte) BlockMode {
|
||||||
return (*cbcDecrypter)(newCBC(b, iv))
|
return (*cbcDecrypter)(newCBC(b, iv))
|
||||||
}
|
}
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
|
|
||||||
|
|
||||||
package cipher
|
|
||||||
|
|
||||||
type ocfbEncrypter struct {
|
|
||||||
b Block
|
|
||||||
fre []byte
|
|
||||||
outUsed int
|
|
||||||
}
|
|
||||||
|
|
||||||
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
|
|
||||||
// performed.
|
|
||||||
type OCFBResyncOption bool
|
|
||||||
|
|
||||||
const (
|
|
||||||
OCFBResync OCFBResyncOption = true
|
|
||||||
OCFBNoResync OCFBResyncOption = false
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewOCFBEncrypter returns a Stream which encrypts data with OpenPGP's cipher
|
|
||||||
// feedback mode using the given Block, and an initial amount of ciphertext.
|
|
||||||
// randData must be random bytes and be the same length as the Block's block
|
|
||||||
// size. Resync determines if the "resynchronization step" from RFC 4880, 13.9
|
|
||||||
// step 7 is performed. Different parts of OpenPGP vary on this point.
|
|
||||||
func NewOCFBEncrypter(block Block, randData []byte, resync OCFBResyncOption) (Stream, []byte) {
|
|
||||||
blockSize := block.BlockSize()
|
|
||||||
if len(randData) != blockSize {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
x := &ocfbEncrypter{
|
|
||||||
b: block,
|
|
||||||
fre: make([]byte, blockSize),
|
|
||||||
outUsed: 0,
|
|
||||||
}
|
|
||||||
prefix := make([]byte, blockSize+2)
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, x.fre)
|
|
||||||
for i := 0; i < blockSize; i++ {
|
|
||||||
prefix[i] = randData[i] ^ x.fre[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, prefix[:blockSize])
|
|
||||||
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
|
|
||||||
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
|
|
||||||
|
|
||||||
if resync {
|
|
||||||
block.Encrypt(x.fre, prefix[2:])
|
|
||||||
} else {
|
|
||||||
x.fre[0] = prefix[blockSize]
|
|
||||||
x.fre[1] = prefix[blockSize+1]
|
|
||||||
x.outUsed = 2
|
|
||||||
}
|
|
||||||
return x, prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
|
|
||||||
for i := 0; i < len(src); i++ {
|
|
||||||
if x.outUsed == len(x.fre) {
|
|
||||||
x.b.Encrypt(x.fre, x.fre)
|
|
||||||
x.outUsed = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
x.fre[x.outUsed] ^= src[i]
|
|
||||||
dst[i] = x.fre[x.outUsed]
|
|
||||||
x.outUsed++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ocfbDecrypter struct {
|
|
||||||
b Block
|
|
||||||
fre []byte
|
|
||||||
outUsed int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
|
|
||||||
// feedback mode using the given Block. Prefix must be the first blockSize + 2
|
|
||||||
// bytes of the ciphertext, where blockSize is the Block's block size. If an
|
|
||||||
// incorrect key is detected then nil is returned. On successful exit,
|
|
||||||
// blockSize+2 bytes of decrypted data are written into prefix. Resync
|
|
||||||
// determines if the "resynchronization step" from RFC 4880, 13.9 step 7 is
|
|
||||||
// performed. Different parts of OpenPGP vary on this point.
|
|
||||||
func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Stream {
|
|
||||||
blockSize := block.BlockSize()
|
|
||||||
if len(prefix) != blockSize+2 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
x := &ocfbDecrypter{
|
|
||||||
b: block,
|
|
||||||
fre: make([]byte, blockSize),
|
|
||||||
outUsed: 0,
|
|
||||||
}
|
|
||||||
prefixCopy := make([]byte, len(prefix))
|
|
||||||
copy(prefixCopy, prefix)
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, x.fre)
|
|
||||||
for i := 0; i < blockSize; i++ {
|
|
||||||
prefixCopy[i] ^= x.fre[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, prefix[:blockSize])
|
|
||||||
prefixCopy[blockSize] ^= x.fre[0]
|
|
||||||
prefixCopy[blockSize+1] ^= x.fre[1]
|
|
||||||
|
|
||||||
if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
|
|
||||||
prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if resync {
|
|
||||||
block.Encrypt(x.fre, prefix[2:])
|
|
||||||
} else {
|
|
||||||
x.fre[0] = prefix[blockSize]
|
|
||||||
x.fre[1] = prefix[blockSize+1]
|
|
||||||
x.outUsed = 2
|
|
||||||
}
|
|
||||||
copy(prefix, prefixCopy)
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
|
|
||||||
for i := 0; i < len(src); i++ {
|
|
||||||
if x.outUsed == len(x.fre) {
|
|
||||||
x.b.Encrypt(x.fre, x.fre)
|
|
||||||
x.outUsed = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
c := src[i]
|
|
||||||
dst[i] = x.fre[x.outUsed] ^ src[i]
|
|
||||||
x.fre[x.outUsed] = c
|
|
||||||
x.outUsed++
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
// 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 cipher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testOCFB(t *testing.T, resync OCFBResyncOption) {
|
|
||||||
block, err := aes.NewCipher(commonKey128)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
|
|
||||||
randData := make([]byte, block.BlockSize())
|
|
||||||
rand.Reader.Read(randData)
|
|
||||||
ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
|
|
||||||
ciphertext := make([]byte, len(plaintext))
|
|
||||||
ocfb.XORKeyStream(ciphertext, plaintext)
|
|
||||||
|
|
||||||
ocfbdec := NewOCFBDecrypter(block, prefix, resync)
|
|
||||||
if ocfbdec == nil {
|
|
||||||
t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
plaintextCopy := make([]byte, len(plaintext))
|
|
||||||
ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
|
|
||||||
|
|
||||||
if !bytes.Equal(plaintextCopy, plaintext) {
|
|
||||||
t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCFB(t *testing.T) {
|
|
||||||
testOCFB(t, OCFBNoResync)
|
|
||||||
testOCFB(t, OCFBResync)
|
|
||||||
}
|
|
@ -14,15 +14,15 @@ import (
|
|||||||
type Hash uint
|
type Hash uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MD4 Hash = 1 + iota // in package crypto/md4
|
MD4 Hash = 1 + iota // import code.google.com/p/go.crypto/md4
|
||||||
MD5 // in package crypto/md5
|
MD5 // import crypto/md5
|
||||||
SHA1 // in package crypto/sha1
|
SHA1 // import crypto/sha1
|
||||||
SHA224 // in package crypto/sha256
|
SHA224 // import crypto/sha256
|
||||||
SHA256 // in package crypto/sha256
|
SHA256 // import crypto/sha256
|
||||||
SHA384 // in package crypto/sha512
|
SHA384 // import crypto/sha512
|
||||||
SHA512 // in package crypto/sha512
|
SHA512 // import crypto/sha512
|
||||||
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
|
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
|
||||||
RIPEMD160 // in package crypto/ripemd160
|
RIPEMD160 // import code.google.com/p/go.crypto/ripemd160
|
||||||
maxHash
|
maxHash
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,8 +50,8 @@ func (h Hash) Size() int {
|
|||||||
|
|
||||||
var hashes = make([]func() hash.Hash, maxHash)
|
var hashes = make([]func() hash.Hash, maxHash)
|
||||||
|
|
||||||
// New returns a new hash.Hash calculating the given hash function. If the
|
// New returns a new hash.Hash calculating the given hash function. New panics
|
||||||
// hash function is not linked into the binary, New returns nil.
|
// if the hash function is not linked into the binary.
|
||||||
func (h Hash) New() hash.Hash {
|
func (h Hash) New() hash.Hash {
|
||||||
if h > 0 && h < maxHash {
|
if h > 0 && h < maxHash {
|
||||||
f := hashes[h]
|
f := hashes[h]
|
||||||
@ -59,7 +59,12 @@ func (h Hash) New() hash.Hash {
|
|||||||
return f()
|
return f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
panic("crypto: requested hash function is unavailable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Available reports whether the given hash function is linked into the binary.
|
||||||
|
func (h Hash) Available() bool {
|
||||||
|
return h < maxHash && hashes[h] != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterHash registers a function that returns a new instance of the given
|
// RegisterHash registers a function that returns a new instance of the given
|
||||||
|
@ -34,13 +34,13 @@ func NewCipher(key []byte) (*Cipher, error) {
|
|||||||
// BlockSize returns the DES block size, 8 bytes.
|
// BlockSize returns the DES block size, 8 bytes.
|
||||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
// Encrypts the 8-byte buffer src and stores the result in dst.
|
// Encrypt encrypts the 8-byte buffer src and stores the result in dst.
|
||||||
// Note that for amounts of data larger than a block,
|
// Note that for amounts of data larger than a block,
|
||||||
// it is not safe to just call Encrypt on successive blocks;
|
// it is not safe to just call Encrypt on successive blocks;
|
||||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||||
func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
|
func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
|
||||||
|
|
||||||
// Decrypts the 8-byte buffer src and stores the result in dst.
|
// Decrypt decrypts the 8-byte buffer src and stores the result in dst.
|
||||||
func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
|
func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
|
||||||
|
|
||||||
// Reset zeros the key data, so that it will no longer
|
// Reset zeros the key data, so that it will no longer
|
||||||
|
@ -65,7 +65,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
|
|||||||
// about the plaintext.
|
// about the plaintext.
|
||||||
// See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
|
// See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
|
||||||
// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
|
// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
|
||||||
// (Crypto '98),
|
// (Crypto '98).
|
||||||
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
|
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
|
||||||
k := (priv.N.BitLen() + 7) / 8
|
k := (priv.N.BitLen() + 7) / 8
|
||||||
if k-(len(key)+3+8) < 0 {
|
if k-(len(key)+3+8) < 0 {
|
||||||
|
@ -412,7 +412,7 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
|
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
|
||||||
// If rand != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
|
// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
|
||||||
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
|
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
|
||||||
k := (priv.N.BitLen() + 7) / 8
|
k := (priv.N.BitLen() + 7) / 8
|
||||||
if len(ciphertext) > k ||
|
if len(ciphertext) > k ||
|
||||||
|
@ -33,16 +33,16 @@ func Client(conn net.Conn, config *Config) *Conn {
|
|||||||
return &Conn{conn: conn, config: config, isClient: true}
|
return &Conn{conn: conn, config: config, isClient: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Listener implements a network listener (net.Listener) for TLS connections.
|
// A listener implements a network listener (net.Listener) for TLS connections.
|
||||||
type Listener struct {
|
type listener struct {
|
||||||
listener net.Listener
|
net.Listener
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept waits for and returns the next incoming TLS connection.
|
// Accept waits for and returns the next incoming TLS connection.
|
||||||
// The returned connection c is a *tls.Conn.
|
// The returned connection c is a *tls.Conn.
|
||||||
func (l *Listener) Accept() (c net.Conn, err error) {
|
func (l *listener) Accept() (c net.Conn, err error) {
|
||||||
c, err = l.listener.Accept()
|
c, err = l.Listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -50,28 +50,22 @@ func (l *Listener) Accept() (c net.Conn, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the listener.
|
|
||||||
func (l *Listener) Close() error { return l.listener.Close() }
|
|
||||||
|
|
||||||
// Addr returns the listener's network address.
|
|
||||||
func (l *Listener) Addr() net.Addr { return l.listener.Addr() }
|
|
||||||
|
|
||||||
// NewListener creates a Listener which accepts connections from an inner
|
// NewListener creates a Listener which accepts connections from an inner
|
||||||
// Listener and wraps each connection with Server.
|
// Listener and wraps each connection with Server.
|
||||||
// The configuration config must be non-nil and must have
|
// The configuration config must be non-nil and must have
|
||||||
// at least one certificate.
|
// at least one certificate.
|
||||||
func NewListener(listener net.Listener, config *Config) (l *Listener) {
|
func NewListener(inner net.Listener, config *Config) net.Listener {
|
||||||
l = new(Listener)
|
l := new(listener)
|
||||||
l.listener = listener
|
l.Listener = inner
|
||||||
l.config = config
|
l.config = config
|
||||||
return
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen creates a TLS listener accepting connections on the
|
// Listen creates a TLS listener accepting connections on the
|
||||||
// given network address using net.Listen.
|
// given network address using net.Listen.
|
||||||
// The configuration config must be non-nil and must have
|
// The configuration config must be non-nil and must have
|
||||||
// at least one certificate.
|
// at least one certificate.
|
||||||
func Listen(network, laddr string, config *Config) (*Listener, error) {
|
func Listen(network, laddr string, config *Config) (net.Listener, error) {
|
||||||
if config == nil || len(config.Certificates) == 0 {
|
if config == nil || len(config.Certificates) == 0 {
|
||||||
return nil, errors.New("tls.Listen: no certificates in configuration")
|
return nil, errors.New("tls.Listen: no certificates in configuration")
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ type RDNSequence []RelativeDistinguishedNameSET
|
|||||||
|
|
||||||
type RelativeDistinguishedNameSET []AttributeTypeAndValue
|
type RelativeDistinguishedNameSET []AttributeTypeAndValue
|
||||||
|
|
||||||
|
// AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
|
||||||
|
// http://tools.ietf.org/html/rfc5280#section-4.1.2.4
|
||||||
type AttributeTypeAndValue struct {
|
type AttributeTypeAndValue struct {
|
||||||
Type asn1.ObjectIdentifier
|
Type asn1.ObjectIdentifier
|
||||||
Value interface{}
|
Value interface{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user