This commit is contained in:
didier.amyot committed 2014-10-14 06:31:36 -07:00
1 parent 4897e8d307
commit 4aca3324c9
10 files changed
+401 -17

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
package envelop
/*
This package containes everything to create an envelop around a payload
*/
+104
View File
@@ -0,0 +1,104 @@
package envelop
import (
"archive/zip"
"encoding/json"
"fmt"
"io"
)
type Payload interface {
GetHash() []byte
GetKey() []byte
GetAlgorithm() string
GetMode() string
GetHashMethod() string
GetPayloadData() io.Reader
}
type Encryptor interface {
Encrypt(data []byte) ([]byte, error)
}
type Signer interface {
Sign(data []byte) ([]byte, error)
}
type Enveloper struct {
encryptor Encryptor
payload Payload
signer Signer
EncryptedKey []byte
Signature []byte
Metadata *Metadata
}
func (this *Enveloper) EncryptKey() ([]byte, error) {
return this.encryptor.Encrypt(this.payload.GetKey())
}
func (this *Enveloper) SignPayload() ([]byte, error) {
return this.signer.Sign(this.payload.GetHash())
}
func (this *Enveloper) CreateMetadata() *Metadata {
md := new(Metadata)
md.BlockAlgorithm = this.payload.GetAlgorithm()
md.BlockMode = this.payload.GetMode()
md.SignatureAlgorithm = "RSAPSS"
md.HashMethod = this.payload.GetHashMethod()
return md
}
func (this *Enveloper) CreateEnvelopCompletely() error {
var err error
if this.EncryptedKey, err = this.EncryptKey(); err != nil {
return err
} else if this.Signature, err = this.SignPayload(); err != nil {
return err
}
this.Metadata = this.CreateMetadata()
return nil
}
func (this *Enveloper) WritePayload(z *zip.Writer) error {
dataWriter, err := z.Create("data")
if err != nil {
return err
}
_, err = io.Copy(dataWriter, this.payload.GetPayloadData())
return err
}
func (this *Enveloper) WriteMetadata(z *zip.Writer) error {
dataWriter, err := z.Create("metadata.json")
if err != nil {
return err
}
encoder := json.NewEncoder(dataWriter)
return encoder.Encode(this.Metadata)
}
func (this *Enveloper) WriteEncryptedKey(z *zip.Writer) error {
dataWriter, err := z.Create("key.json")
if err != nil {
return err
}
encoder := json.NewEncoder(dataWriter)
return encoder.Encode(&struct {
Key string
}{fmt.Sprintf("%s", this.EncryptedKey)})
}
func (this *Enveloper) WriteToWriter(w io.Writer) error {
z := zip.NewWriter(w)
defer z.Close()
if err := this.WritePayload(z); err != nil {
return err
} else if err := this.WriteMetadata(z); err != nil {
return err
} else if err := this.WriteEncryptedKey(z); err != nil {
return err
}
return nil
}
+163
View File
@@ -0,0 +1,163 @@
package envelop
import (
"archive/zip"
"bytes"
"github.com/didiercrunch/ecrypto/helper"
"io"
"reflect"
"testing"
)
type mockPayload struct{}
func (this *mockPayload) GetKey() []byte {
return []byte{1, 2, 3}
}
func (this *mockPayload) GetHash() []byte {
return []byte{10, 9, 8}
}
func (this *mockPayload) GetAlgorithm() string {
symetricEncryptionAlgorithm := "DES"
return symetricEncryptionAlgorithm
}
func (this *mockPayload) GetMode() string {
symetricEncryptionMode := "OFB"
return symetricEncryptionMode
}
func (this *mockPayload) GetHashMethod() string {
theHashMethodUsedInThePayLoad := "SHA1"
return theHashMethodUsedInThePayLoad
}
func (this *mockPayload) GetPayloadData() io.Reader {
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))
}
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{
encryptor: &mockEncryptor{},
payload: &mockPayload{},
}
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 := &Enveloper{
encryptor: &mockEncryptor{},
payload: &mockPayload{},
signer: &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 := &Enveloper{
payload: &mockPayload{},
encryptor: &mockEncryptor{},
signer: &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: &mockPayload{}}
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{
encryptor: &mockEncryptor{},
payload: &mockPayload{},
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: &mockPayload{},
}
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")
}
}
+8
View File
@@ -0,0 +1,8 @@
package envelop
type Metadata struct {
BlockMode string
BlockAlgorithm string
SignatureAlgorithm string
HashMethod string
}