Commit 83c49738 authored by Loïck Bonniot's avatar Loïck Bonniot

Merge branch '192_client_signing_execution' into 'master'

192 client signing execution

A least.

*HUGE PR* (+1000/-100) and the review will take time.

Included
---

+ Sequence analysis (Axel)
+ *Naive* signature sequence execution
+ Persist result to file in JSON

Still pending (reported to another story?)
----

+ ~~Persist evidences after completion to a file~~
+ Check for connection security (cert) here and there
+ Better error management
+ Benchmarks 😄 

See merge request !45
parents 94c7a2a2 e8867f36
Pipeline #646 passed with stages
......@@ -61,8 +61,8 @@ Integration tests:
# Build binary
- "cd $GOPATH/src/dfss/dfssd && go build -ldflags \"-r .\" -o dfssd"
# Install binary
- "mv $GOPATH/src/dfss/dfssd/dfssd /bin/"
- "mv $GOPATH/src/dfss/dfssd/libqtdrv.ui.so.1 /lib/"
- "cp $GOPATH/src/dfss/dfssd/dfssd $GOPATH/bin/"
- "cp $GOPATH/src/dfss/dfssd/libqtdrv.ui.so.1 /lib/"
# Start integration tests
- "go test -v dfss/tests"
......
......@@ -9,6 +9,7 @@ It is generated from these files:
dfss/dfssc/api/client.proto
It has these top-level messages:
Context
Promise
Signature
Hello
......@@ -34,36 +35,60 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
const _ = proto.ProtoPackageIsVersion1
type Context struct {
RecipientKeyHash []byte `protobuf:"bytes,1,opt,name=recipientKeyHash,proto3" json:"recipientKeyHash,omitempty"`
SenderKeyHash []byte `protobuf:"bytes,2,opt,name=senderKeyHash,proto3" json:"senderKeyHash,omitempty"`
SignatureUuid string `protobuf:"bytes,3,opt,name=signatureUuid" json:"signatureUuid,omitempty"`
ContractUuid string `protobuf:"bytes,4,opt,name=contractUuid" json:"contractUuid,omitempty"`
ContractDocumentHash string `protobuf:"bytes,5,opt,name=contractDocumentHash" json:"contractDocumentHash,omitempty"`
}
func (m *Context) Reset() { *m = Context{} }
func (m *Context) String() string { return proto.CompactTextString(m) }
func (*Context) ProtoMessage() {}
func (*Context) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// Promise message contains all the required information to verify
// the identity of the sender and reciever, and the actual promise
// the identity of the sender and receiver, and the actual promise
type Promise struct {
RecipientKeyHash []byte `protobuf:"bytes,1,opt,name=recipientKeyHash,proto3" json:"recipientKeyHash,omitempty"`
SenderKeyHash []byte `protobuf:"bytes,2,opt,name=senderKeyHash,proto3" json:"senderKeyHash,omitempty"`
SignatureUuid string `protobuf:"bytes,3,opt,name=signatureUuid" json:"signatureUuid,omitempty"`
ContractUuid string `protobuf:"bytes,4,opt,name=contractUuid" json:"contractUuid,omitempty"`
Context *Context `protobuf:"bytes,1,opt,name=context" json:"context,omitempty"`
Index uint32 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"`
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
}
func (m *Promise) Reset() { *m = Promise{} }
func (m *Promise) String() string { return proto.CompactTextString(m) }
func (*Promise) ProtoMessage() {}
func (*Promise) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*Promise) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Promise) GetContext() *Context {
if m != nil {
return m.Context
}
return nil
}
// Signature message contains all the required information to verify
// the identity of the sender and reciever, and the actual signature
// the identity of the sender and receiver, and the actual signature
type Signature struct {
RecipientKeyHash []byte `protobuf:"bytes,1,opt,name=recipientKeyHash,proto3" json:"recipientKeyHash,omitempty"`
SenderKeyHash []byte `protobuf:"bytes,2,opt,name=senderKeyHash,proto3" json:"senderKeyHash,omitempty"`
Signature string `protobuf:"bytes,3,opt,name=signature" json:"signature,omitempty"`
SignatureUuid string `protobuf:"bytes,4,opt,name=signatureUuid" json:"signatureUuid,omitempty"`
ContractUuid string `protobuf:"bytes,5,opt,name=contractUuid" json:"contractUuid,omitempty"`
Context *Context `protobuf:"bytes,1,opt,name=context" json:"context,omitempty"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
}
func (m *Signature) Reset() { *m = Signature{} }
func (m *Signature) String() string { return proto.CompactTextString(m) }
func (*Signature) ProtoMessage() {}
func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *Signature) GetContext() *Context {
if m != nil {
return m.Context
}
return nil
}
// Hello message is used when discovering peers. It contains the current version of the software.
// Hello message is used when discovering peers.
// It contains the current version of the software.
type Hello struct {
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
}
......@@ -71,9 +96,10 @@ type Hello struct {
func (m *Hello) Reset() { *m = Hello{} }
func (m *Hello) String() string { return proto.CompactTextString(m) }
func (*Hello) ProtoMessage() {}
func (*Hello) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (*Hello) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func init() {
proto.RegisterType((*Context)(nil), "api.Context")
proto.RegisterType((*Promise)(nil), "api.Promise")
proto.RegisterType((*Signature)(nil), "api.Signature")
proto.RegisterType((*Hello)(nil), "api.Hello")
......@@ -199,24 +225,27 @@ var _Client_serviceDesc = grpc.ServiceDesc{
}
var fileDescriptor0 = []byte{
// 302 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x92, 0x4f, 0x4e, 0xf3, 0x30,
0x10, 0xc5, 0x9b, 0xaf, 0xff, 0xbe, 0x8c, 0x42, 0x85, 0xbc, 0xaa, 0x02, 0x48, 0x10, 0x75, 0x81,
0x58, 0x24, 0x52, 0x39, 0x42, 0x41, 0xaa, 0xc4, 0x06, 0x05, 0x38, 0x80, 0x71, 0xa6, 0x60, 0x29,
0x8d, 0xa3, 0xb1, 0x8b, 0xc4, 0x35, 0xb8, 0x03, 0x47, 0xe1, 0x5e, 0xa4, 0xd3, 0x26, 0x25, 0x6a,
0x17, 0x6c, 0xd8, 0x44, 0x79, 0xcf, 0xbf, 0xb1, 0xdf, 0x78, 0x0c, 0x27, 0xd9, 0xc2, 0xda, 0x64,
0xfd, 0x51, 0x89, 0x2c, 0x75, 0xa2, 0x72, 0x8d, 0x85, 0x8b, 0x4b, 0x32, 0xce, 0x88, 0x6e, 0xe5,
0x84, 0x67, 0x0d, 0x51, 0x32, 0x51, 0xe6, 0xd2, 0x2d, 0x0c, 0x2d, 0x37, 0x4c, 0xf4, 0xe9, 0xc1,
0xf0, 0x9e, 0xcc, 0x52, 0x5b, 0x14, 0x57, 0x70, 0x4c, 0xa8, 0x74, 0xb9, 0xde, 0xe2, 0x0e, 0xdf,
0xe7, 0xd2, 0xbe, 0x8e, 0xbd, 0x73, 0xef, 0x32, 0x48, 0xf7, 0x7c, 0x31, 0x81, 0x23, 0x8b, 0x45,
0x86, 0x54, 0x83, 0xff, 0x18, 0x6c, 0x9b, 0x4c, 0xe9, 0x97, 0x42, 0xba, 0x15, 0xe1, 0xd3, 0x4a,
0x67, 0xe3, 0x6e, 0x45, 0xf9, 0x69, 0xdb, 0x14, 0x11, 0x04, 0xca, 0x14, 0x8e, 0xa4, 0x72, 0x0c,
0xf5, 0x18, 0x6a, 0x79, 0xd1, 0x97, 0x07, 0xfe, 0x43, 0x5d, 0xf5, 0x07, 0x49, 0x4f, 0xc1, 0x6f,
0x42, 0x6d, 0x53, 0xee, 0x8c, 0xfd, 0x3e, 0x7a, 0xbf, 0xe9, 0xa3, 0x7f, 0xa0, 0x8f, 0x0b, 0xe8,
0xcf, 0x31, 0xcf, 0x8d, 0x18, 0xc3, 0xf0, 0x0d, 0xc9, 0x6a, 0x53, 0x70, 0x72, 0x3f, 0xad, 0xe5,
0xf4, 0xc3, 0x83, 0xc1, 0x8c, 0xe7, 0x28, 0x62, 0x08, 0x1e, 0x09, 0xa5, 0xab, 0x27, 0x14, 0xc4,
0xd5, 0x08, 0xe3, 0xad, 0x0a, 0x47, 0xac, 0x6e, 0x89, 0x0c, 0xcd, 0x4c, 0x86, 0x51, 0x47, 0x4c,
0x61, 0xc4, 0xfc, 0xee, 0xa6, 0x36, 0x4c, 0xa3, 0x0f, 0xd4, 0x4c, 0xe0, 0xff, 0x8d, 0xb6, 0xca,
0x54, 0xc7, 0x0b, 0xe0, 0x55, 0x0e, 0x18, 0xfe, 0xf8, 0x8f, 0x3a, 0xcf, 0x03, 0x7e, 0x2e, 0xd7,
0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x61, 0x73, 0x57, 0xa2, 0x71, 0x02, 0x00, 0x00,
// 348 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x92, 0xd1, 0x4a, 0xfb, 0x30,
0x14, 0xc6, 0xd7, 0xed, 0xbf, 0xf5, 0xbf, 0x63, 0x37, 0x24, 0xec, 0x62, 0x4c, 0x04, 0x2d, 0x43,
0xc4, 0x8b, 0x0e, 0xe6, 0x23, 0x6c, 0xc2, 0x40, 0x04, 0xa9, 0xfa, 0x00, 0x31, 0xcd, 0x34, 0xd0,
0x35, 0x25, 0xc9, 0x64, 0x7b, 0x0d, 0xdf, 0xce, 0xb7, 0x31, 0x3d, 0x59, 0xe6, 0x8a, 0xbb, 0xf0,
0xa6, 0xf4, 0xfb, 0xce, 0xaf, 0xe7, 0x9c, 0x2f, 0x0d, 0x9c, 0x65, 0x4b, 0xad, 0x27, 0xd5, 0x83,
0x4d, 0x68, 0x29, 0x26, 0x2c, 0x17, 0xbc, 0x30, 0x49, 0xa9, 0xa4, 0x91, 0xa4, 0x65, 0x9d, 0xd1,
0xf9, 0x9e, 0x28, 0x91, 0x28, 0x73, 0x6a, 0x96, 0x52, 0xad, 0x1c, 0x13, 0x7f, 0x05, 0x10, 0xce,
0x64, 0x61, 0xf8, 0xc6, 0x90, 0x1b, 0x38, 0x55, 0x9c, 0x89, 0xb2, 0x6a, 0x71, 0xcf, 0xb7, 0x0b,
0xaa, 0xdf, 0x87, 0xc1, 0x45, 0x70, 0x1d, 0xa5, 0xbf, 0x7c, 0x32, 0x86, 0x9e, 0xe6, 0x45, 0xc6,
0x95, 0x07, 0x9b, 0x08, 0xd6, 0x4d, 0xa4, 0xc4, 0x5b, 0x41, 0xcd, 0x5a, 0xf1, 0x97, 0xb5, 0xc8,
0x86, 0x2d, 0x4b, 0x75, 0xd3, 0xba, 0x49, 0x62, 0x88, 0x98, 0x5d, 0x41, 0x51, 0x66, 0x10, 0xfa,
0x87, 0x50, 0xcd, 0x23, 0x53, 0x18, 0x78, 0x3d, 0x97, 0x6c, 0xbd, 0xb2, 0xab, 0xe0, 0xd8, 0x36,
0xb2, 0x47, 0x6b, 0x31, 0x85, 0xf0, 0x51, 0xc9, 0x95, 0xd0, 0x9c, 0x5c, 0x41, 0xc8, 0x5c, 0x4a,
0x4c, 0x74, 0x32, 0x8d, 0x12, 0x7b, 0x18, 0xc9, 0x2e, 0x79, 0xea, 0x8b, 0x64, 0x00, 0x6d, 0x61,
0x03, 0x6c, 0x30, 0x4e, 0x2f, 0x75, 0x82, 0x0c, 0x21, 0x2c, 0xe9, 0x36, 0x97, 0xd4, 0x05, 0x88,
0x52, 0x2f, 0xe3, 0x07, 0xe8, 0x3e, 0xf9, 0x2c, 0x7f, 0x1e, 0x72, 0xd0, 0xae, 0x59, 0x6f, 0x77,
0x09, 0xed, 0x05, 0xcf, 0x73, 0x59, 0x21, 0x1f, 0x5c, 0x69, 0x21, 0x0b, 0x6c, 0xd5, 0x4d, 0xbd,
0x9c, 0x7e, 0x06, 0xd0, 0x99, 0xe1, 0x5f, 0x26, 0x09, 0x44, 0xcf, 0x8a, 0x53, 0xe3, 0x43, 0xba,
0x71, 0x3b, 0x35, 0xea, 0xa3, 0xba, 0x53, 0x4a, 0xaa, 0x99, 0xcc, 0x78, 0xdc, 0xb0, 0x67, 0xd8,
0x47, 0xfe, 0x67, 0x63, 0xc7, 0xec, 0xf5, 0x91, 0x6f, 0xc6, 0xf0, 0x7f, 0x2e, 0x34, 0x93, 0x76,
0x3c, 0x01, 0xac, 0xe2, 0x82, 0xa3, 0x83, 0xf7, 0xb8, 0xf1, 0xda, 0xc1, 0xcb, 0x74, 0xfb, 0x1d,
0x00, 0x00, 0xff, 0xff, 0x8e, 0x21, 0x38, 0xfd, 0x8f, 0x02, 0x00, 0x00,
}
......@@ -10,26 +10,31 @@ service Client {
rpc Discover(Hello) returns (Hello) {}
}
// Promise message contains all the required information to verify
// the identity of the sender and reciever, and the actual promise
message Promise {
message Context {
bytes recipientKeyHash = 1; // SHA-512
bytes senderKeyHash = 2; // SHA-512
bytes senderKeyHash = 2; // SHA-512
string signatureUuid = 3;
string contractUuid = 4;
string contractDocumentHash = 5;
}
// Promise message contains all the required information to verify
// the identity of the sender and receiver, and the actual promise
message Promise {
Context context = 1;
uint32 index = 2;
bytes payload = 3;
}
// Signature message contains all the required information to verify
// the identity of the sender and reciever, and the actual signature
// the identity of the sender and receiver, and the actual signature
message Signature {
bytes recipientKeyHash = 1; // SHA-512
bytes senderKeyHash = 2; // SHA-512
string signature = 3; // Cryptographic signature
string signatureUuid = 4;
string contractUuid = 5;
Context context = 1;
bytes payload = 2;
}
// Hello message is used when discovering peers. It contains the current version of the software.
// Hello message is used when discovering peers.
// It contains the current version of the software.
message Hello {
string version = 1;
}
package common
import (
"errors"
)
// FindNextIndex analyses the specified sequence and tries to find the next occurence of id after the specified index (excluded)
// Therefore to find the first occurence of the id in the sequence, use -1 as the index
//
// If there is no occurence of id, then -1 is returned
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
func FindNextIndex(s []uint32, id uint32, index int) (int, error) {
if index >= len(s) || index < -1 {
return -1, errors.New("Index out of range")
}
for i := index + 1; i < len(s); i++ {
if s[i] == id {
return i, nil
}
}
return -1, nil
}
// GetPendingSet analyses the specified sequence and computes the set of ids occuring between index (excluded) and the previous occurence of id
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
//
// If the index is not the one of the specified id in the sequence, the result still holds, but may be incomplete for your needs
// If the id is not valid for the specified sequence, the result will be the set of ids of the sequence
func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
res := []uint32{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
}
curIndex := index - 1
if curIndex < 0 {
return res, nil
}
for curIndex > -1 && s[curIndex] != id {
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
}
curIndex--
}
return res, nil
}
// GetSendSet analyses the specified sequence and computes the set of ids occuring between index (excluded) and the next occurence of id
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
//
// If the index is not the one of the specified id in the sequence, the result still holds, but may be incomplete for your needs
// If the id is not valid for the specified sequence, the result will be the set of ids of the sequence
func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
res := []uint32{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
}
curIndex := index + 1
if curIndex >= len(s) {
return res, nil
}
for curIndex < len(s) && s[curIndex] != id {
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
}
curIndex++
}
return res, nil
}
// contains determines if s contains e
func contains(s []uint32, e uint32) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
// GetAllButOne creates the slice of all sequence ids, except the one specified
//
// TODO This is O(n^2) and need a rework with a map
func GetAllButOne(s []uint32, e uint32) []uint32 {
var res = make([]uint32, 0)
for i := 0; i < len(s); i++ {
curID := s[i]
if !contains(res, curID) && curID != e {
res = append(res, curID)
}
}
return res
}
// Remove an ID from the sequence
func Remove(s []uint32, e uint32) ([]uint32, error) {
for i, a := range s {
if a == e {
return append(s[:i], s[i+1:]...), nil
}
}
return s, errors.New("ID not in sequence")
}
package common
import (
"fmt"
"testing"
"github.com/bmizerany/assert"
)
func TestFindNextIndex(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res, err := FindNextIndex(s, id, 0)
assert.Equal(t, res, 2)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, 2)
assert.Equal(t, res, 5)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, 5)
assert.Equal(t, res, -1)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, -2)
assert.Equal(t, res, -1)
assert.Equal(t, err.Error(), "Index out of range")
res, err = FindNextIndex(s, id, len(s))
assert.Equal(t, res, -1)
assert.Equal(t, err.Error(), "Index out of range")
res, err = FindNextIndex(s, 0, -1)
assert.Equal(t, res, 0)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, 0, 0)
assert.Equal(t, res, 3)
assert.Equal(t, err, nil)
}
func TestGetPendingSet(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res, err := GetPendingSet(s, id, 0)
assert.Equal(t, len(res), 0)
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 1)
assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 2)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 5)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, -1)
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
res, err = GetPendingSet(s, id, len(s))
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
s = []uint32{0, 1, 0, 2}
res, err = GetPendingSet(s, id, 3)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
assert.Equal(t, err, nil)
}
func TestContains(t *testing.T) {
s := []uint32{0, 1}
assert.Equal(t, contains(s, 0), true)
assert.Equal(t, contains(s, 1), true)
assert.Equal(t, contains(s, 2), false)
}
func TestGetSendSet(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(0)
res, err := GetSendSet(s, id, 3)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, id, 0)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, 1, 4)
assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, 2, 5)
assert.Equal(t, len(res), 0)
assert.Equal(t, err, nil)
res, err = GetSendSet(s, id, -1)
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
res, err = GetSendSet(s, id, len(s))
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
}
func TestGetAllButOne(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res := GetAllButOne(s, id)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
res = GetAllButOne(s, uint32(42))
assert.Equal(t, len(res), 3)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
assert.Equal(t, res[2], uint32(2))
}
func ExampleFindNextIndex() {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
index, _ := FindNextIndex(s, id, -1)
fmt.Println("First index:", index)
pSet, _ := GetPendingSet(s, id, index)
fmt.Println("Pending Set:", pSet)
sSet, _ := GetSendSet(s, id, index)
fmt.Println("Send Set:", sSet)
// Output:
// First index: 2
// Pending Set: [1 0]
// Send Set: [0 1]
}
......@@ -49,4 +49,18 @@ func signContract(args []string) {
fmt.Println("Everybody is ready, starting the signature", signatureUUID)
// Signature
err = manager.Sign()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(5)
}
// Persist evidencies, if any
err = manager.PersistSignaturesToFile()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(5)
}
fmt.Println("Signature complete! See .proof file for evidences.")
}
package sign
import (
"encoding/json"
"fmt"
"io/ioutil"
cAPI "dfss/dfssc/api"
"dfss/dfssp/contract"
)
// SignedContractJSON is an union of contract and related signatures
type SignedContractJSON struct {
Contract contract.JSON
Signatures []cAPI.Signature
}
// PersistSignaturesToFile save contract informations and signatures to disk
func (m *SignatureManager) PersistSignaturesToFile() error {
// Check content, don't write an empty file
if len(m.archives.receivedSignatures) == 0 {
return fmt.Errorf("No stored signatures, cannot create an empty file (yes I'm a coward)")
}
// Fill JSON struct
signedContract := SignedContractJSON{
Contract: *m.contract,
Signatures: make(
[]cAPI.Signature,
len(m.archives.sentSignatures)+len(m.archives.receivedSignatures),
),
}
for i, s := range m.archives.sentSignatures {
signedContract.Signatures[i] = *s
}
for i, s := range m.archives.receivedSignatures {
signedContract.Signatures[len(m.archives.sentSignatures)+i] = *s
}
proof, err := json.MarshalIndent(signedContract, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(m.mail+"-"+m.contract.UUID+".proof", proof, 0600)
}
package sign
import (
"errors"
"time"
cAPI "dfss/dfssc/api"
dAPI "dfss/dfssd/api"
pAPI "dfss/dfssp/api"
"golang.org/x/net/context"
)
func (m *SignatureManager) createContext(from, to uint32) (*cAPI.Context, error) {
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return nil, errors.New("Invalid id for context creation")
}
return &cAPI.Context{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
ContractDocumentHash: m.contract.File.Hash,
SignatureUuid: m.uuid,
ContractUuid: m.contract.UUID,
}, nil
}
// CreatePromise creates a promise from 'from' to 'to', in the context of the SignatureManager
// provided the specified sequence indexes are valid
func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error) {
context, err := m.createContext(from, to)
if err != nil {
return nil, err