diff --git a/dfssc/api/client.pb.go b/dfssc/api/client.pb.go index ecc04ef58869ff618f1844cfed3883180ea3a304..6eb40bee89034344a21dcc8b9e7a12f08cbe3a9f 100644 --- a/dfssc/api/client.pb.go +++ b/dfssc/api/client.pb.go @@ -51,8 +51,13 @@ type Context struct { ContractDocumentHash []byte `protobuf:"bytes,5,opt,name=contractDocumentHash,proto3" json:"contractDocumentHash,omitempty"` // / The unique signature attemp ID, as provided by the platform during the ready signal SignatureUUID string `protobuf:"bytes,6,opt,name=signatureUUID" json:"signatureUUID,omitempty"` + // / The TTP address provided by the platform, to use in case of issue during signature. + // / Empty if no TTP used. + TtpAddrPort string `protobuf:"bytes,7,opt,name=ttpAddrPort" json:"ttpAddrPort,omitempty"` + // / The TTP certificate SHA-512 hash + TtpHash []byte `protobuf:"bytes,8,opt,name=ttpHash,proto3" json:"ttpHash,omitempty"` // / The signed metadata seal, as provided by the platform during the ready signal - Seal []byte `protobuf:"bytes,7,opt,name=seal,proto3" json:"seal,omitempty"` + Seal []byte `protobuf:"bytes,10,opt,name=seal,proto3" json:"seal,omitempty"` } func (m *Context) Reset() { *m = Context{} } @@ -262,27 +267,31 @@ var _Client_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 348 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x91, 0xcf, 0x4e, 0xea, 0x40, - 0x14, 0xc6, 0xe9, 0xe5, 0x4f, 0xe1, 0xdc, 0xc2, 0x25, 0x93, 0x6b, 0x32, 0x41, 0x49, 0x48, 0xe3, - 0x82, 0x55, 0x49, 0x70, 0xe9, 0x12, 0x4c, 0x30, 0x6e, 0x4c, 0x94, 0x07, 0x18, 0xa7, 0x07, 0x9d, - 0xa4, 0x74, 0xea, 0xcc, 0x60, 0xe0, 0x35, 0x7c, 0x02, 0x1f, 0xd5, 0xe9, 0xa9, 0x45, 0x16, 0x26, - 0x6e, 0x9a, 0x9e, 0x6f, 0xbe, 0xf3, 0xf5, 0xf7, 0x75, 0xe0, 0x3c, 0xdd, 0x58, 0x3b, 0x2b, 0x1f, - 0x72, 0x26, 0x0a, 0x35, 0x93, 0x99, 0xc2, 0xdc, 0x25, 0x85, 0xd1, 0x4e, 0xb3, 0xa6, 0x57, 0x46, - 0xe3, 0xa3, 0xa3, 0x20, 0x47, 0x91, 0x09, 0xb7, 0xd1, 0x66, 0x5b, 0x79, 0xe2, 0x8f, 0x00, 0xc2, - 0x85, 0xce, 0x1d, 0xee, 0x1d, 0xe3, 0x30, 0x34, 0x28, 0x55, 0x51, 0x46, 0xdc, 0xe1, 0x61, 0x25, - 0xec, 0x0b, 0x0f, 0x26, 0xc1, 0x34, 0x62, 0x67, 0xd0, 0xb7, 0x98, 0xa7, 0x68, 0x6a, 0xf9, 0x0f, - 0xc9, 0x43, 0xe8, 0x5a, 0x7c, 0xdd, 0x61, 0x2e, 0x91, 0x37, 0x27, 0xcd, 0x69, 0x9f, 0xfd, 0x83, - 0xd0, 0xaa, 0xe7, 0x1c, 0x8d, 0xe5, 0x2d, 0x2f, 0x44, 0xec, 0x02, 0xfe, 0x4b, 0x1f, 0x6f, 0x84, - 0x74, 0x4b, 0x2d, 0x77, 0x5b, 0x1f, 0x4d, 0x01, 0xed, 0x63, 0xae, 0xb7, 0x0b, 0xb7, 0x33, 0xb8, - 0x5e, 0xdf, 0x2e, 0x79, 0xc7, 0xcb, 0x3d, 0x16, 0x41, 0xcb, 0xa2, 0xc8, 0x78, 0x58, 0x9a, 0xe2, - 0x15, 0x84, 0xf7, 0x46, 0x6f, 0x95, 0x45, 0x36, 0x86, 0x50, 0x56, 0xb0, 0x04, 0xf6, 0x77, 0x1e, - 0x25, 0xbe, 0x53, 0x52, 0x17, 0xe8, 0x43, 0x5b, 0x79, 0xca, 0x3d, 0xe1, 0x11, 0x4c, 0x21, 0x0e, - 0x99, 0x16, 0xa9, 0xa7, 0x2b, 0x93, 0xae, 0xa1, 0xf7, 0x50, 0x7f, 0xee, 0xb7, 0xac, 0x93, 0x65, - 0x2a, 0x1b, 0x73, 0x68, 0xaf, 0x30, 0xcb, 0x74, 0x79, 0xf2, 0xe6, 0x0b, 0x2a, 0x9d, 0xd3, 0x62, - 0x6f, 0xfe, 0x1e, 0x40, 0x67, 0x41, 0x3f, 0x9e, 0x25, 0x10, 0x3d, 0x1a, 0x14, 0xae, 0x06, 0xae, - 0x32, 0xbf, 0xa6, 0xd1, 0x80, 0xa6, 0x1b, 0x63, 0xb4, 0x59, 0xe8, 0x14, 0xe3, 0x06, 0x9b, 0xc3, - 0x80, 0xfc, 0xdf, 0x58, 0x95, 0xe7, 0x38, 0xff, 0xb0, 0x73, 0x09, 0xdd, 0xa5, 0xb2, 0x52, 0x7b, - 0x08, 0x06, 0x74, 0x4a, 0x5c, 0xa3, 0x93, 0xf7, 0xb8, 0xf1, 0xd4, 0xa1, 0xfb, 0xbd, 0xfa, 0x0c, - 0x00, 0x00, 0xff, 0xff, 0x64, 0x27, 0xd3, 0xc2, 0x22, 0x02, 0x00, 0x00, + // 404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x52, 0xdd, 0xca, 0xda, 0x40, + 0x10, 0xf5, 0x3f, 0x3a, 0x46, 0x29, 0x8b, 0x17, 0x21, 0xa5, 0x60, 0x83, 0x14, 0xe9, 0x45, 0x04, + 0xfb, 0x04, 0x45, 0x0b, 0x96, 0x52, 0x90, 0xb4, 0x3e, 0xc0, 0x76, 0x33, 0xb6, 0x0b, 0x31, 0x9b, + 0xee, 0xae, 0x45, 0x5f, 0xa3, 0xaf, 0xd3, 0x97, 0xeb, 0x66, 0x62, 0xfc, 0x94, 0xcf, 0x8b, 0xef, + 0x26, 0xec, 0x39, 0x73, 0x76, 0xce, 0xec, 0xc9, 0xc0, 0xeb, 0x74, 0x6f, 0xcc, 0xa2, 0xfc, 0x88, + 0x05, 0x2f, 0xe4, 0x42, 0x64, 0x12, 0x73, 0x1b, 0x17, 0x5a, 0x59, 0xc5, 0xda, 0x8e, 0x09, 0xdf, + 0x5c, 0x15, 0x05, 0x29, 0x8a, 0x8c, 0xdb, 0xbd, 0xd2, 0x87, 0x4a, 0x13, 0xfd, 0x6b, 0x81, 0xb7, + 0x52, 0xb9, 0xc5, 0x93, 0x65, 0xef, 0xe1, 0x95, 0x46, 0x21, 0x8b, 0xb2, 0xc5, 0x17, 0x3c, 0x6f, + 0xb8, 0xf9, 0x15, 0x34, 0xa7, 0xcd, 0xb9, 0x9f, 0x3c, 0xe3, 0xd9, 0x0c, 0x46, 0x06, 0xf3, 0x14, + 0x75, 0x2d, 0x6c, 0x91, 0xf0, 0x9e, 0x64, 0x21, 0xf4, 0x0d, 0xfe, 0x3e, 0x62, 0x2e, 0x30, 0x68, + 0x4f, 0xdb, 0xf3, 0x51, 0x72, 0xc5, 0x2c, 0x00, 0xcf, 0xc8, 0x9f, 0x39, 0x6a, 0x13, 0x74, 0x5c, + 0xc9, 0x4f, 0x6a, 0xc8, 0x96, 0x30, 0x11, 0x6e, 0x24, 0xcd, 0x85, 0x5d, 0x2b, 0x71, 0x3c, 0x38, + 0x5b, 0xb2, 0xe8, 0x92, 0xc5, 0xc3, 0x1a, 0xcd, 0xe3, 0xae, 0x73, 0x7b, 0xd4, 0xb8, 0xdb, 0x7d, + 0x5e, 0x07, 0x3d, 0x27, 0x1e, 0x24, 0xf7, 0x24, 0x9b, 0xc2, 0xd0, 0xda, 0xe2, 0x63, 0x9a, 0xea, + 0xad, 0xd2, 0x36, 0xf0, 0x48, 0x73, 0x4b, 0x95, 0x53, 0x39, 0x48, 0x76, 0x7d, 0xb2, 0xab, 0x21, + 0x63, 0xd0, 0x31, 0xc8, 0xb3, 0x00, 0x88, 0xa6, 0x73, 0xc4, 0xc1, 0xdb, 0x6a, 0x75, 0x90, 0x06, + 0xd9, 0x3b, 0xf0, 0x44, 0x95, 0x23, 0x65, 0x36, 0x5c, 0xfa, 0xb1, 0x8b, 0x3b, 0xbe, 0x64, 0x9b, + 0xd4, 0x45, 0x36, 0x81, 0xae, 0x74, 0x11, 0x9d, 0x28, 0xb0, 0x51, 0x52, 0x81, 0xd2, 0xb6, 0xe0, + 0xe7, 0x4c, 0xf1, 0xd4, 0xe5, 0x44, 0xb6, 0x17, 0x18, 0x7d, 0x85, 0xc1, 0xb7, 0xfa, 0x0d, 0x2f, + 0x36, 0xb9, 0x69, 0xd7, 0xba, 0x6f, 0xf7, 0x16, 0xba, 0x1b, 0xcc, 0x32, 0x55, 0x4a, 0xfe, 0xb8, + 0xb0, 0xa5, 0xca, 0xa9, 0xd5, 0x20, 0xa9, 0xe1, 0xf2, 0x6f, 0x13, 0x7a, 0x2b, 0xda, 0x23, 0x16, + 0x83, 0xff, 0x5d, 0x23, 0xb7, 0xf5, 0x23, 0x2b, 0xbb, 0x0b, 0x0a, 0xc7, 0x84, 0x3e, 0x69, 0xad, + 0xf4, 0x4a, 0xa5, 0x18, 0x35, 0xdc, 0x9f, 0x1b, 0x93, 0xfe, 0x69, 0xe2, 0x4a, 0x73, 0xc5, 0x0f, + 0xee, 0xcc, 0xa0, 0xbf, 0x96, 0x46, 0x28, 0x67, 0xcf, 0x80, 0xaa, 0x34, 0x60, 0x78, 0x73, 0x8e, + 0x1a, 0x3f, 0x7a, 0xb4, 0xae, 0x1f, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0x63, 0xf5, 0x69, 0x69, + 0xf1, 0x02, 0x00, 0x00, } diff --git a/dfssc/api/client.proto b/dfssc/api/client.proto index 79b5382725956d38de0fb584fa6f706a39792e71..d2c48546d8fb394d4756b4a8c7ea6fbdc20cf57f 100644 --- a/dfssc/api/client.proto +++ b/dfssc/api/client.proto @@ -30,8 +30,13 @@ message Context { bytes contractDocumentHash = 5; /// The unique signature attemp ID, as provided by the platform during the ready signal string signatureUUID = 6; + /// The TTP address provided by the platform, to use in case of issue during signature. + /// Empty if no TTP used. + string ttpAddrPort = 7; + /// The TTP certificate SHA-512 hash + bytes ttpHash = 8; /// The signed metadata seal, as provided by the platform during the ready signal - bytes seal = 7; + bytes seal = 10; } message Promise { diff --git a/dfssc/sign/promises.go b/dfssc/sign/promises.go index e5d35590e2b133ad2cccc549100e8b8652fc0633..9144921efcc964168a46ec59fe9d0d6e885887a8 100644 --- a/dfssc/sign/promises.go +++ b/dfssc/sign/promises.go @@ -25,6 +25,8 @@ func (m *SignatureManager) createContext(from, to uint32) (*cAPI.Context, error) Signers: m.keyHash, ContractDocumentHash: h, SignatureUUID: m.uuid, + TtpAddrPort: m.ttpData.Addrport, + TtpHash: m.ttpData.Hash, Seal: m.seal, }, nil } diff --git a/dfssc/sign/protocol.go b/dfssc/sign/protocol.go index 3c7a52ff5969991d6bf14ea52ce28ee98b3383f3..167ad23c516049221b5524bc19a115436e4871ed 100644 --- a/dfssc/sign/protocol.go +++ b/dfssc/sign/protocol.go @@ -14,9 +14,9 @@ import ( dAPI "dfss/dfssd/api" tAPI "dfss/dfsst/api" "dfss/net" + "github.com/spf13/viper" "golang.org/x/net/context" "google.golang.org/grpc" - "github.com/spf13/viper" ) // Sign performs all the message exchanges for the contract to be signed @@ -49,8 +49,10 @@ func (m *SignatureManager) Sign() error { // Promess rounds // Follow the sequence until there is no next occurence of me + round := 0 for m.currentIndex >= 0 { - stopIfNeeded(m.currentIndex) + round = round + 1 + stopIfNeeded(round) m.OnProgressUpdate(m.currentIndex, seqLen+1) time.Sleep(viper.GetDuration("slowdown")) dAPI.DLog("starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "] with nextIndex=" + fmt.Sprintf("%d", nextIndex)) @@ -132,7 +134,7 @@ func (m *SignatureManager) promiseRound(pendingSet, sendSet []common.SequenceCoo return m.resolve() } - case <-time.After(time.Minute): + case <-time.After(net.DefaultTimeout): return m.resolve() } } @@ -235,16 +237,20 @@ func (m *SignatureManager) callForResolve() (*tAPI.TTPResponse, error) { // resolve : calls for the resolution, and persists the contract if obtained. func (m *SignatureManager) resolve() error { if m.ttp == nil { + dAPI.DLog("unable to contact TTP") return errors.New("No connection to TTP, aborting!") } + dAPI.DLog("contacting TTP") response, err := m.callForResolve() if err != nil { return err } if response.Abort { + dAPI.DLog("contacted TTP, received abort token") return nil } + dAPI.DLog("contacted TTP, received signed contract") return ioutil.WriteFile(m.mail+"-"+m.contract.UUID+".proof", response.Contract, 0600) } @@ -283,7 +289,7 @@ func stopIfNeeded(index int) { return } - if index == -1 && s == -1 || index+1 == s { + if index == -1 && s == -1 || index == s { os.Exit(0) } -} \ No newline at end of file +} diff --git a/dfssc/sign/starter.go b/dfssc/sign/starter.go index 49b2102cfead94c7e4002ce7de3877fa8cccd8b5..af2280410f757877579d0126d096a994b27c8234 100644 --- a/dfssc/sign/starter.go +++ b/dfssc/sign/starter.go @@ -1,8 +1,6 @@ package sign import ( - "crypto/rsa" - "crypto/x509" "errors" "fmt" "strconv" @@ -34,6 +32,7 @@ type SignatureManager struct { platform pAPI.PlatformClient platformConn *grpc.ClientConn ttp tAPI.TTPClient + ttpData *pAPI.LaunchSignature_TTP peersConn map[string]*grpc.ClientConn peers map[string]*cAPI.ClientClient hashToID map[string]uint32 @@ -98,12 +97,6 @@ func NewSignatureManager(passphrase string, c *contract.JSON) (*SignatureManager m.platform = pAPI.NewPlatformClient(connp) m.platformConn = connp - // connect to the ttp - connt, err := m.connectToTTP(m.auth.Cert, m.auth.Key, m.auth.CA) - if err == nil { - m.ttp = tAPI.NewTTPClient(connt) - } - m.peersConn = make(map[string]*grpc.ClientConn) m.peers = make(map[string]*cAPI.ClientClient) for _, u := range c.Signers { @@ -119,17 +112,6 @@ func NewSignatureManager(passphrase string, c *contract.JSON) (*SignatureManager return m, nil } -// connectToTTP : tries to open a connection with the ttp specified in the contract. -// If there was no specified ttp, returns an error. -// Otherwise, returns the connection, or an error if something else occured. -func (m *SignatureManager) connectToTTP(cert *x509.Certificate, key *rsa.PrivateKey, ca *x509.Certificate) (*grpc.ClientConn, error) { - if m.contract.TTP == nil { - return nil, errors.New("No specified ttp in contract") - } - addrPort := m.contract.TTP.IP + ":" + string(m.contract.TTP.Port) - return net.Connect(addrPort, cert, key, ca, nil) -} - // ConnectToPeers tries to fetch the list of users for this contract, and tries to establish a connection to each peer. func (m *SignatureManager) ConnectToPeers() error { localIps, err := net.ExternalInterfaceAddr() @@ -299,6 +281,9 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) { } } + // Connect to TTP, if any + err = m.connectToTTP(launch.Ttp) + m.sequence = launch.Sequence m.uuid = launch.SignatureUuid m.keyHash = launch.KeyHash @@ -307,6 +292,27 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) { return } +// connectToTTP : tries to open a connection with the ttp specified in the contract. +func (m *SignatureManager) connectToTTP(ttp *pAPI.LaunchSignature_TTP) error { + if ttp == nil { + m.ttpData = &pAPI.LaunchSignature_TTP{ + Addrport: "", + Hash: []byte{}, + } + return nil + } + + // TODO check that the connection spots missing TTP and returns an error quickly enough + conn, err := net.Connect(ttp.Addrport, m.auth.Cert, m.auth.Key, m.auth.CA, ttp.Hash) + if err != nil { + return err + } + + m.ttpData = ttp + m.ttp = tAPI.NewTTPClient(conn) + return nil +} + // Initialize computes the values needed for the start of the signing func (m *SignatureManager) Initialize() (int, error) { myID, err := m.FindID() diff --git a/dfssd/api/demonstrator.pb.go b/dfssd/api/demonstrator.pb.go index b67de87c2750d89f55ebeb4c48846fc3e8d3eaab..bb771ef96c5cea0662a613038198ffa9e2001cdf 100644 --- a/dfssd/api/demonstrator.pb.go +++ b/dfssd/api/demonstrator.pb.go @@ -135,15 +135,16 @@ var _Demonstrator_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 159 bytes of a gzipped FileDescriptorProto + // 167 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x4c, 0x49, 0x2b, 0x2e, 0xd6, 0x07, 0x11, 0x29, 0xfa, 0x89, 0x05, 0x99, 0xfa, 0x29, 0xa9, 0xb9, 0xf9, 0x79, 0xc5, 0x25, - 0x45, 0x89, 0x25, 0xf9, 0x45, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xcc, 0x40, 0x71, 0x25, - 0x4b, 0x2e, 0x66, 0x9f, 0xfc, 0x74, 0x21, 0x41, 0x2e, 0xce, 0x92, 0xcc, 0xdc, 0xd4, 0xe2, 0x92, - 0xc4, 0xdc, 0x02, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x66, 0x21, 0x21, 0x2e, 0xae, 0xcc, 0x94, 0xd4, - 0xbc, 0x92, 0xcc, 0xb4, 0xcc, 0xd4, 0x22, 0x09, 0x26, 0xa0, 0x18, 0xa7, 0x10, 0x37, 0x17, 0x73, - 0x4e, 0x7e, 0xba, 0x04, 0x33, 0x88, 0xa3, 0xc4, 0xca, 0xc5, 0xec, 0x98, 0x9c, 0x6d, 0xa4, 0xcf, - 0xc5, 0xe3, 0x82, 0x64, 0xb8, 0x90, 0x3c, 0x17, 0x7b, 0x70, 0x6a, 0x5e, 0x0a, 0xc8, 0x54, 0x0e, - 0x3d, 0xa0, 0x15, 0x7a, 0x40, 0x96, 0x14, 0x84, 0x05, 0x54, 0xae, 0xc4, 0x90, 0xc4, 0x06, 0xb6, - 0xde, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x16, 0xf4, 0xd0, 0x37, 0xa3, 0x00, 0x00, 0x00, + 0x45, 0x89, 0x25, 0xf9, 0x45, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xcc, 0x40, 0x71, 0xa5, + 0x50, 0x2e, 0x66, 0x9f, 0xfc, 0x74, 0x21, 0x19, 0x2e, 0xce, 0x92, 0xcc, 0xdc, 0xd4, 0xe2, 0x92, + 0xc4, 0xdc, 0x02, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xe6, 0x20, 0x84, 0x80, 0x90, 0x1c, 0x17, 0x57, + 0x66, 0x4a, 0x6a, 0x5e, 0x49, 0x66, 0x5a, 0x66, 0x6a, 0x91, 0x04, 0x13, 0x50, 0x9a, 0x33, 0x08, + 0x49, 0x44, 0x48, 0x80, 0x8b, 0x39, 0x27, 0x3f, 0x5d, 0x82, 0x19, 0x2c, 0x01, 0x62, 0x2a, 0xb1, + 0x72, 0x31, 0x3b, 0x26, 0x67, 0x1b, 0xe9, 0x73, 0xf1, 0xb8, 0x20, 0x59, 0x2c, 0x24, 0xcf, 0xc5, + 0x1e, 0x9c, 0x9a, 0x97, 0x02, 0xb2, 0x91, 0x43, 0x0f, 0x68, 0xbd, 0x1e, 0x90, 0x25, 0x05, 0x61, + 0x01, 0x95, 0x2b, 0x31, 0x24, 0xb1, 0x81, 0x9d, 0x66, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc3, + 0xc3, 0x86, 0x7b, 0xbf, 0x00, 0x00, 0x00, } diff --git a/dfssp/api/platform.pb.go b/dfssp/api/platform.pb.go index 9742fe97e28aab40ab045fffd5eab9abf6f1a06a..3e124bbf17349e632155a182a6cbfd4ae938a42e 100644 --- a/dfssp/api/platform.pb.go +++ b/dfssp/api/platform.pb.go @@ -269,10 +269,12 @@ type LaunchSignature struct { KeyHash [][]byte `protobuf:"bytes,4,rep,name=keyHash,proto3" json:"keyHash,omitempty"` // / The signing sequence generated on-the-fly by the platform Sequence []uint32 `protobuf:"varint,5,rep,name=sequence" json:"sequence,omitempty"` + // / The ttp can be nil if no ttp is available for this signature + Ttp *LaunchSignature_TTP `protobuf:"bytes,6,opt,name=ttp" json:"ttp,omitempty"` // / The cryptographic object of the signature of this structure (seal and errorCode excepted) by the platform, for data certification. // / The signature is computed using auth.SignStructure function: // / PKCS1v15 + SHA512 hash of the string representation of the structure - Seal []byte `protobuf:"bytes,6,opt,name=seal,proto3" json:"seal,omitempty"` + Seal []byte `protobuf:"bytes,10,opt,name=seal,proto3" json:"seal,omitempty"` } func (m *LaunchSignature) Reset() { *m = LaunchSignature{} } @@ -287,6 +289,24 @@ func (m *LaunchSignature) GetErrorCode() *ErrorCode { return nil } +func (m *LaunchSignature) GetTtp() *LaunchSignature_TTP { + if m != nil { + return m.Ttp + } + return nil +} + +// / TTP is the ttp associated to this signature, that should be contacted in case of error +type LaunchSignature_TTP struct { + Addrport string `protobuf:"bytes,1,opt,name=addrport" json:"addrport,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *LaunchSignature_TTP) Reset() { *m = LaunchSignature_TTP{} } +func (m *LaunchSignature_TTP) String() string { return proto.CompactTextString(m) } +func (*LaunchSignature_TTP) ProtoMessage() {} +func (*LaunchSignature_TTP) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} } + func init() { proto.RegisterType((*RegisterRequest)(nil), "api.RegisterRequest") proto.RegisterType((*ErrorCode)(nil), "api.ErrorCode") @@ -301,6 +321,7 @@ func init() { proto.RegisterType((*User)(nil), "api.User") proto.RegisterType((*ReadySignRequest)(nil), "api.ReadySignRequest") proto.RegisterType((*LaunchSignature)(nil), "api.LaunchSignature") + proto.RegisterType((*LaunchSignature_TTP)(nil), "api.LaunchSignature.TTP") proto.RegisterEnum("api.ErrorCode_Code", ErrorCode_Code_name, ErrorCode_Code_value) } @@ -622,47 +643,53 @@ var _Platform_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 666 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0x5d, 0x6f, 0xda, 0x4a, - 0x10, 0xc5, 0xc1, 0xe1, 0x63, 0xc0, 0xc4, 0x5a, 0x88, 0xe2, 0x8b, 0x74, 0xa5, 0xdc, 0xd5, 0x7d, - 0x88, 0xee, 0x95, 0xa0, 0xa5, 0x0f, 0x95, 0xda, 0x97, 0x12, 0x4a, 0x93, 0x54, 0x6d, 0x1a, 0x19, - 0x48, 0x9f, 0x5d, 0x7b, 0x13, 0xdc, 0x60, 0xaf, 0xbb, 0xbb, 0x7e, 0xc8, 0xbf, 0xa8, 0xfa, 0x1f, - 0xfa, 0x37, 0xdb, 0xee, 0xae, 0x3f, 0x0a, 0x94, 0x56, 0xe1, 0x01, 0xb4, 0x3b, 0x33, 0x67, 0xce, - 0x9c, 0x3d, 0x03, 0xfc, 0x1d, 0xdc, 0x70, 0x3e, 0x54, 0x5f, 0xc9, 0xd0, 0x4b, 0xc2, 0x61, 0xb2, - 0xf2, 0xc4, 0x0d, 0x65, 0xd1, 0x20, 0x61, 0x54, 0x50, 0x54, 0x95, 0x77, 0xf8, 0x31, 0x1c, 0xb8, - 0xe4, 0x36, 0xe4, 0x82, 0x30, 0x97, 0x7c, 0x4a, 0x09, 0x17, 0xc8, 0x82, 0x7d, 0x12, 0x79, 0xe1, - 0xca, 0x31, 0x8e, 0x8d, 0x93, 0x26, 0x3a, 0x80, 0x3a, 0xcb, 0x22, 0xce, 0x9e, 0xba, 0xc0, 0x5f, - 0x0d, 0x68, 0x4e, 0x19, 0xa3, 0x6c, 0x42, 0x03, 0x82, 0xfe, 0x01, 0xd3, 0x97, 0xbf, 0x3a, 0xb9, - 0x33, 0xea, 0x0e, 0x24, 0xe8, 0xa0, 0x8c, 0x0e, 0x74, 0x8a, 0x44, 0x88, 0x08, 0xe7, 0xde, 0x2d, - 0xc9, 0x11, 0x02, 0x30, 0x75, 0xa0, 0x05, 0xf5, 0xd9, 0x62, 0x32, 0x99, 0xce, 0x66, 0x76, 0x05, - 0x01, 0xd4, 0x2e, 0x2e, 0xaf, 0xc7, 0xee, 0x99, 0x6d, 0xa8, 0xc0, 0xe9, 0xf8, 0xe5, 0x78, 0x31, - 0x3f, 0xb7, 0xf7, 0xd4, 0xe1, 0xfd, 0xd8, 0xbd, 0xbc, 0xb8, 0x3c, 0xb3, 0xab, 0xa8, 0xab, 0xb2, - 0xe6, 0x53, 0xd7, 0xb5, 0xbf, 0x17, 0x1f, 0x03, 0xf5, 0xa0, 0x3e, 0xbf, 0x78, 0x3b, 0x7d, 0xb7, - 0x98, 0xdb, 0xdf, 0xca, 0x5b, 0xfc, 0x3f, 0xb4, 0xc6, 0xa9, 0x58, 0xfe, 0x66, 0x2c, 0x79, 0x14, - 0xf4, 0x8e, 0xc4, 0x39, 0xa5, 0x7f, 0xa1, 0x53, 0xe8, 0x40, 0x82, 0x05, 0x27, 0x0c, 0x49, 0x42, - 0xfe, 0x2a, 0x24, 0xb1, 0x98, 0x10, 0x26, 0xb2, 0x22, 0x5c, 0x87, 0xfd, 0x69, 0x94, 0x88, 0x7b, - 0x7c, 0x0d, 0xdd, 0x2b, 0xca, 0xc5, 0x84, 0xc6, 0x82, 0x79, 0xbe, 0x28, 0x7a, 0xb4, 0xc1, 0x5c, - 0x7a, 0x7c, 0xa9, 0xb3, 0xdb, 0xc8, 0x86, 0xc6, 0x4d, 0xb8, 0x22, 0xb1, 0x17, 0xe5, 0x83, 0xa3, - 0x0e, 0xd4, 0x78, 0x78, 0x1b, 0x13, 0xe6, 0x54, 0x8f, 0xab, 0x99, 0xb6, 0x3e, 0x8d, 0x22, 0xd9, - 0xc4, 0x31, 0x75, 0x03, 0x0c, 0xe8, 0x8c, 0xec, 0x82, 0x4d, 0xd3, 0x30, 0xc8, 0x49, 0x3c, 0x87, - 0x46, 0x91, 0x20, 0xd5, 0x6f, 0x92, 0x42, 0x6c, 0x1d, 0x6e, 0x8d, 0x3a, 0x9b, 0x4f, 0xa0, 0x8a, - 0x3f, 0x72, 0x9a, 0xcd, 0xd9, 0xc6, 0xaf, 0xa0, 0xf7, 0x9a, 0x86, 0xf1, 0x4c, 0xb2, 0xf0, 0x44, - 0xca, 0x48, 0xd1, 0xa2, 0x07, 0x6d, 0x3f, 0x07, 0x5d, 0x94, 0xad, 0x54, 0x6d, 0x42, 0x59, 0xf6, - 0xf0, 0x96, 0x14, 0x64, 0x2f, 0x4c, 0x32, 0xe6, 0xd8, 0x03, 0x4b, 0xa9, 0x24, 0x89, 0xc4, 0xc4, - 0x17, 0x24, 0x78, 0x08, 0x93, 0xed, 0x1e, 0x99, 0x26, 0x47, 0x72, 0x38, 0xae, 0x15, 0x51, 0x35, - 0x4d, 0x5d, 0xa3, 0xa0, 0xf1, 0x0b, 0x30, 0xf5, 0x43, 0x48, 0x91, 0xee, 0xc8, 0xfd, 0xf9, 0x4f, - 0x5d, 0xcb, 0x97, 0xcc, 0x00, 0xd6, 0x68, 0x95, 0x84, 0x95, 0x9a, 0x16, 0x3e, 0x01, 0xdb, 0x25, - 0x5e, 0x70, 0xaf, 0xa6, 0xfd, 0xe3, 0xa0, 0xf8, 0x8b, 0x01, 0x07, 0x6f, 0xbc, 0x34, 0xf6, 0x97, - 0xa5, 0x32, 0x0f, 0x99, 0xe8, 0x10, 0x2c, 0x5e, 0xe4, 0xaf, 0x8d, 0x24, 0x7b, 0x04, 0xd4, 0x4f, - 0xd5, 0xbb, 0x6a, 0xda, 0x55, 0x4d, 0x7b, 0x6d, 0x0e, 0x53, 0x92, 0xd5, 0xfe, 0xe0, 0x8a, 0x55, - 0xec, 0x13, 0x67, 0x5f, 0xde, 0x58, 0x8a, 0x3e, 0x27, 0xde, 0xca, 0xa9, 0xa9, 0x82, 0xd1, 0xe7, - 0x2a, 0x34, 0xae, 0xf2, 0x9d, 0x45, 0x23, 0x68, 0x14, 0x06, 0x45, 0x3d, 0x4d, 0x63, 0x6b, 0x6f, - 0xfb, 0x5b, 0xe4, 0x70, 0x05, 0x0d, 0xc1, 0x54, 0x1b, 0x80, 0x6c, 0x1d, 0x59, 0x5b, 0x86, 0x7e, - 0x77, 0x03, 0x21, 0x73, 0xbc, 0x2c, 0xf8, 0x0f, 0x60, 0x11, 0xb3, 0xa2, 0x0d, 0x64, 0x80, 0xca, - 0xf0, 0x3b, 0xc0, 0x9f, 0x41, 0x7b, 0x7d, 0x05, 0x90, 0xa3, 0x33, 0x76, 0x6c, 0xc5, 0x8e, 0xda, - 0xa7, 0xd0, 0x5a, 0xb3, 0x39, 0x3a, 0xd2, 0x09, 0xbf, 0x1a, 0xbf, 0x6f, 0xe9, 0x40, 0x71, 0x2b, - 0x0b, 0x4f, 0xc1, 0xda, 0xb0, 0x2f, 0xfa, 0x4b, 0x67, 0xec, 0xb2, 0x74, 0x1f, 0x95, 0x56, 0x2a, - 0x5d, 0x8a, 0x2b, 0x8f, 0x0c, 0x49, 0xbc, 0x59, 0xba, 0x02, 0x1d, 0xe6, 0x42, 0x6c, 0xba, 0xa4, - 0x9f, 0x29, 0xbc, 0xe5, 0x08, 0x5c, 0xf9, 0x50, 0xd3, 0x7f, 0x9d, 0x4f, 0x7e, 0x04, 0x00, 0x00, - 0xff, 0xff, 0x9e, 0x01, 0x0b, 0x56, 0x5b, 0x05, 0x00, 0x00, + // 768 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x55, 0xdd, 0x6e, 0xd3, 0x4a, + 0x10, 0x4e, 0x62, 0x37, 0x3f, 0x93, 0x26, 0xb5, 0x36, 0x39, 0xe7, 0xf8, 0x44, 0xea, 0x51, 0xb5, + 0x3a, 0x12, 0x55, 0x85, 0x92, 0x2a, 0x08, 0x10, 0xdc, 0xa5, 0x21, 0x6a, 0x8b, 0x4a, 0xa9, 0x36, + 0x09, 0x48, 0x5c, 0x20, 0x19, 0x7b, 0xdb, 0x98, 0x26, 0xb6, 0xd9, 0xdd, 0x08, 0xf5, 0x8e, 0x47, + 0xe0, 0x61, 0x10, 0x8f, 0x07, 0xec, 0xae, 0x7f, 0xe2, 0x84, 0x08, 0xa9, 0xbd, 0x70, 0x77, 0x7e, + 0x76, 0xe6, 0x9b, 0x6f, 0x67, 0x26, 0xb0, 0xef, 0x5d, 0x73, 0xde, 0x53, 0x9f, 0xa8, 0xe7, 0x44, + 0x7e, 0x2f, 0x9a, 0x3b, 0xe2, 0x3a, 0x64, 0x8b, 0x6e, 0xc4, 0x42, 0x11, 0x22, 0x43, 0xea, 0xf0, + 0x00, 0xf6, 0x08, 0xbd, 0xf1, 0xb9, 0xa0, 0x8c, 0xd0, 0x4f, 0x4b, 0xca, 0x05, 0x6a, 0xc3, 0x0e, + 0x5d, 0x38, 0xfe, 0xdc, 0x2e, 0x1e, 0x14, 0x0f, 0x6b, 0x24, 0x16, 0x90, 0x0d, 0x15, 0x16, 0x3b, + 0xd8, 0x25, 0xad, 0x4f, 0x45, 0xfc, 0xad, 0x08, 0xb5, 0x11, 0x63, 0x21, 0x1b, 0x86, 0x1e, 0x45, + 0x0f, 0xc0, 0x74, 0xe5, 0x7f, 0x7d, 0xb9, 0xd9, 0x6f, 0x75, 0x65, 0x92, 0x6e, 0x66, 0xed, 0xaa, + 0x0f, 0xd1, 0x0e, 0x2a, 0xe0, 0x82, 0x72, 0xee, 0xdc, 0xd0, 0x34, 0x60, 0x22, 0x62, 0x0f, 0x4c, + 0x1d, 0xaa, 0x0e, 0x95, 0xf1, 0x74, 0x38, 0x1c, 0x8d, 0xc7, 0x56, 0x01, 0x01, 0x94, 0xcf, 0x2f, + 0xdf, 0x0c, 0xc8, 0xa9, 0x55, 0x54, 0x86, 0x93, 0xc1, 0x8b, 0xc1, 0x74, 0x72, 0x66, 0x95, 0x94, + 0xf0, 0x76, 0x40, 0x2e, 0xcf, 0x2f, 0x4f, 0x2d, 0x03, 0xb5, 0x94, 0xd7, 0x64, 0x44, 0x88, 0xf5, + 0x33, 0xfd, 0x2b, 0xca, 0x82, 0x2a, 0x93, 0xf3, 0x57, 0xa3, 0xd7, 0xd3, 0x89, 0xf5, 0x23, 0xd3, + 0xe2, 0x67, 0x50, 0x1f, 0x2c, 0xc5, 0xec, 0xcf, 0x55, 0x4b, 0xad, 0x08, 0x6f, 0x69, 0x90, 0x40, + 0x8c, 0x05, 0x7c, 0x0c, 0xcd, 0x94, 0x34, 0xea, 0x4d, 0x39, 0x65, 0xe8, 0x3f, 0x00, 0x77, 0xee, + 0xd3, 0x40, 0x0c, 0x29, 0x13, 0x49, 0x88, 0x9c, 0x06, 0x57, 0x60, 0x67, 0xb4, 0x88, 0xc4, 0x1d, + 0xfe, 0x0c, 0xad, 0xab, 0x90, 0x8b, 0x61, 0x18, 0x08, 0xe6, 0xb8, 0x22, 0xcd, 0x8e, 0xc0, 0x9c, + 0x39, 0x7c, 0xa6, 0x6f, 0xee, 0x12, 0x7d, 0x46, 0x1d, 0xa8, 0x5e, 0xfb, 0x73, 0x1a, 0x38, 0x8b, + 0x94, 0xa1, 0x4c, 0x46, 0x7f, 0x43, 0x99, 0xfb, 0x37, 0x01, 0x65, 0xb6, 0x71, 0x60, 0x48, 0x4b, + 0x22, 0x29, 0x52, 0xdd, 0x70, 0xb1, 0x90, 0x69, 0x6d, 0x33, 0x26, 0x35, 0x11, 0xf1, 0x21, 0xa0, + 0x53, 0xba, 0x2d, 0xef, 0x72, 0xe9, 0x7b, 0x09, 0x62, 0x7d, 0xc6, 0x17, 0x50, 0x4d, 0xdd, 0xd0, + 0x43, 0xa8, 0xd1, 0xf4, 0xf1, 0xb4, 0x53, 0xbd, 0xdf, 0x5c, 0x7f, 0x52, 0xb2, 0x72, 0x50, 0xd1, + 0x3e, 0xf2, 0x30, 0x26, 0x4b, 0x56, 0xa1, 0xce, 0xf8, 0x3d, 0xb4, 0x5f, 0x86, 0x7e, 0x30, 0x96, + 0xf8, 0x1c, 0xb1, 0x64, 0x34, 0xcd, 0x8c, 0x61, 0xd7, 0x4d, 0xb2, 0x4c, 0x57, 0x08, 0xd6, 0x74, + 0x2a, 0x5e, 0x14, 0xb2, 0xb8, 0xe1, 0x1a, 0x44, 0x9f, 0x51, 0x13, 0x4a, 0x7e, 0x94, 0x54, 0x2d, + 0x4f, 0xf8, 0x4b, 0x11, 0x1a, 0xea, 0x09, 0x24, 0xe4, 0x80, 0xba, 0x82, 0x7a, 0xf7, 0xc4, 0xbc, + 0x89, 0xa3, 0xb4, 0x05, 0xc7, 0xbe, 0x64, 0x89, 0x6b, 0xae, 0x55, 0xb0, 0x9a, 0x0e, 0xa6, 0x72, + 0x12, 0xad, 0xc6, 0xef, 0xc0, 0xd4, 0x4d, 0x20, 0xc9, 0xbf, 0xa5, 0x77, 0x67, 0xab, 0x77, 0x4c, + 0xc5, 0x55, 0x73, 0x95, 0xf2, 0xcd, 0xb5, 0x51, 0x4a, 0x56, 0xae, 0xb9, 0x2a, 0x17, 0x3f, 0x01, + 0x8b, 0x50, 0xc7, 0xbb, 0x53, 0xfc, 0xdd, 0x83, 0x3a, 0xfc, 0xbd, 0x04, 0x7b, 0x17, 0xce, 0x32, + 0x70, 0x67, 0x19, 0xf3, 0xf7, 0x24, 0xe6, 0x7f, 0x68, 0xf0, 0xf4, 0x6a, 0x8e, 0x99, 0x75, 0xa5, + 0xc2, 0xe2, 0x85, 0xee, 0x52, 0xb5, 0x98, 0x2e, 0xdc, 0xd0, 0x85, 0xaf, 0xe9, 0xf2, 0xbc, 0x98, + 0xb2, 0xd8, 0x1c, 0x2f, 0xb2, 0xc5, 0xb9, 0x2a, 0x2a, 0x70, 0xa9, 0xbd, 0x23, 0x4d, 0x0d, 0x92, + 0xc9, 0xe8, 0x08, 0x0c, 0x21, 0x22, 0xbb, 0xac, 0x71, 0xda, 0x1a, 0xe7, 0x46, 0x41, 0xdd, 0xc9, + 0xe4, 0x8a, 0x28, 0x27, 0xc5, 0x1c, 0xa7, 0xce, 0xdc, 0x86, 0xb8, 0xf1, 0xd4, 0xb9, 0xf3, 0x18, + 0x0c, 0x69, 0x57, 0x29, 0x1c, 0xcf, 0x63, 0x9a, 0xd8, 0x98, 0xa8, 0x4c, 0xce, 0xa6, 0xae, 0xb4, + 0x9a, 0xba, 0xfe, 0x57, 0x03, 0xaa, 0x57, 0xc9, 0xa2, 0x44, 0x7d, 0xa8, 0xa6, 0x83, 0x8e, 0xda, + 0x1a, 0xc2, 0xc6, 0xb2, 0xec, 0x6c, 0x10, 0x88, 0x0b, 0xa8, 0x07, 0xa6, 0xda, 0x2b, 0xc8, 0xd2, + 0x96, 0xdc, 0x8a, 0xe9, 0xb4, 0xd6, 0x22, 0xc4, 0x9b, 0x43, 0x5e, 0x38, 0x02, 0x98, 0x06, 0x2c, + 0x4d, 0x03, 0x71, 0x40, 0xb5, 0x2c, 0xb6, 0x04, 0x7f, 0x0e, 0xbb, 0xf9, 0xf5, 0x81, 0x62, 0x5e, + 0xb6, 0x6c, 0x94, 0x2d, 0x77, 0x9f, 0x42, 0x3d, 0xb7, 0x01, 0xd0, 0x3f, 0xda, 0xe1, 0xf7, 0x9d, + 0xd0, 0x69, 0x68, 0x43, 0xaa, 0x95, 0x17, 0x4f, 0xa0, 0xb1, 0x36, 0xc2, 0xe8, 0x5f, 0xed, 0xb1, + 0x6d, 0xac, 0x3b, 0x28, 0x1b, 0x8e, 0x6c, 0x20, 0x71, 0xe1, 0xb8, 0x28, 0x81, 0xd7, 0xb2, 0x3e, + 0x46, 0x7f, 0x25, 0x44, 0xac, 0xf7, 0x75, 0xa7, 0xbd, 0xed, 0x91, 0x71, 0xe1, 0x43, 0x59, 0xff, + 0x5e, 0x3d, 0xfa, 0x15, 0x00, 0x00, 0xff, 0xff, 0x31, 0x18, 0xb6, 0x50, 0xd0, 0x06, 0x00, 0x00, } diff --git a/dfssp/api/platform.proto b/dfssp/api/platform.proto index c4d92ef76f7074d0b1f3d70ba40c057f5e42965f..210f63a2f5a0bb4df643cc4edab815f7fe414a99 100644 --- a/dfssp/api/platform.proto +++ b/dfssp/api/platform.proto @@ -144,8 +144,15 @@ message LaunchSignature { repeated bytes keyHash = 4; /// The signing sequence generated on-the-fly by the platform repeated uint32 sequence = 5; + /// TTP is the ttp associated to this signature, that should be contacted in case of error + message TTP { + string addrport = 1; + bytes hash = 2; + } + /// The ttp can be nil if no ttp is available for this signature + TTP ttp = 6; /// The cryptographic object of the signature of this structure (seal and errorCode excepted) by the platform, for data certification. /// The signature is computed using auth.SignStructure function: /// PKCS1v15 + SHA512 hash of the string representation of the structure - bytes seal = 6; + bytes seal = 10; } diff --git a/dfssp/authority/rootCA.go b/dfssp/authority/rootCA.go index ca568df3ec5b3131fcd151a63eeb8c985a799501..406913f5f825c375da99e6d83b1e3048f3b9102d 100644 --- a/dfssp/authority/rootCA.go +++ b/dfssp/authority/rootCA.go @@ -22,12 +22,13 @@ type PlatformID struct { // Initialize creates and saves the platform's private key and root certificate to a PEM format. // If ca and rKey are not nil, they will be used as the root certificate and root private key instead of creating a ones. // The files are saved at the specified path by viper. -func Initialize(v *viper.Viper, ca *x509.Certificate, rKey *rsa.PrivateKey) error { +// The returned `hash` is the SHA-512 hash of the generated certificate. +func Initialize(v *viper.Viper, ca *x509.Certificate, rKey *rsa.PrivateKey) (hash []byte, err error) { // Generate the private key. key, err := auth.GeneratePrivateKey(v.GetInt("key_size")) if err != nil { - return err + return nil, err } var cert []byte @@ -50,24 +51,25 @@ func Initialize(v *viper.Viper, ca *x509.Certificate, rKey *rsa.PrivateKey) erro } if err != nil { - return err + return nil, err } // Create missing folders, if needed err = os.MkdirAll(path, os.ModeDir|0700) if err != nil { - return err + return nil, err } // Convert the private key to a PEM format, and save it. keyPem := auth.PrivateKeyToPEM(key) err = ioutil.WriteFile(keyPath, keyPem, 0600) if err != nil { - return err + return nil, err } // Save the root certificate. - return ioutil.WriteFile(certPath, cert, 0600) + rawCert, _ := auth.PEMToCertificate(cert) // TODO optimize this... + return auth.GetCertificateHash(rawCert), ioutil.WriteFile(certPath, cert, 0600) } // Start fetches the platform's private rsa key and root certificate, and create a PlatformID accordingly. diff --git a/dfssp/authority/rootCA_test.go b/dfssp/authority/rootCA_test.go index b97bc871d9c64590247e383cef6ff9e29607972c..b22ba304acb95639149ff11ff95879cf8c8bf028 100644 --- a/dfssp/authority/rootCA_test.go +++ b/dfssp/authority/rootCA_test.go @@ -8,10 +8,9 @@ import ( "path/filepath" "testing" - "github.com/spf13/viper" - "dfss/auth" "dfss/dfssc/common" + "github.com/spf13/viper" ) var ( @@ -36,9 +35,9 @@ func TestInitialize(t *testing.T) { certPath := filepath.Join(path, RootCAFileName) v := common.MockViper("key_size", 1024, "validity", 365, "country", "country", "organization", "organization", "unit", "unit", "cn", "cn", "path", path) - err := Initialize(v, nil, nil) + hash, err := Initialize(v, nil, nil) - if err != nil { + if err != nil || hash == nil { t.Fatal(err) } @@ -60,8 +59,8 @@ func Example() { // Generate root certificate and key v := common.MockViper("key_size", 1024, "validity", 365, "country", "UK", "organization", "DFSS", "unit", "unit", "cn", "ROOT", "path", path) - err := Initialize(v, nil, nil) - if err != nil { + hash, err := Initialize(v, nil, nil) + if err != nil || hash == nil { fmt.Println(err) return } @@ -79,7 +78,7 @@ func Example() { // Generate child certificate and key childPath := filepath.Join(path, "child") v = common.MockViper("key_size", 1024, "validity", 10, "country", "FR", "organization", "DFSS", "unit", "unit", "cn", "CHILD", "path", childPath) - err = Initialize(v, pid.RootCA, pid.Pkey) + _, err = Initialize(v, pid.RootCA, pid.Pkey) if err != nil { fmt.Println(err) return @@ -107,7 +106,7 @@ func CheckFile(path, name string) { func TestStart(t *testing.T) { path, _ := ioutil.TempDir("", "") v := common.MockViper("key_size", 1024, "validity", 365, "country", "country", "organization", "organization", "unit", "unit", "cn", "cn", "path", path) - _ = Initialize(v, nil, nil) + _, _ = Initialize(v, nil, nil) pid, err := Start(path) if err != nil { diff --git a/dfssp/authority/testdata/corrupted_ttps b/dfssp/authority/testdata/corrupted_ttps new file mode 100644 index 0000000000000000000000000000000000000000..318583d4fae4d7a55fd85586dac2931bfc8cf386 --- /dev/null +++ b/dfssp/authority/testdata/corrupted_ttps @@ -0,0 +1 @@ +wrongline diff --git a/dfssp/authority/testdata/ttps b/dfssp/authority/testdata/ttps new file mode 100644 index 0000000000000000000000000000000000000000..594a8f6ec5df375e242f2171bab550594ebf1a09 --- /dev/null +++ b/dfssp/authority/testdata/ttps @@ -0,0 +1,2 @@ +1.2.3.4:9005 aabbcc +192.168.1.1:36500 0123456789 diff --git a/dfssp/authority/ttp.go b/dfssp/authority/ttp.go new file mode 100644 index 0000000000000000000000000000000000000000..ead05fcc97a72ddb373cbfc6d7622370ea398d87 --- /dev/null +++ b/dfssp/authority/ttp.go @@ -0,0 +1,108 @@ +package authority + +import ( + "encoding/hex" + "errors" + "io/ioutil" + "strconv" + "strings" + "sync" + + "dfss/dfssp/api" +) + +// TTPHolder stores available TTPs (trusted third parties) +type TTPHolder struct { + ttps []*api.LaunchSignature_TTP + next int + mutex *sync.Mutex +} + +// NewTTPHolder loads available TTPs from the specified file. +// The format of this file should be as-is: +// +// [:\n +// ... +// +// Example: see testdata/ttps. +// If an error occurs during the retrieval of the file, an empty TTPHolder will be provided. +// If the file is corrupted (wrong format), and error will be thrown. +func NewTTPHolder(filename string) (*TTPHolder, error) { + data, err := ioutil.ReadFile(filename) + if err != nil { + data = []byte{} + } + + lines := strings.Split(string(data), "\n") + ttps := make([]*api.LaunchSignature_TTP, len(lines)-1) // -1 to ignore last string (empty) + for i := 0; i < len(lines)-1; i++ { + line := lines[i] + words := strings.Split(line, " ") + if len(words) < 2 { + return nil, errors.New("corrupted ttp file: not enough words at line " + strconv.Itoa(i)) + } + hash, err := hex.DecodeString(words[1]) + if err != nil { + return nil, errors.New("corrupted ttp file: invalid hash at line " + strconv.Itoa(i)) + } + ttps[i] = &api.LaunchSignature_TTP{ + Addrport: words[0], + Hash: hash, + } + } + + holder := &TTPHolder{ + ttps: ttps, + next: 0, + mutex: &sync.Mutex{}, + } + + return holder, nil +} + +// Nb returns the number of loaded TTP in this holder. +func (h *TTPHolder) Nb() int { + return len(h.ttps) +} + +// Get returns a TTP from the TTP holder. +// It is thread-safe, and base on a round-robin system. +// +// If the TTPHolder is empty, returns nil. +func (h *TTPHolder) Get() *api.LaunchSignature_TTP { + if h.Nb() == 0 { + return nil + } + + h.mutex.Lock() + defer h.mutex.Unlock() + + if len(h.ttps) == h.next { + h.next = 0 + } + + ttp := h.ttps[h.next] + h.next++ + return ttp +} + +// Add adds the provided TTP to the TTP holder. +// It is thread-safe. +func (h *TTPHolder) Add(addrport string, hash []byte) { + h.mutex.Lock() + defer h.mutex.Unlock() + + h.ttps = append(h.ttps, &api.LaunchSignature_TTP{ + Addrport: addrport, + Hash: hash, + }) +} + +// Save saves the TTP holder in a file, respecting the same format as presented in the loader. +func (h *TTPHolder) Save(filename string) error { + data := "" + for _, ttp := range h.ttps { + data += ttp.Addrport + " " + hex.EncodeToString(ttp.Hash) + "\n" + } + return ioutil.WriteFile(filename, []byte(data), 0600) +} diff --git a/dfssp/authority/ttp_test.go b/dfssp/authority/ttp_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7f164d32d28aff8ccb798cbda336f589a903620f --- /dev/null +++ b/dfssp/authority/ttp_test.go @@ -0,0 +1,62 @@ +package authority + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTTPHolderNewFile(t *testing.T) { + // Load from a missing file + holder, err := NewTTPHolder("holder") + assert.NotNil(t, holder) + assert.Nil(t, err) + + ttp := holder.Get() + assert.Nil(t, ttp) + assert.Equal(t, 0, holder.Nb()) + + holder.Add("1.2.3.4", []byte{0x01, 0xff}) + holder.Add("localhost:9000", []byte{0xaa}) + assert.Equal(t, 2, holder.Nb()) + + err = holder.Save("holder") + assert.Nil(t, err) + + res, _ := ioutil.ReadFile("holder") + assert.Equal(t, "1.2.3.4 01ff\nlocalhost:9000 aa\n", fmt.Sprintf("%s", res)) + + _ = os.Remove("holder") +} + +func TestTTPHolderRetrieveFile(t *testing.T) { + holder, err := NewTTPHolder(filepath.Join("testdata", "ttps")) + assert.NotNil(t, holder) + assert.Nil(t, err) + assert.Equal(t, 2, holder.Nb()) + + ttp := holder.Get() + assert.NotNil(t, ttp) + assert.Equal(t, "1.2.3.4:9005", ttp.Addrport) + assert.Equal(t, "aabbcc", fmt.Sprintf("%x", ttp.Hash)) + + ttp = holder.Get() + assert.NotNil(t, ttp) + assert.Equal(t, "192.168.1.1:36500", ttp.Addrport) + assert.Equal(t, "0123456789", fmt.Sprintf("%x", ttp.Hash)) + + ttp = holder.Get() + assert.NotNil(t, ttp) + assert.Equal(t, "1.2.3.4:9005", ttp.Addrport) + assert.Equal(t, "aabbcc", fmt.Sprintf("%x", ttp.Hash)) +} + +func TestTTPHolderRetrieveCorruptedFile(t *testing.T) { + holder, err := NewTTPHolder(filepath.Join("testdata", "corrupted_ttps")) + assert.Nil(t, holder) + assert.NotNil(t, err) +} diff --git a/dfssp/cmd/init.go b/dfssp/cmd/init.go index 4d8379ff9e91ba7e8dd8aecd6ed805cee960ab80..5079eebd31106f23905004b8d14e2ee9344d872d 100644 --- a/dfssp/cmd/init.go +++ b/dfssp/cmd/init.go @@ -5,7 +5,6 @@ import ( "os" "dfss/dfssc/common" - dapi "dfss/dfssd/api" "dfss/dfssp/authority" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -23,11 +22,10 @@ var initCmd = &cobra.Command{ _ = viper.BindPFlag("unit", cmd.Flags().Lookup("unit")) _ = viper.BindPFlag("key_size", cmd.Flags().Lookup("key")) - err := authority.Initialize(common.SubViper("key_size", "validity", "country", "organization", "unit", "cn", "path"), nil, nil) + _, err := authority.Initialize(common.SubViper("key_size", "validity", "country", "organization", "unit", "cn", "path"), nil, nil) if err != nil { fmt.Fprintln(os.Stderr, "An error occured during the initialization operation:", err) os.Exit(1) } - dapi.DLog("Private key and root certificate generated") }, } diff --git a/dfssp/cmd/root.go b/dfssp/cmd/root.go index a17eb16868ea3e719bf45f677db25a9c351de036..03cd567450f05b33405d9b4d3a9479f0c6cb4479 100644 --- a/dfssp/cmd/root.go +++ b/dfssp/cmd/root.go @@ -46,11 +46,14 @@ func init() { ttpCmd.Flags().String("org", "DFSS", "organization for the ttp certificate") ttpCmd.Flags().String("unit", "INSA Rennes", "organizational unit for the ttp certificate") ttpCmd.Flags().IntP("key", "k", 2048, "encoding size for the private key of the ttp") + ttpCmd.Flags().StringP("ttps", "t", "ttps", "file containing available TTPs list") + ttpCmd.Flags().StringP("addr", "a", "localhost:9098", "address of the ttp to be transmitted to signers") startCmd.Flags().IntP("validity", "c", 365, "validity duration for the child certificates (days)") startCmd.Flags().StringP("address", "a", "0.0.0.0", "address to bind for listening") startCmd.Flags().StringP("port", "p", "9000", "port to bind for listening") startCmd.Flags().String("db", "mongodb://localhost/dfss", "server url in standard MongoDB format for accessing database") + startCmd.Flags().StringP("ttps", "t", "", "file containing available TTPs list, disabled by default") // Bind viper to flags _ = viper.BindPFlag("verbose", RootCmd.PersistentFlags().Lookup("verbose")) diff --git a/dfssp/cmd/start.go b/dfssp/cmd/start.go index a54709160f4b79a1d5861f0cec04b40ff16e8250..f312946a2b8e8ce73aa03b83fe10ade5243bc370 100644 --- a/dfssp/cmd/start.go +++ b/dfssp/cmd/start.go @@ -20,6 +20,7 @@ var startCmd = &cobra.Command{ _ = viper.BindPFlag("address", cmd.Flags().Lookup("address")) _ = viper.BindPFlag("port", cmd.Flags().Lookup("port")) _ = viper.BindPFlag("validity", cmd.Flags().Lookup("validity")) + _ = viper.BindPFlag("ttps", cmd.Flags().Lookup("ttps")) address := viper.GetString("address") port := viper.GetString("port") diff --git a/dfssp/cmd/ttp.go b/dfssp/cmd/ttp.go index 0e38e003b62148bda2c14892fdd5073d68a40152..64eb0769243d56de6bc93200d646de8499276c84 100644 --- a/dfssp/cmd/ttp.go +++ b/dfssp/cmd/ttp.go @@ -6,7 +6,6 @@ import ( "path/filepath" "dfss/dfssc/common" - dapi "dfss/dfssd/api" "dfss/dfssp/authority" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -15,6 +14,19 @@ import ( var ttpCmd = &cobra.Command{ Use: "ttp", Short: "create and save the TTP's private key and certificate", + Long: `This command creates a new private key and a related certificate for a Trusted Third Party (TTP). +You must run the init command before this one in order to compute root certificate. + +TTP credentials are saved in the ttp folder. You may want to move this folder in another secure place. +In order to provide one TTP per signature, a list must be stored for the platform. +This list is generated and updated with the ttp command, along with the future TTP address and port. +If no list is provided, no TTP will be proposed to signers, and they won't be able to use the resolution protocol. + +You can customize the list location and the TTP address with "-t" and "-a" flags. +For example, to setup a TTP that will run on ttp.example.com:3000 + dfssp ttp -t ttp.example.com:3000 -a storefile.data + +You can setup as many TTPs as you want, but beware certificate and private key are erased between each call of this command.`, Run: func(cmd *cobra.Command, args []string) { _ = viper.BindPFlag("cn", cmd.Flags().Lookup("cn")) @@ -23,6 +35,8 @@ var ttpCmd = &cobra.Command{ _ = viper.BindPFlag("organization", cmd.Flags().Lookup("org")) _ = viper.BindPFlag("unit", cmd.Flags().Lookup("unit")) _ = viper.BindPFlag("key_size", cmd.Flags().Lookup("key")) + _ = viper.BindPFlag("ttps", cmd.Flags().Lookup("ttps")) + _ = viper.BindPFlag("ttp_addr", cmd.Flags().Lookup("addr")) path := viper.GetString("path") @@ -34,11 +48,24 @@ var ttpCmd = &cobra.Command{ ttpPath := filepath.Join(path, "ttp") v := common.SubViper("key_size", "validity", "country", "organization", "unit", "cn") v.Set("path", ttpPath) - err = authority.Initialize(v, pid.RootCA, pid.Pkey) + hash, err := authority.Initialize(v, pid.RootCA, pid.Pkey) if err != nil { fmt.Fprintln(os.Stderr, "An error occured during TTP credentials generation:", err) os.Exit(1) } - dapi.DLog("Private key and certificate generated for TTP") + + // Add this ttp to the ttp holder + holder, err := authority.NewTTPHolder(viper.GetString("ttps")) + if err != nil { + fmt.Fprintln(os.Stderr, "An error occured during TTP list load:", err) + os.Exit(1) + } + + holder.Add(viper.GetString("ttp_addr"), hash) + err = holder.Save(viper.GetString("ttps")) + if err != nil { + fmt.Fprintln(os.Stderr, "An error occured during TTP list save:", err) + os.Exit(1) + } }, } diff --git a/dfssp/contract/create.go b/dfssp/contract/create.go index a050a571e20c4cacc073310bcab6cc553d25f958..e0d0eb122334738a382f700a47b56b8aa8e9ef49 100644 --- a/dfssp/contract/create.go +++ b/dfssp/contract/create.go @@ -152,7 +152,7 @@ func (c *Builder) SendNewContractMail() { return } - file, err := GetJSON(c.Contract, nil) + file, err := GetJSON(c.Contract) if err != nil { log.Println(err) return diff --git a/dfssp/contract/fetch.go b/dfssp/contract/fetch.go index 81e96055c4e2c19c15d05923686607be8ebbedc2..c13a48496b6df3f09cbc3ea28b075126125c628d 100644 --- a/dfssp/contract/fetch.go +++ b/dfssp/contract/fetch.go @@ -23,7 +23,7 @@ func Fetch(db *mgdb.MongoManager, contractUUID string, clientHash []byte) *api.C } } - data, err := GetJSON(contract, nil) + data, err := GetJSON(contract) if err != nil { return &api.Contract{ ErrorCode: &api.ErrorCode{Code: api.ErrorCode_INTERR}, diff --git a/dfssp/contract/file.go b/dfssp/contract/file.go index 7fdebcc955a8517498e02cb7e53b8c8d3c0e47b5..63ed668c931ebada4f2e1c8658e1e0e0a282423a 100644 --- a/dfssp/contract/file.go +++ b/dfssp/contract/file.go @@ -21,12 +21,6 @@ type SignerJSON struct { Hash string } -// TTPJSON is the structure used to store TTP information in JSON format -type TTPJSON struct { - IP string - Port uint -} - // JSON is the structure used to store contract information in JSON format type JSON struct { UUID string @@ -34,11 +28,10 @@ type JSON struct { Comment string File *FileJSON Signers []SignerJSON - TTP *TTPJSON } // GetJSON returns indented json from a contract and some ttp information (nil allowed) -func GetJSON(c *entities.Contract, ttp *TTPJSON) ([]byte, error) { +func GetJSON(c *entities.Contract) ([]byte, error) { data := JSON{ UUID: c.ID.Hex(), Date: &c.Date, @@ -49,7 +42,6 @@ func GetJSON(c *entities.Contract, ttp *TTPJSON) ([]byte, error) { Hosted: c.File.Hosted, }, Signers: make([]SignerJSON, len(c.Signers)), - TTP: ttp, } for i, s := range c.Signers { diff --git a/dfssp/contract/file_test.go b/dfssp/contract/file_test.go index 52948c9cd663549dddde7c4b6f8f4263b4ec9ab6..465a66c686f19d133115f3452402460618654b88 100644 --- a/dfssp/contract/file_test.go +++ b/dfssp/contract/file_test.go @@ -47,11 +47,10 @@ allow multiline and accents: éÉ`, "Email": "b", "Hash": "bb" } - ], - "TTP": null + ] }` - j, err := GetJSON(c, nil) + j, err := GetJSON(c) assert.Equal(t, nil, err) assert.Equal(t, expected, string(j)) diff --git a/dfssp/server/server.go b/dfssp/server/server.go index b47bad748462fb3a5b95a3c0d49745b6aae9b389..83d8fdea66b1eebdd467ba4b041bb4c90ae9c852 100644 --- a/dfssp/server/server.go +++ b/dfssp/server/server.go @@ -22,6 +22,7 @@ type platformServer struct { Pid *authority.PlatformID DB *mgdb.MongoManager Rooms *common.WaitingGroupMap + TTPs *authority.TTPHolder } // Register handler @@ -98,6 +99,7 @@ func (s *platformServer) ReadySign(ctx context.Context, in *api.ReadySignRequest signal := contract.ReadySign(s.DB, s.Rooms, &ctx, in) if signal.ErrorCode.Code == api.ErrorCode_SUCCESS { + signal.Ttp = s.TTPs.Get() // Assign a ttp to this signature, if any available sealedSignal := *signal sealedSignal.ErrorCode = nil sealedSignal.Seal = nil @@ -125,11 +127,21 @@ func GetServer() *grpc.Server { os.Exit(1) } + ttpholder, err := authority.NewTTPHolder(viper.GetString("ttps")) + if err != nil { + fmt.Println("An error occured during the ttp file load:", err) + } + + if ttpholder.Nb() == 0 { + fmt.Println("Warning: no TTP loaded. See `dfssp ttp --help`.") + } + server := net.NewServer(pid.RootCA, pid.Pkey, pid.RootCA) api.RegisterPlatformServer(server, &platformServer{ Pid: pid, DB: dbManager, Rooms: common.NewWaitingGroupMap(), + TTPs: ttpholder, }) return server } diff --git a/dfsst/entities/check_request.go b/dfsst/entities/check_request.go index dc1564d050185cefce92bd622e7619d4dea6e7df..a5105f08e7aa0ca0d236b0d91cfb3ed00bd1f783 100644 --- a/dfsst/entities/check_request.go +++ b/dfsst/entities/check_request.go @@ -143,11 +143,19 @@ func IsPlatformSealValid(promise *cAPI.Promise) bool { return false } + var ttp *pAPI.LaunchSignature_TTP + if promise.Context.TtpAddrPort != "" { + ttp = new(pAPI.LaunchSignature_TTP) + ttp.Addrport = promise.Context.TtpAddrPort + ttp.Hash = promise.Context.TtpHash + } + theoric := pAPI.LaunchSignature{ SignatureUuid: promise.Context.SignatureUUID, DocumentHash: promise.Context.ContractDocumentHash, KeyHash: promise.Context.Signers, Sequence: promise.Context.Sequence, + Ttp: ttp, } ok, _ := auth.VerifyStructure(AuthContainer.CA, theoric, promise.Context.Seal) diff --git a/dfsst/server/server.go b/dfsst/server/server.go index 7fee6056a8e17ca5e68ddca6532161cfe24c0c96..7b354b24845999d3765dd2adf6f54af6392f1afe 100644 --- a/dfsst/server/server.go +++ b/dfsst/server/server.go @@ -8,6 +8,7 @@ import ( cAPI "dfss/dfssc/api" "dfss/dfssc/security" + dAPI "dfss/dfssd/api" tAPI "dfss/dfsst/api" "dfss/dfsst/entities" "dfss/dfsst/resolve" @@ -29,10 +30,12 @@ type ttpServer struct { func (server *ttpServer) Alert(ctx context.Context, in *tAPI.AlertRequest) (*tAPI.TTPResponse, error) { valid, signatureUUID, signers, senderIndex := entities.IsRequestValid(ctx, in.Promises) if !valid { + dAPI.DLog("invalid request from " + net.GetCN(&ctx)) return nil, errors.New(InternalError) } valid = int(in.Index) >= len(in.Promises[0].Context.Sequence) if !valid { + dAPI.DLog("invalid sequence index from " + net.GetCN(&ctx)) return nil, errors.New(InternalError) } // Now we know that the request contains information correctly signed by the platform, @@ -46,6 +49,7 @@ func (server *ttpServer) Alert(ctx context.Context, in *tAPI.AlertRequest) (*tAP // We check if we have already sent an abort token to the sender of the request stop, message, err := server.handleAbortedSender(manager, senderIndex) if stop { + dAPI.DLog("already sent an abort token to " + net.GetCN(&ctx)) return message, err } diff --git a/net/client.go b/net/client.go index ad8316d1fc4ccc1d8cb090f380dc2edc67550aa9..e3a0b6e716b60b66bf0e09ad9bd8e1deccbaa381 100644 --- a/net/client.go +++ b/net/client.go @@ -17,7 +17,7 @@ import ( ) // DefaultTimeout should be used when a non-critical timeout is used in the application. -var DefaultTimeout = 30 * time.Second +var DefaultTimeout = 5 * time.Second // Connect to a peer. // diff --git a/net/fixtures/test.pb.go b/net/fixtures/test.pb.go index f036fb5af254bc3310c96e55022dc92b2e47f5a6..2b7ee391b75cc5ad5fd5b197cd21845c7adced1a 100644 --- a/net/fixtures/test.pb.go +++ b/net/fixtures/test.pb.go @@ -170,15 +170,16 @@ var _Test_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 158 bytes of a gzipped FileDescriptorProto + // 164 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x49, 0x49, 0x2b, 0x2e, 0xd6, 0xcf, 0x4b, 0x2d, 0xd1, 0x4f, 0xcb, 0xac, 0x28, 0x29, 0x2d, 0x4a, 0x2d, 0xd6, 0x2f, 0x49, - 0x2d, 0x2e, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0x09, 0x2a, 0x09, 0x72, 0x31, - 0x7b, 0xe4, 0x17, 0x08, 0x71, 0x71, 0x31, 0x65, 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x2a, - 0x89, 0x71, 0xb1, 0x79, 0x16, 0x3b, 0x96, 0x96, 0x64, 0x08, 0xf1, 0x70, 0xb1, 0x24, 0x02, 0x69, - 0xb0, 0x38, 0x87, 0x12, 0x3b, 0x17, 0xab, 0x6b, 0x6e, 0x41, 0x49, 0xa5, 0x51, 0x34, 0x17, 0x4b, - 0x08, 0xd0, 0x2c, 0x21, 0x35, 0x2e, 0x96, 0x80, 0xcc, 0xbc, 0x74, 0x21, 0x5e, 0x3d, 0x98, 0x71, - 0x7a, 0x40, 0xb3, 0xa4, 0x50, 0xb9, 0x4a, 0x0c, 0x42, 0xda, 0x5c, 0x2c, 0x60, 0xe3, 0xf8, 0x11, - 0x12, 0x60, 0x83, 0xa4, 0x04, 0x10, 0x02, 0x10, 0x1b, 0x95, 0x18, 0x92, 0xd8, 0xc0, 0x2e, 0x34, - 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe6, 0x7b, 0x0d, 0xb5, 0xc1, 0x00, 0x00, 0x00, + 0x2d, 0x2e, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0x09, 0x2a, 0x89, 0x72, 0x31, + 0x7b, 0xe4, 0x17, 0x08, 0xf1, 0x71, 0x31, 0x65, 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, + 0x01, 0x59, 0x4a, 0x32, 0x5c, 0x6c, 0x9e, 0xc5, 0x8e, 0xa5, 0x25, 0x19, 0x42, 0x42, 0x5c, 0x2c, + 0x89, 0x40, 0x1a, 0x2c, 0xc7, 0x11, 0x04, 0x66, 0x2b, 0xb1, 0x73, 0xb1, 0xba, 0xe6, 0x16, 0x94, + 0x54, 0x1a, 0x45, 0x73, 0xb1, 0x84, 0x00, 0x4d, 0x15, 0x52, 0xe3, 0x62, 0x09, 0xc8, 0xcc, 0x4b, + 0x17, 0xe2, 0xd5, 0x83, 0x19, 0xac, 0x07, 0x34, 0x55, 0x0a, 0x95, 0xab, 0xc4, 0x20, 0xa4, 0xcd, + 0xc5, 0x02, 0x36, 0x94, 0x1f, 0x21, 0x01, 0x36, 0x48, 0x4a, 0x00, 0x21, 0x00, 0xb1, 0x57, 0x89, + 0x21, 0x89, 0x0d, 0xec, 0x56, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xf2, 0x1b, 0xf6, + 0xcb, 0x00, 0x00, 0x00, } diff --git a/tests/sign_test.go b/tests/sign_test.go index af3bf2e9888c14687d8fd2fcb92a59a76e331803..c0148da67cebb84fcd9634d100d18e6368969846 100644 --- a/tests/sign_test.go +++ b/tests/sign_test.go @@ -14,18 +14,11 @@ import ( "github.com/stretchr/testify/assert" ) -// TestSignContract unroll the whole signature process. -// -// GOOD CASE -// - Start platform +// setupSignature prepares required servers and clients to sign a contract. +// - Start platform, ttp, demonstrator // - Register client1, client2 and client3 // - Create contract `contract.txt` -// - Sign it -// - Check if all proof files are present -// -// TODO BAD CASES - -func TestSignContract(t *testing.T) { +func setupSignature(t *testing.T) (stop func(), clients []*exec.Cmd, contractPath, contractFilePath string) { // Cleanup eraseDatabase() @@ -34,12 +27,10 @@ func TestSignContract(t *testing.T) { assert.Equal(t, nil, err) _, _, _, stop, ca, err := startPlatform(workingDir) assert.Equal(t, nil, err) - defer stop() time.Sleep(2 * time.Second) // Register clients - clients := make([]*exec.Cmd, 3) client1, err := createClient(workingDir, ca, 9091) assert.Equal(t, nil, err) err = registerAndAuth(client1, "client1@example.com", "password", "", true, true) @@ -56,7 +47,7 @@ func TestSignContract(t *testing.T) { // Create contract client1 = newClient(client1) setLastArg(client1, "new", true) - contractFilePath := filepath.Join("testdata", "contract.txt") + contractFilePath = filepath.Join("testdata", "contract.txt") client1.Stdin = strings.NewReader( "password\n" + contractFilePath + "\n" + @@ -71,9 +62,9 @@ func TestSignContract(t *testing.T) { // Get contract file contractEntity := getContract("contract.txt", 0) - contractData, err := contract.GetJSON(contractEntity, nil) + contractData, err := contract.GetJSON(contractEntity) assert.Equal(t, nil, err) - contractPath := filepath.Join(workingDir, "c.dfss") + contractPath = filepath.Join(workingDir, "c.dfss") err = ioutil.WriteFile(contractPath, contractData, os.ModePerm) assert.Equal(t, nil, err) @@ -85,11 +76,21 @@ func TestSignContract(t *testing.T) { _, err = wrongFileClient.Output() assert.NotNil(t, err) - // Sign! + clients = make([]*exec.Cmd, 3) clients[0] = newClient(client1) clients[1] = newClient(client2) clients[2] = newClient(client3) + return +} + +// TestSignContract unroll the whole signature process. +// In this test, everything should work fine without any ttp call. +func TestSignContract(t *testing.T) { + // Setup + stop, clients, contractPath, contractFilePath := setupSignature(t) + defer stop() + // Sign! closeChannel := make(chan []byte, 3) for i := 0; i < 3; i++ { setLastArg(clients[i], "sign", true) @@ -98,8 +99,8 @@ func TestSignContract(t *testing.T) { time.Sleep(time.Duration(i*2) * time.Second) c.Stdin = strings.NewReader(contractFilePath + "\npassword\nyes\n") c.Stderr = os.Stderr - output, err1 := c.Output() - if err1 != nil { + output, err := c.Output() + if err != nil { output = nil } closeChannel <- output @@ -118,6 +119,12 @@ func TestSignContract(t *testing.T) { } } + checkProofFile(t, 3) + time.Sleep(time.Second) +} + +// checkProofFile counts the number of proof file contained in the current directory, and compares it to the nb parameter. +func checkProofFile(t *testing.T, nb int) { // Ensure that all the files are present proofFile := regexp.MustCompile(`client[0-9]+@example.com.*\.proof`) files, _ := ioutil.ReadDir("./") @@ -126,11 +133,42 @@ func TestSignContract(t *testing.T) { for _, file := range files { if proofFile.Match([]byte(file.Name())) { matches++ - err = os.Remove("./" + file.Name()) + err := os.Remove("./" + file.Name()) assert.True(t, err == nil, "Cannot remove .proof matching file") } } - assert.True(t, matches == 3, "Missing proof file ?") + assert.Equal(t, nb, matches, "Invalid number of proof file(s)") +} + +// TestSignContractFailure tests the signature with a faulty client. +// In this test, everything should not work fine, because client1 shutdowns way too early. +func TestSignContractFailure(t *testing.T) { + // Setup + stop, clients, contractPath, contractFilePath := setupSignature(t) + defer stop() + + // Configure client3 to be faulty + setLastArg(clients[2], "--stopbefore", true) + setLastArg(clients[2], "1", false) + setLastArg(clients[2], "sign", false) + + // Sign! + closeChannel := make(chan []byte, 3) + for i := 0; i < 3; i++ { + setLastArg(clients[i], "sign", true) + setLastArg(clients[i], contractPath, false) + go func(c *exec.Cmd, i int) { + c.Stdin = strings.NewReader(contractFilePath + "\npassword\nyes\n") + output, _ := c.Output() + closeChannel <- output + }(clients[i], i) + } + + for i := 0; i < 3; i++ { + // TODO check stderr? + <-closeChannel + } + checkProofFile(t, 0) time.Sleep(time.Second) } diff --git a/tests/starters_test.go b/tests/starters_test.go index f7f8f8ff573f4e26364ee598ce1053916bbbbdf9..67f4e90763a94f9d13681a6eed1e28fcc05c0487 100644 --- a/tests/starters_test.go +++ b/tests/starters_test.go @@ -31,13 +31,14 @@ func startPlatform(tmpDir string) (platform, ttp, demo *exec.Cmd, stop func(), c // Init cmd := exec.Command(path, "--path", dir, "-v", "init") + ttpsPath := filepath.Join(dir, "ttps") err = cmd.Run() if err != nil { return } // Create TTP working directory - cmd = exec.Command(path, "--path", dir, "-v", "--cn", "ttp", "ttp") + cmd = exec.Command(path, "--path", dir, "--ttps", ttpsPath, "--addr", "localhost:9098", "ttp") err = cmd.Run() if err != nil { return @@ -50,13 +51,13 @@ func startPlatform(tmpDir string) (platform, ttp, demo *exec.Cmd, stop func(), c } // Start platform - platform = exec.Command(path, "--db", dbURI, "--path", dir, "-p", testPort, "-v", "start") + platform = exec.Command(path, "--db", dbURI, "--path", dir, "-p", testPort, "--ttps", ttpsPath, "-d", "localhost:9099", "-v", "start") platform.Stdout = os.Stdout platform.Stderr = os.Stderr err = platform.Start() // Start TTP - ttp = exec.Command(ttpPath, "--db", dbURI, "--port", "9098", "start") + ttp = exec.Command(ttpPath, "--db", dbURI, "--port", "9098", "-d", "localhost:9099", "-v", "start") ttp.Dir = filepath.Join(dir, "ttp") ttp.Stdout = os.Stdout ttp.Stderr = os.Stderr