Crypto library movement and changes to content helper interfaces
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
committed by
Brandon Lum
parent
bf8804c743
commit
dde436e65b
114
pkg/encryption/blockcipher/blockcipher.go
Normal file
114
pkg/encryption/blockcipher/blockcipher.go
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// LayerCipherType is the ciphertype as specified in the layer metadata
|
||||
type LayerCipherType string
|
||||
|
||||
// TODO: Should be obtained from OCI spec once included
|
||||
const (
|
||||
AESSIVCMAC256 LayerCipherType = "AEAD_AES_SIV_CMAC_STREAM_256"
|
||||
AESSIVCMAC512 LayerCipherType = "AEAD_AES_SIV_CMAC_STREAM_512"
|
||||
CipherTypeOpt string = "type"
|
||||
)
|
||||
|
||||
// LayerBlockCipherOptions includes the information required to encrypt/decrypt
|
||||
// an image
|
||||
type LayerBlockCipherOptions struct {
|
||||
// SymmetricKey represents the symmetric key used for encryption/decryption
|
||||
// This field should be populated by Encrypt/Decrypt calls
|
||||
SymmetricKey []byte `json:"symkey"`
|
||||
|
||||
// Digest is the digest of the original data for verification.
|
||||
// This is NOT populated by Encrypt/Decrypt calls
|
||||
Digest digest.Digest `json:"digest"`
|
||||
|
||||
// CipherOptions contains the cipher metadata used for encryption/decryption
|
||||
// This field should be populated by Encrypt/Decrypt calls
|
||||
CipherOptions map[string][]byte `json:"cipheroptions"`
|
||||
}
|
||||
|
||||
// LayerBlockCipher returns a provider for encrypt/decrypt functionality
|
||||
// for handling the layer data for a specific algorithm
|
||||
type LayerBlockCipher interface {
|
||||
// GenerateKey creates a symmetric key
|
||||
GenerateKey() []byte
|
||||
// Encrypt takes in layer data and returns the ciphertext and relevant LayerBlockCipherOptions
|
||||
Encrypt(layerDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error)
|
||||
// Decrypt takes in layer ciphertext data and returns the plaintext and relevant LayerBlockCipherOptions
|
||||
Decrypt(layerDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error)
|
||||
}
|
||||
|
||||
// LayerBlockCipherHandler is the handler for encrypt/decrypt for layers
|
||||
type LayerBlockCipherHandler struct {
|
||||
cipherMap map[LayerCipherType]LayerBlockCipher
|
||||
}
|
||||
|
||||
// Encrypt is the handler for the layer decryption routine
|
||||
func (h *LayerBlockCipherHandler) Encrypt(plainDataReader io.Reader, typ LayerCipherType) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
|
||||
if c, ok := h.cipherMap[typ]; ok {
|
||||
opt := LayerBlockCipherOptions{
|
||||
SymmetricKey: c.GenerateKey(),
|
||||
}
|
||||
encDataReader, newopt, err := c.Encrypt(plainDataReader, opt)
|
||||
if err == nil {
|
||||
newopt.CipherOptions[CipherTypeOpt] = []byte(typ)
|
||||
}
|
||||
return encDataReader, newopt, err
|
||||
}
|
||||
return nil, LayerBlockCipherOptions{}, errors.Errorf("unsupported cipher type: %s", typ)
|
||||
}
|
||||
|
||||
// Decrypt is the handler for the layer decryption routine
|
||||
func (h *LayerBlockCipherHandler) Decrypt(encDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
typ, ok := opt.CipherOptions[CipherTypeOpt]
|
||||
if !ok {
|
||||
return nil, LayerBlockCipherOptions{}, errors.New("no cipher type provided")
|
||||
}
|
||||
if c, ok := h.cipherMap[LayerCipherType(typ)]; ok {
|
||||
return c.Decrypt(encDataReader, opt)
|
||||
}
|
||||
return nil, LayerBlockCipherOptions{}, errors.Errorf("unsupported cipher type: %s", typ)
|
||||
}
|
||||
|
||||
// NewLayerBlockCipherHandler returns a new default handler
|
||||
func NewLayerBlockCipherHandler() (*LayerBlockCipherHandler, error) {
|
||||
h := LayerBlockCipherHandler{
|
||||
cipherMap: map[LayerCipherType]LayerBlockCipher{},
|
||||
}
|
||||
|
||||
var err error
|
||||
h.cipherMap[AESSIVCMAC256], err = NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to set up Cipher AES-SIV-CMAC-256")
|
||||
}
|
||||
|
||||
h.cipherMap[AESSIVCMAC512], err = NewAESSIVLayerBlockCipher(512)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to set up Cipher AES-SIV-CMAC-512")
|
||||
}
|
||||
|
||||
return &h, nil
|
||||
}
|
||||
194
pkg/encryption/blockcipher/blockcipher_siv.go
Normal file
194
pkg/encryption/blockcipher/blockcipher_siv.go
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
miscreant "github.com/miscreant/miscreant-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// AESSIVLayerBlockCipher implements the AES SIV block cipher
|
||||
type AESSIVLayerBlockCipher struct {
|
||||
keylen int // in bytes
|
||||
reader io.Reader
|
||||
encryptor *miscreant.StreamEncryptor
|
||||
decryptor *miscreant.StreamDecryptor
|
||||
err error // error that occurred during operation
|
||||
eof bool // hit EOF in the input data
|
||||
toread int // how many bytes to read in one chunk
|
||||
inbuffer []byte // input buffer with data from reader
|
||||
inoffset int64 // offset where to read from next
|
||||
outbuffer []byte // output buffer to return to user
|
||||
outoffset int // offset in output buffer
|
||||
outsize int64 // output size
|
||||
}
|
||||
|
||||
type aessivcryptor struct {
|
||||
bc *AESSIVLayerBlockCipher
|
||||
outputReader io.Reader
|
||||
}
|
||||
|
||||
// NewAESSIVLayerBlockCipher returns a new AES SIV block cipher of 256 or 512 bits
|
||||
func NewAESSIVLayerBlockCipher(bits int) (LayerBlockCipher, error) {
|
||||
if bits != 256 && bits != 512 {
|
||||
return nil, errors.New("AES SIV bit count not supported")
|
||||
}
|
||||
return &AESSIVLayerBlockCipher{keylen: bits / 8}, nil
|
||||
}
|
||||
|
||||
func (r *aessivcryptor) Read(p []byte) (int, error) {
|
||||
if r.bc.err != nil {
|
||||
return 0, r.bc.err
|
||||
}
|
||||
|
||||
for {
|
||||
// return data if we have any
|
||||
if r.bc.outbuffer != nil && r.bc.outoffset < len(r.bc.outbuffer) {
|
||||
n := copy(p, r.bc.outbuffer[r.bc.outoffset:])
|
||||
r.bc.outoffset += n
|
||||
|
||||
return n, nil
|
||||
}
|
||||
// no data and hit eof before?
|
||||
if r.bc.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
// read new data; we expect to get r.bc.toread number of bytes
|
||||
// for anything less we assume it's EOF
|
||||
numbytes := 0
|
||||
for numbytes < r.bc.toread {
|
||||
var n int
|
||||
n, r.bc.err = r.bc.reader.Read(r.bc.inbuffer[numbytes:r.bc.toread])
|
||||
numbytes += n
|
||||
if r.bc.err != nil {
|
||||
if r.bc.err == io.EOF {
|
||||
r.bc.eof = true
|
||||
r.bc.err = nil
|
||||
break
|
||||
} else {
|
||||
return 0, r.bc.err
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if numbytes < r.bc.toread {
|
||||
r.bc.eof = true
|
||||
}
|
||||
|
||||
r.bc.inoffset += int64(numbytes)
|
||||
|
||||
// transform the data
|
||||
if r.bc.encryptor != nil {
|
||||
r.bc.outbuffer = r.bc.encryptor.Seal(nil, r.bc.inbuffer[:numbytes], []byte(""), r.bc.eof)
|
||||
} else {
|
||||
r.bc.outbuffer, r.bc.err = r.bc.decryptor.Open(nil, r.bc.inbuffer[:numbytes], []byte(""), r.bc.eof)
|
||||
if r.bc.err != nil {
|
||||
return 0, r.bc.err
|
||||
}
|
||||
}
|
||||
// let reader start from beginning of buffer
|
||||
r.bc.outoffset = 0
|
||||
r.bc.outsize += int64(len(r.bc.outbuffer))
|
||||
}
|
||||
}
|
||||
|
||||
// init initializes an instance
|
||||
func (bc *AESSIVLayerBlockCipher) init(encrypt bool, reader io.Reader, opt LayerBlockCipherOptions) (LayerBlockCipherOptions, error) {
|
||||
var (
|
||||
err error
|
||||
se miscreant.StreamEncryptor
|
||||
)
|
||||
|
||||
bc.reader = reader
|
||||
|
||||
key := opt.SymmetricKey
|
||||
if len(key) != bc.keylen {
|
||||
return LayerBlockCipherOptions{}, fmt.Errorf("invalid key length of %d bytes; need %d bytes", len(key), bc.keylen)
|
||||
}
|
||||
|
||||
nonce := opt.CipherOptions["nonce"]
|
||||
if len(nonce) == 0 {
|
||||
nonce = make([]byte, se.NonceSize())
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return LayerBlockCipherOptions{}, errors.Wrap(err, "unable to generate random nonce")
|
||||
}
|
||||
}
|
||||
|
||||
bc.inbuffer = make([]byte, 1024*1024)
|
||||
bc.toread = len(bc.inbuffer)
|
||||
bc.inoffset = 0
|
||||
bc.outbuffer = nil
|
||||
bc.outoffset = 0
|
||||
bc.eof = false
|
||||
bc.err = nil
|
||||
bc.outsize = 0
|
||||
|
||||
if encrypt {
|
||||
bc.encryptor, err = miscreant.NewStreamEncryptor("AES-SIV", key, nonce)
|
||||
if err != nil {
|
||||
return LayerBlockCipherOptions{}, errors.Wrap(err, "unable to create AES-SIV stream encryptor")
|
||||
}
|
||||
bc.toread -= bc.encryptor.Overhead()
|
||||
bc.decryptor = nil
|
||||
} else {
|
||||
bc.decryptor, err = miscreant.NewStreamDecryptor("AES-SIV", key, nonce)
|
||||
if err != nil {
|
||||
return LayerBlockCipherOptions{}, errors.Wrap(err, "unable to create AES-SIV stream decryptor")
|
||||
}
|
||||
bc.encryptor = nil
|
||||
}
|
||||
|
||||
lbco := LayerBlockCipherOptions{
|
||||
SymmetricKey: key,
|
||||
CipherOptions: map[string][]byte{
|
||||
"nonce": nonce,
|
||||
},
|
||||
}
|
||||
|
||||
return lbco, nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a synmmetric key
|
||||
func (bc *AESSIVLayerBlockCipher) GenerateKey() []byte {
|
||||
return miscreant.GenerateKey(bc.keylen)
|
||||
}
|
||||
|
||||
// Encrypt takes in layer data and returns the ciphertext and relevant LayerBlockCipherOptions
|
||||
func (bc *AESSIVLayerBlockCipher) Encrypt(plainDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
lbco, err := bc.init(true, plainDataReader, opt)
|
||||
if err != nil {
|
||||
return nil, LayerBlockCipherOptions{}, err
|
||||
}
|
||||
|
||||
return &aessivcryptor{bc, nil}, lbco, nil
|
||||
}
|
||||
|
||||
// Decrypt takes in layer ciphertext data and returns the plaintext and relevant LayerBlockCipherOptions
|
||||
func (bc *AESSIVLayerBlockCipher) Decrypt(encDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
lbco, err := bc.init(false, encDataReader, opt)
|
||||
if err != nil {
|
||||
return nil, LayerBlockCipherOptions{}, err
|
||||
}
|
||||
|
||||
return &aessivcryptor{bc, nil}, lbco, nil
|
||||
}
|
||||
163
pkg/encryption/blockcipher/blockcipher_siv_test.go
Normal file
163
pkg/encryption/blockcipher/blockcipher_siv_test.go
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "crypto/sha256"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBlockCipherAesSivCreateValid(t *testing.T) {
|
||||
_, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = NewAESSIVLayerBlockCipher(512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherAesSivCreateInvalid(t *testing.T) {
|
||||
_, err := NewAESSIVLayerBlockCipher(8)
|
||||
if err == nil {
|
||||
t.Fatal("Test should have failed due to invalid cipher size")
|
||||
}
|
||||
_, err = NewAESSIVLayerBlockCipher(255)
|
||||
if err == nil {
|
||||
t.Fatal("Test should have failed due to invalid cipher size")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherAesSivEncryption(t *testing.T) {
|
||||
var (
|
||||
symKey = []byte("01234567890123456789012345678912")
|
||||
opt = LayerBlockCipherOptions{
|
||||
SymmetricKey: symKey,
|
||||
}
|
||||
layerData = []byte("this is some data")
|
||||
)
|
||||
|
||||
bc, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
layerDataReader := bytes.NewReader(layerData)
|
||||
ciphertextReader, lbco, err := bc.Encrypt(layerDataReader, opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use a different instantiated object to indicate an invocation at a diff time
|
||||
bc2, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ciphertext := make([]byte, 1024)
|
||||
encsize, err := ciphertextReader.Read(ciphertext)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ciphertextTestReader := bytes.NewReader(ciphertext[:encsize])
|
||||
|
||||
plaintextReader, _, err := bc2.Decrypt(ciphertextTestReader, lbco)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plaintext := make([]byte, 1024)
|
||||
size, err := plaintextReader.Read(plaintext)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(plaintext[:size]) != string(layerData) {
|
||||
t.Fatalf("expected %q, got %q", layerData, plaintext[:size])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherAesSivEncryptionInvalidKey(t *testing.T) {
|
||||
var (
|
||||
symKey = []byte("01234567890123456789012345678912")
|
||||
opt = LayerBlockCipherOptions{
|
||||
SymmetricKey: symKey,
|
||||
}
|
||||
layerData = []byte("this is some data")
|
||||
)
|
||||
|
||||
bc, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
layerDataReader := bytes.NewReader(layerData)
|
||||
ciphertextReader, lbco, err := bc.Encrypt(layerDataReader, opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use a different instantiated object to indicate an invokation at a diff time
|
||||
bc2, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lbco.SymmetricKey = []byte("aaa34567890123456789012345678912")
|
||||
|
||||
ciphertext := make([]byte, 1024)
|
||||
encsize, err := ciphertextReader.Read(ciphertext)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ciphertextTestReader := bytes.NewReader(ciphertext[:encsize])
|
||||
|
||||
plaintextReader, _, err := bc2.Decrypt(ciphertextTestReader, lbco)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plaintext := make([]byte, 1024)
|
||||
_, err = plaintextReader.Read(plaintext)
|
||||
if err == nil {
|
||||
t.Fatal("Read() should have failed due to wrong key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherAesSivEncryptionInvalidKeyLength(t *testing.T) {
|
||||
var (
|
||||
symKey = []byte("012345")
|
||||
opt = LayerBlockCipherOptions{
|
||||
SymmetricKey: symKey,
|
||||
}
|
||||
layerData = []byte("this is some data")
|
||||
)
|
||||
|
||||
bc, err := NewAESSIVLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
layerDataReader := bytes.NewReader(layerData)
|
||||
_, _, err = bc.Encrypt(layerDataReader, opt)
|
||||
if err == nil {
|
||||
t.Fatal("Test should have failed due to invalid key length")
|
||||
}
|
||||
}
|
||||
115
pkg/encryption/blockcipher/blockcipher_test.go
Normal file
115
pkg/encryption/blockcipher/blockcipher_test.go
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBlockCipherHandlerCreate(t *testing.T) {
|
||||
_, err := NewLayerBlockCipherHandler()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherEncryption(t *testing.T) {
|
||||
var (
|
||||
layerData = []byte("this is some data")
|
||||
)
|
||||
|
||||
h, err := NewLayerBlockCipherHandler()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
layerDataReader := bytes.NewReader(layerData)
|
||||
|
||||
ciphertextReader, lbco, err := h.Encrypt(layerDataReader, AESSIVCMAC256)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ciphertext := make([]byte, 1024)
|
||||
encsize, err := ciphertextReader.Read(ciphertext)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatal("Reading the ciphertext should not have failed")
|
||||
}
|
||||
ciphertextTestReader := bytes.NewReader(ciphertext[:encsize])
|
||||
|
||||
// Use a different instantiated object to indicate an invokation at a diff time
|
||||
plaintextReader, _, err := h.Decrypt(ciphertextTestReader, lbco)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plaintext := make([]byte, 1024)
|
||||
decsize, err := plaintextReader.Read(plaintext)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatal("Read the plaintext should not have failed")
|
||||
}
|
||||
|
||||
if string(plaintext[:decsize]) != string(layerData) {
|
||||
t.Fatal("Decrypted data is incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCipherEncryptionInvalidKey(t *testing.T) {
|
||||
var (
|
||||
layerData = []byte("this is some data")
|
||||
)
|
||||
|
||||
h, err := NewLayerBlockCipherHandler()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
layerDataReader := bytes.NewReader(layerData)
|
||||
|
||||
ciphertextReader, lbco, err := h.Encrypt(layerDataReader, AESSIVCMAC512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use a different instantiated object to indicate an invokation at a diff time
|
||||
bc2, err := NewAESSIVLayerBlockCipher(512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lbco.SymmetricKey = []byte("aaa3456789012345678901234567890123456789012345678901234567890123")
|
||||
|
||||
ciphertext := make([]byte, 1024)
|
||||
encsize, err := ciphertextReader.Read(ciphertext)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ciphertextTestReader := bytes.NewReader(ciphertext[:encsize])
|
||||
|
||||
plaintextReader, _, err := bc2.Decrypt(ciphertextTestReader, lbco)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plaintext := make([]byte, 1024)
|
||||
_, err = plaintextReader.Read(plaintext)
|
||||
if err == nil {
|
||||
t.Fatal("Read() should have failed due to wrong key")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user