216 lines
5.4 KiB
Go
216 lines
5.4 KiB
Go
package envelop
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/didiercrunch/filou/helper"
|
|
)
|
|
|
|
type mockPayload struct {
|
|
MethodsCall []string
|
|
}
|
|
|
|
func newMockPayload() *mockPayload {
|
|
return &mockPayload{make([]string, 0)}
|
|
}
|
|
|
|
func (this *mockPayload) addMethodCall(methodName string) {
|
|
this.MethodsCall = append(this.MethodsCall, methodName)
|
|
}
|
|
|
|
// assert firstToBeCalled is called before secondToBeCalled. Calls can be made
|
|
// between them and defore firstToBeCalled and after secondToBeCalled.
|
|
func (this *mockPayload) assertMethodCallOrder(firstToBeCalled, secondToBeCalled string) error {
|
|
var firstToBeCalledIdx, secondToBeCalledIdx = -1, -1
|
|
for i, name := range this.MethodsCall {
|
|
if firstToBeCalledIdx == -1 && name == firstToBeCalled {
|
|
firstToBeCalledIdx = i
|
|
}
|
|
if secondToBeCalledIdx == -1 && name == secondToBeCalled {
|
|
secondToBeCalledIdx = i
|
|
}
|
|
}
|
|
if firstToBeCalledIdx == -1 {
|
|
return errors.New(firstToBeCalled + " is never called")
|
|
}
|
|
if secondToBeCalledIdx == -1 {
|
|
return errors.New(secondToBeCalled + " is never called")
|
|
}
|
|
if firstToBeCalledIdx >= secondToBeCalledIdx {
|
|
return errors.New(firstToBeCalled + " is called after " + secondToBeCalled)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (this *mockPayload) GetKey() []byte {
|
|
this.addMethodCall("GetKey")
|
|
return []byte{1, 2, 3}
|
|
}
|
|
|
|
func (this *mockPayload) GetHash() []byte {
|
|
this.addMethodCall("GetHash")
|
|
return []byte{10, 9, 8}
|
|
}
|
|
|
|
func (this *mockPayload) GetAlgorithm() string {
|
|
this.addMethodCall("GetAlgorithm")
|
|
symetricEncryptionAlgorithm := "DES"
|
|
return symetricEncryptionAlgorithm
|
|
}
|
|
|
|
func (this *mockPayload) GetMode() string {
|
|
this.addMethodCall("GetMode")
|
|
symetricEncryptionMode := "OFB"
|
|
return symetricEncryptionMode
|
|
}
|
|
|
|
func (this *mockPayload) GetHashMethod() string {
|
|
this.addMethodCall("GetHashMethod")
|
|
theHashMethodUsedInThePayLoad := "SHA1"
|
|
return theHashMethodUsedInThePayLoad
|
|
}
|
|
|
|
func (this *mockPayload) GetPayloadData() (io.Reader, error) {
|
|
this.addMethodCall("GetPayloadData")
|
|
someData := `some data must be here. In reality, the data
|
|
would be the encrypted payload. This will be
|
|
the big chunk of the data.
|
|
`
|
|
return bytes.NewReader([]byte(someData)), nil
|
|
}
|
|
|
|
type mockEncryptor struct{}
|
|
|
|
func (this *mockEncryptor) Encrypt(data []byte) ([]byte, error) {
|
|
// cesar encryption!
|
|
ret := make([]byte, len(data))
|
|
for i, d := range data {
|
|
ret[i] = d + 3 // modulo is implicit
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
type mockSigner struct{}
|
|
|
|
func (this *mockSigner) Sign(data []byte) ([]byte, error) {
|
|
// a slice with the sum of the data plus a "secret" value
|
|
var sum byte = 36
|
|
for _, d := range data {
|
|
sum += d
|
|
}
|
|
return []byte{sum}, nil
|
|
}
|
|
|
|
func TestEncryptKey(t *testing.T) {
|
|
env := &Enveloper{
|
|
publicKeyEncryptor: &mockEncryptor{},
|
|
payload: newMockPayload(),
|
|
}
|
|
if enc, err := env.EncryptKey(); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(enc, []byte{1 + 3, 2 + 3, 3 + 3}) {
|
|
t.Error("bad signature")
|
|
}
|
|
}
|
|
|
|
func TestCreateEnvelopCompletelyEncryptKey(t *testing.T) {
|
|
env := NewEnveloper(&mockEncryptor{}, newMockPayload(), &mockSigner{})
|
|
if err := env.CreateEnvelopCompletely(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !reflect.DeepEqual(env.EncryptedKey, []byte{1 + 3, 2 + 3, 3 + 3}) {
|
|
t.Error("CreateEnvelopCompletely has not encrypted the key")
|
|
}
|
|
}
|
|
|
|
func TestSignPayload(t *testing.T) {
|
|
env := &Enveloper{
|
|
signer: &mockSigner{},
|
|
payload: &mockPayload{},
|
|
}
|
|
if sign, err := env.SignPayload(); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual([]byte{10 + 9 + 8 + 36}, sign) {
|
|
t.Error("bad signature")
|
|
}
|
|
}
|
|
|
|
func TestCreateEnvelopCompletelySignHash(t *testing.T) {
|
|
env := NewEnveloper(&mockEncryptor{}, newMockPayload(), &mockSigner{})
|
|
if err := env.CreateEnvelopCompletely(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !reflect.DeepEqual(env.Signature, []byte{10 + 9 + 8 + 36}) {
|
|
t.Error("CreateEnvelopCompletely has not signature")
|
|
}
|
|
}
|
|
|
|
func TestCreateMetadata(t *testing.T) {
|
|
env := &Enveloper{payload: newMockPayload()}
|
|
exptectedMetaData := &Metadata{
|
|
BlockAlgorithm: "DES",
|
|
BlockMode: "OFB",
|
|
SignatureAlgorithm: "RSAPSS",
|
|
HashMethod: "SHA1",
|
|
}
|
|
|
|
if m := env.CreateMetadata(); !reflect.DeepEqual(m, exptectedMetaData) {
|
|
t.Error("bad meta data")
|
|
}
|
|
}
|
|
|
|
func TestCreateEnvelopCompletelyMetadata(t *testing.T) {
|
|
env := &Enveloper{
|
|
publicKeyEncryptor: &mockEncryptor{},
|
|
payload: newMockPayload(),
|
|
signer: &mockSigner{},
|
|
}
|
|
if err := env.CreateEnvelopCompletely(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if env.Metadata == nil || env.Metadata.HashMethod != "SHA1" {
|
|
t.Error("CreateEnvelopCompletely has not created metadata")
|
|
}
|
|
}
|
|
|
|
func TestWriteToWriter(t *testing.T) {
|
|
env := &Enveloper{
|
|
payload: newMockPayload(),
|
|
signer: &mockSigner{},
|
|
publicKeyEncryptor: &mockEncryptor{},
|
|
}
|
|
w := helper.NewMockIoWriter()
|
|
if err := env.WriteToWriter(w); err != nil {
|
|
t.Error(err)
|
|
}
|
|
r, err := zip.NewReader(w.ReaderAt(), int64(w.Length()))
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
if len(r.File) != 3 {
|
|
t.Error("wrong file number")
|
|
}
|
|
}
|
|
|
|
func TestMethodOrder(t *testing.T) {
|
|
mockPayload := newMockPayload()
|
|
env := &Enveloper{
|
|
payload: mockPayload,
|
|
signer: &mockSigner{},
|
|
publicKeyEncryptor: &mockEncryptor{},
|
|
}
|
|
w := helper.NewMockIoWriter()
|
|
if err := env.WriteToWriter(w); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := mockPayload.assertMethodCallOrder("GetPayloadData", "GetHashMethod"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|