mirror of https://github.com/v2ray/v2ray-core
refine authentication reader
parent
a13a8cffd8
commit
47c3646162
|
@ -2,20 +2,16 @@ package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/errors"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrAuthenticationFailed = errors.New("Authentication failed.")
|
|
||||||
|
|
||||||
errInsufficientBuffer = errors.New("Insufficient buffer.")
|
errInsufficientBuffer = errors.New("Insufficient buffer.")
|
||||||
errInvalidNonce = errors.New("Invalid nonce.")
|
|
||||||
errInvalidLength = errors.New("Invalid buffer size.")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BytesGenerator interface {
|
type BytesGenerator interface {
|
||||||
|
@ -54,7 +50,7 @@ type AEADAuthenticator struct {
|
||||||
func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
|
func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
|
||||||
iv := v.NonceGenerator.Next()
|
iv := v.NonceGenerator.Next()
|
||||||
if len(iv) != v.AEAD.NonceSize() {
|
if len(iv) != v.AEAD.NonceSize() {
|
||||||
return nil, errInvalidNonce
|
return nil, errors.New("Crypto:AEADAuthenticator: Invalid nonce size: ", len(iv))
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalData := v.AdditionalDataGenerator.Next()
|
additionalData := v.AdditionalDataGenerator.Next()
|
||||||
|
@ -64,7 +60,7 @@ func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
|
||||||
func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
|
func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
|
||||||
iv := v.NonceGenerator.Next()
|
iv := v.NonceGenerator.Next()
|
||||||
if len(iv) != v.AEAD.NonceSize() {
|
if len(iv) != v.AEAD.NonceSize() {
|
||||||
return nil, errInvalidNonce
|
return nil, errors.New("Crypto:AEADAuthenticator: Invalid nonce size: ", len(iv))
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalData := v.AdditionalDataGenerator.Next()
|
additionalData := v.AdditionalDataGenerator.Next()
|
||||||
|
@ -100,13 +96,13 @@ func (v *AuthenticationReader) NextChunk() error {
|
||||||
return errInsufficientBuffer
|
return errInsufficientBuffer
|
||||||
}
|
}
|
||||||
if size > readerBufferSize-2 {
|
if size > readerBufferSize-2 {
|
||||||
return errInvalidLength
|
return errors.New("Crypto:AuthenticationReader: Size too large: ", size)
|
||||||
}
|
}
|
||||||
if size == v.auth.Overhead() {
|
if size == v.auth.Overhead() {
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
if size < v.auth.Overhead() {
|
if size < v.auth.Overhead() {
|
||||||
return errors.New("AuthenticationReader: invalid packet size.")
|
return errors.New("AuthenticationReader: invalid packet size:", size)
|
||||||
}
|
}
|
||||||
cipherChunk := v.buffer.BytesRange(2, size+2)
|
cipherChunk := v.buffer.BytesRange(2, size+2)
|
||||||
plainChunk, err := v.auth.Open(cipherChunk[:0], cipherChunk)
|
plainChunk, err := v.auth.Open(cipherChunk[:0], cipherChunk)
|
||||||
|
@ -132,26 +128,26 @@ func (v *AuthenticationReader) CopyChunk(b []byte) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *AuthenticationReader) EnsureChunk() error {
|
func (v *AuthenticationReader) EnsureChunk() error {
|
||||||
|
if v.buffer.IsEmpty() {
|
||||||
|
v.buffer.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := v.NextChunk()
|
err := v.NextChunk()
|
||||||
if err == nil {
|
if err != errInsufficientBuffer {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
if err == errInsufficientBuffer {
|
|
||||||
if v.buffer.IsEmpty() {
|
leftover := v.buffer.Bytes()
|
||||||
v.buffer.Clear()
|
if len(leftover) > 0 {
|
||||||
} else {
|
common.Must(v.buffer.Reset(func(b []byte) (int, error) {
|
||||||
leftover := v.buffer.Bytes()
|
return copy(b, leftover), nil
|
||||||
common.Must(v.buffer.Reset(func(b []byte) (int, error) {
|
}))
|
||||||
return copy(b, leftover), nil
|
}
|
||||||
}))
|
|
||||||
}
|
if err := v.buffer.AppendSupplier(buf.ReadFrom(v.reader)); err != nil {
|
||||||
err = v.buffer.AppendSupplier(buf.ReadFrom(v.reader))
|
return err
|
||||||
if err == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/crypto"
|
. "v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
|
@ -77,10 +79,10 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
||||||
payload := make([]byte, 8*1024)
|
payload := make([]byte, 8*1024)
|
||||||
rand.Read(payload)
|
rand.Read(payload)
|
||||||
|
|
||||||
cache := buf.NewLocal(16 * 1024)
|
|
||||||
iv := make([]byte, 12)
|
iv := make([]byte, 12)
|
||||||
rand.Read(iv)
|
rand.Read(iv)
|
||||||
|
|
||||||
|
cache := buf.NewLocal(16 * 1024)
|
||||||
writer := NewAuthenticationWriter(&AEADAuthenticator{
|
writer := NewAuthenticationWriter(&AEADAuthenticator{
|
||||||
AEAD: aead,
|
AEAD: aead,
|
||||||
NonceGenerator: &StaticBytesGenerator{
|
NonceGenerator: &StaticBytesGenerator{
|
||||||
|
@ -96,13 +98,22 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
||||||
_, err = writer.Write([]byte{})
|
_, err = writer.Write([]byte{})
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
go func() {
|
||||||
|
pw.Write(cache.BytesTo(1024))
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
pw.Write(cache.BytesFrom(1024))
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
pw.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
reader := NewAuthenticationReader(&AEADAuthenticator{
|
reader := NewAuthenticationReader(&AEADAuthenticator{
|
||||||
AEAD: aead,
|
AEAD: aead,
|
||||||
NonceGenerator: &StaticBytesGenerator{
|
NonceGenerator: &StaticBytesGenerator{
|
||||||
Content: iv,
|
Content: iv,
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
||||||
}, cache)
|
}, pr)
|
||||||
|
|
||||||
actualPayload := make([]byte, 7*1024)
|
actualPayload := make([]byte, 7*1024)
|
||||||
nBytes, err = reader.Read(actualPayload)
|
nBytes, err = reader.Read(actualPayload)
|
||||||
|
|
Loading…
Reference in New Issue