Commit 9bc1fb12 authored by Caro Axel's avatar Caro Axel Committed by Loïck Bonniot

[c] Add promise/signature emission and archiving

parent 7e4ef127
......@@ -15,7 +15,7 @@ func FindNextIndex(s []uint32, id uint32, index int) (int, error) {
return -1, errors.New("Index out of range")
}
for i := index+1; i < len(s); i++ {
for i := index + 1; i < len(s); i++ {
if s[i] == id {
return i, nil
}
......@@ -37,15 +37,15 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
return res, errors.New("Index out of range")
}
curIndex := index-1
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)
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
}
curIndex--
}
......@@ -66,15 +66,15 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
return res, errors.New("Index out of range")
}
curIndex := index+1
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)
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
}
curIndex++
}
......@@ -84,10 +84,24 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
// contains determines if s contains e
func contains(s []uint32, e uint32) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
\ No newline at end of file
for _, a := range s {
if a == e {
return true
}
}
return false
}
// GetAllButOne creates the slice of all sequence ids, except the one specified
func GetAllButOne(s []uint32, e uint32) []uint32 {
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
}
......@@ -2,8 +2,8 @@ package common
import (
"fmt"
"testing"
"github.com/bmizerany/assert"
"testing"
)
func TestFindNextIndex(t *testing.T) {
......@@ -122,6 +122,22 @@ func TestGetSendSet(t *testing.T) {
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 ExampleSequenceAnalysis() {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
......@@ -138,4 +154,4 @@ func ExampleSequenceAnalysis() {
// First index: 2
// Pending Set: [1 0]
// Send Set: [0 1]
}
\ No newline at end of file
}
package sign
/*
import (
"fmt"
......@@ -58,4 +59,4 @@ func TestComputeFile(t *testing.T) {
assert.Equal(t, "37fd29decfb2d689439478b1f64b60441534c1e373a7023676c94ac6772639edab46f80139d167a2741f159e62b3064eca58bb331d32cd10770f29064af2a9de", fmt.Sprintf("%x", m.hash))
assert.Equal(t, "contract.txt", m.filename)
}
*/
\ No newline at end of file
*/
......@@ -29,7 +29,17 @@ type SignatureManager struct {
cServer *grpc.Server
sequence []uint32
uuid string
mail string
keyHash [][]byte
mail string
archives *Archives
}
// Archives stores the recieved and sent messages, as evidence if needed
type Archives struct {
sentPromises []*cAPI.Promise
recievedPromises []*cAPI.Promise
sentSignatures []*cAPI.Signature
recievedSignatures []*cAPI.Signature
}
// NewSignatureManager populates a SignatureManager and connects to the platform.
......@@ -38,14 +48,20 @@ func NewSignatureManager(fileCA, fileCert, fileKey, addrPort, passphrase string,
auth: security.NewAuthContainer(fileCA, fileCert, fileKey, addrPort, passphrase),
localPort: port,
contract: c,
archives: &Archives{
sentPromises: make([]*cAPI.Promise, 0),
recievedPromises: make([]*cAPI.Promise, 0),
sentSignatures: make([]*cAPI.Signature, 0),
recievedSignatures: make([]*cAPI.Signature, 0),
},
}
var err error
_, x509cert, _, err := m.auth.LoadFiles()
_, _, _, err = m.auth.LoadFiles()
if err != nil {
return nil, err
}
m.mail = x509cert.Subject.CommonName
m.mail = m.auth.Cert.Subject.CommonName
m.cServer = m.GetServer()
go func() { log.Fatalln(net.Listen("0.0.0.0:"+strconv.Itoa(port), m.cServer)) }()
......@@ -175,38 +191,32 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) {
m.sequence = launch.Sequence
m.uuid = launch.SignatureUuid
m.keyHash = launch.KeyHash
signatureUUID = m.uuid
return
}
// Sign make the SignatureManager perform its specified signature
// Sign makes the SignatureManager perform its specified signature
func (m *SignatureManager) Sign() error {
mySeqId, err := m.FindId()
if (err != nil) {
return err
}
curIndex, err := common.FindNextIndex(m.sequence, mySeqId, -1)
if (err != nil) {
myID, currentIndex, nextIndex, err := m.Initialize()
if err != nil {
return err
}
nextIndex, err := common.FindNextIndex(m.sequence, mySeqId, curIndex)
// Promess tounds
for (nextIndex != -1) {
pendingSet, err := common.GetPendingSet(m.sequence, mySeqId, curIndex)
if (err != nil) {
// Promess rounds
for nextIndex != -1 {
pendingSet, err := common.GetPendingSet(m.sequence, myID, currentIndex)
if err != nil {
return err
}
sendSet, err := common.GetSendSet(m.sequence, mySeqId, curIndex)
if (err != nil) {
sendSet, err := common.GetSendSet(m.sequence, myID, currentIndex)
if err != nil {
return err
}
// Reception of the due promesses
for (len(pendingSet) != 0) {
for len(pendingSet) != 0 {
i := 0
// TODO
// Improve, because potential memory leak
......@@ -217,55 +227,189 @@ func (m *SignatureManager) Sign() error {
c := make(chan int)
// Sending of the due promesses
/*
for _, id := range sendSet {
go func(id) {
promise := m.CreatePromise(id)
recpt := m.SendPromise(promise, id)
c <- id
}(id)
}
for _, id := range sendSet {
go func(id) {
promise, err := m.CreatePromise(id)
recpt := m.SendPromise(promise, id)
c <- id
}(id)
}
*/
// Verifying we sent all the due promesses
for _ = range sendSet {
<- c
<-c
}
currentIndex = nextIndex
nextIndex, err = common.FindNextIndex(m.sequence, myID, currentIndex)
if err != nil {
return err
}
}
// Signature round
m.SendAllSigns()
m.RecieveAllSigns()
err = m.SendAllSigns()
if err != nil {
return err
}
err = m.RecieveAllSigns()
if err != nil {
return err
}
return nil
}
// findId finds the sequence id for the user's email and the contract to sign
func (m *SignatureManager) FindId() (uint32, error) {
// Initialize computes the values needed for the start of the signing
func (m *SignatureManager) Initialize() (uint32, int, int, error) {
myID, err := m.FindID()
if err != nil {
return 0, 0, 0, err
}
currentIndex, err := common.FindNextIndex(m.sequence, myID, -1)
if err != nil {
return 0, 0, 0, err
}
nextIndex, err := common.FindNextIndex(m.sequence, myID, currentIndex)
if err != nil {
return 0, 0, 0, err
}
return myID, currentIndex, nextIndex, nil
}
// FindID finds the sequence id for the user's email and the contract to sign
func (m *SignatureManager) FindID() (uint32, error) {
signers := m.contract.Signers
for id, signer := range signers {
if (signer.Email == m.mail) {
if signer.Email == m.mail {
return uint32(id), nil
}
}
return 0, errors.New("Mail couldn't be found amongst signers")
}
// TODO
func (m *SignatureManager) CreatePromise(id uint32) error {
return 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) {
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return &cAPI.Promise{}, errors.New("Invalid id for promise creation")
}
promise := &cAPI.Promise{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
SignatureUuid: m.uuid,
ContractUuid: m.contract.UUID,
}
return promise, nil
}
// SendPromise sends the specified promise to the specified peer
// TODO
func (m *SignatureManager) SendPromise(id uint32) error {
return nil
func (m *SignatureManager) SendPromise(promise *cAPI.Promise, to uint32) (*pAPI.ErrorCode, error) {
connection, err := m.GetClient(to)
if err != nil {
return &pAPI.ErrorCode{}, err
}
// TODO
// Handle the timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
errCode, err := (*connection).TreatPromise(ctx, promise)
if err != nil {
return &pAPI.ErrorCode{}, err
}
m.archives.sentPromises = append(m.archives.sentPromises, promise)
return errCode, nil
}
// GetClient retrieves the Client to the specified sequence id provided it exists
func (m *SignatureManager) GetClient(to uint32) (*cAPI.ClientClient, error) {
mailto := m.contract.Signers[to].Email
if _, ok := m.peers[mailto]; !ok {
return nil, fmt.Errorf("No connection to user %s", mailto)
}
return m.peers[mailto], nil
}
// SendAllSigns creates and sends signatures to all the signers of the contract
// TODO
// Use goroutines to send in parallel
func (m *SignatureManager) SendAllSigns() error {
myID, err := m.FindID()
if err != nil {
return err
}
sendSet := common.GetAllButOne(m.sequence, myID)
for _, id := range sendSet {
signature, err := m.CreateSignature(myID, id)
if err != nil {
return err
}
_, err = m.SendSignature(signature, id)
if err != nil {
return err
}
}
return nil
}
// CreateSignature creates a signature from from to to, in the context of the SignatureManager
// provided the specified sequence indexes are valid
// TODO
// Implement a true cryptographic signature
func (m *SignatureManager) CreateSignature(from, to uint32) (*cAPI.Signature, error) {
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return &cAPI.Signature{}, errors.New("Invalid id for signature creation")
}
signature := &cAPI.Signature{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
Signature: "Signature",
SignatureUuid: m.uuid,
ContractUuid: m.contract.UUID,
}
return signature, nil
}
// SendSignature sends the specified signature to the specified peer
// TODO
func (m *SignatureManager) SendSignature(signature *cAPI.Signature, to uint32) (*pAPI.ErrorCode, error) {
connection, err := m.GetClient(to)
if err != nil {
return &pAPI.ErrorCode{}, err
}
// TODO
// Handle the timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
errCode, err := (*connection).TreatSignature(ctx, signature)
if err != nil {
return &pAPI.ErrorCode{}, err
}
m.archives.sentSignatures = append(m.archives.sentSignatures, signature)
return errCode, nil
}
// RecieveAllSigns is not done yet
// TODO
func (m *SignatureManager) RecieveAllSigns() error {
return nil
}
\ No newline at end of file
}
......@@ -11,9 +11,9 @@ import (
func TestFindId(t *testing.T) {
mail := "signer2@foo.foo"
s1 := contract.SignerJSON{ Email: "signer1@foo.foo" }
s2 := contract.SignerJSON{ Email: mail }
s3 := contract.SignerJSON{ Email: "signer3@foo.foo" }
s1 := contract.SignerJSON{Email: "signer1@foo.foo"}
s2 := contract.SignerJSON{Email: mail}
s3 := contract.SignerJSON{Email: "signer3@foo.foo"}
contract := &contract.JSON{
Signers: []contract.SignerJSON{s1, s2, s3},
......@@ -27,12 +27,12 @@ func TestFindId(t *testing.T) {
mail: mail,
}
id, err := sm.FindId()
id, err := sm.FindID()
assert.Equal(t, err, nil)
assert.Equal(t, id, uint32(1))
sm.mail = ""
id, err = sm.FindId()
id, err = sm.FindID()
assert.Equal(t, err.Error(), "Mail couldn't be found amongst signers")
assert.Equal(t, id, uint32(0))
}
\ No newline at end of file
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment