This is an automated email from the ASF dual-hosted git repository. smihaylov pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/incubator-milagro-dta.git
commit ef993c8e3f195fdf930dbecd0a37183889c04870 Author: Stanislav Mihaylov <[email protected]> AuthorDate: Tue Sep 24 13:49:12 2019 +0300 CreateIdentity as a new package --- go.sum | 5 +++ libs/documents/crypto.go | 2 +- libs/documents/docs.go | 21 ++++----- libs/documents/docs_test.go | 19 ++++---- pkg/bitcoinplugin/helpers.go | 2 +- pkg/common/common.go | 41 +++++------------- pkg/defaultservice/identity.go | 54 ++--------------------- pkg/identity/identity.go | 98 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 135 insertions(+), 107 deletions(-) diff --git a/go.sum b/go.sum index c31086c..aed6fea 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,7 @@ github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= @@ -85,6 +86,7 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= @@ -537,6 +539,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= @@ -594,6 +597,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= @@ -760,6 +764,7 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/gotestsum v0.3.4/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY= diff --git a/libs/documents/crypto.go b/libs/documents/crypto.go index f504ec0..cfb7b05 100644 --- a/libs/documents/crypto.go +++ b/libs/documents/crypto.go @@ -56,7 +56,7 @@ func decapsulateWithRecipient(recipient Recipient, sikeSK []byte) ([]byte, error return recreatedAesKey, nil } -func encapsulateKeyForRecipient(recipientsIDDocs map[string]IDDoc, secret []byte) (recipientList []*Recipient, err error) { +func encapsulateKeyForRecipient(recipientsIDDocs map[string]*IDDoc, secret []byte) (recipientList []*Recipient, err error) { for id, idDocument := range recipientsIDDocs { r := &Recipient{} iv, err := cryptowallet.RandomBytes(16) diff --git a/libs/documents/docs.go b/libs/documents/docs.go index ae36c11..1b190a6 100644 --- a/libs/documents/docs.go +++ b/libs/documents/docs.go @@ -46,11 +46,11 @@ type OrderDoc struct { } //NewIDDoc generate a new empty IDDoc -func NewIDDoc() IDDoc { - ret := IDDoc{} - ret.Header = &Header{} - ret.IDDocument = &IDDocument{} - return ret +func NewIDDoc() *IDDoc { + return &IDDoc{ + &Header{}, + &IDDocument{}, + } } //NewOrderDoc generate a new order @@ -62,17 +62,14 @@ func NewOrderDoc() OrderDoc { } //EncodeIDDocument encode an IDDoc into a raw bytes stream for the wire -func EncodeIDDocument(idDocument IDDoc, blsSK []byte) ([]byte, error) { - header := idDocument.Header - plaintext := idDocument.IDDocument - rawDoc, err := Encode("", plaintext, nil, header, blsSK, nil) +func EncodeIDDocument(idDocument *IDDoc, blsSK []byte) ([]byte, error) { + rawDoc, err := Encode("", idDocument.IDDocument, nil, idDocument.Header, blsSK, nil) return rawDoc, err } //EncodeOrderDocument encode an OrderDoc into a raw bytes stream for the wire -func EncodeOrderDocument(nodeID string, orderDoc OrderDoc, blsSK []byte, previousCID string, recipients map[string]IDDoc) ([]byte, error) { +func EncodeOrderDocument(nodeID string, orderDoc OrderDoc, blsSK []byte, recipients map[string]*IDDoc) ([]byte, error) { header := orderDoc.Header - header.PreviousCID = previousCID // rawDoc, err := Encode(orderDoc.OrderDocument, nil, header, blsSK, nil) rawDoc, err := Encode(nodeID, nil, orderDoc.OrderDocument, header, blsSK, recipients) return rawDoc, err @@ -169,7 +166,7 @@ func Decode(rawDoc []byte, tag string, sikeSK []byte, recipientID string, plainT //Encode - convert the header, secret and plaintext into a message for the wire //The Header can be pre-populated with any nece -func Encode(nodeID string, plainText proto.Message, secretText proto.Message, header *Header, blsSK []byte, recipients map[string]IDDoc) (rawDoc []byte, err error) { +func Encode(nodeID string, plainText proto.Message, secretText proto.Message, header *Header, blsSK []byte, recipients map[string]*IDDoc) (rawDoc []byte, err error) { plainTextDocType, err := detectDocType(plainText) if err != nil { return nil, errors.New("Plaintext Document - Unknown Type") diff --git a/libs/documents/docs_test.go b/libs/documents/docs_test.go index 40509e1..513fc7b 100644 --- a/libs/documents/docs_test.go +++ b/libs/documents/docs_test.go @@ -40,13 +40,13 @@ func Test_EnvelopeEncryption(t *testing.T) { order, _ := BuildTestOrderDoc() order.IPFSID = "NEW IPFS ID" - recipients := map[string]IDDoc{ + recipients := map[string]*IDDoc{ id1: s1, } testText := "SEARCH_FOR_THIS123" testTextBytes := []byte(testText) order.Reference = testText - raw, _ := EncodeOrderDocument(id1, order, blsSK, "", recipients) + raw, _ := EncodeOrderDocument(id1, order, blsSK, recipients) contains := bytes.Contains(raw, testTextBytes) assert.False(t, contains, "Testtext should not be found inside the Envelope - its inside the ciphertext") @@ -64,10 +64,10 @@ func Test_EncodeDecodeOrderDoc(t *testing.T) { s1, id1, _, sikeSK, blsPK, blsSK := BuildTestIDDoc() order, _ := BuildTestOrderDoc() order.IPFSID = "NEW IPFS ID" - recipients := map[string]IDDoc{ + recipients := map[string]*IDDoc{ id1: s1, } - raw, _ := EncodeOrderDocument(id1, order, blsSK, "PREVIOUSCID", recipients) + raw, _ := EncodeOrderDocument(id1, order, blsSK, recipients) reconstitutedOrder := OrderDoc{} _ = DecodeOrderDocument(raw, "NEW IPFS ID", &reconstitutedOrder, sikeSK, id1, blsPK) order.Header.Recipients[0].CipherText = reconstitutedOrder.Header.Recipients[0].CipherText @@ -87,7 +87,7 @@ func Test_EncodeDecodeID(t *testing.T) { iddoc, tag, _, _, _, blsSK := BuildTestIDDoc() raw, _ := EncodeIDDocument(iddoc, blsSK) reconstitutedIDDoc := NewIDDoc() - _ = DecodeIDDocument(raw, tag, &reconstitutedIDDoc) + _ = DecodeIDDocument(raw, tag, reconstitutedIDDoc) differences := deep.Equal(reconstitutedIDDoc, iddoc) var failed = false for _, diff := range differences { @@ -112,7 +112,7 @@ func Test_AESPadding(t *testing.T) { func Test_EncodeDecode(t *testing.T) { //These are some DocID for local user s1, id1, _, sikeSK1, _, _ := BuildTestIDDoc() - recipients := map[string]IDDoc{ + recipients := map[string]*IDDoc{ id1: s1, } seed, _ := cryptowallet.RandomBytes(16) @@ -121,8 +121,6 @@ func Test_EncodeDecode(t *testing.T) { secretBody := &SimpleString{Content: "B"} plainText := &SimpleString{Content: "A"} header := &Header{} - previousIDCode := "previous_id_code" - header.PreviousCID = previousIDCode rawDoc, err := Encode(id1, plainText, secretBody, header, blsSK, recipients) assert.Nil(t, err, "Failed to Encode") @@ -142,7 +140,6 @@ func Test_EncodeDecode(t *testing.T) { assert.Equal(t, plainText.Content, reconPlainText.Content, "Verify fails") assert.Equal(t, secretBody.Content, reconSecretBody.Content, "Verify fails") assert.NotNil(t, reconHeader.DateTime, "Header not populated") - assert.Equal(t, header.PreviousCID, previousIDCode, "Verify fails") assert.Equal(t, reconHeader.IPFSID, tag, "tag not loaded into header") } @@ -181,7 +178,7 @@ func BuildTestOrderDoc() (OrderDoc, error) { return order, nil } -func BuildTestIDDoc() (IDDoc, string, []byte, []byte, []byte, []byte) { +func BuildTestIDDoc() (*IDDoc, string, []byte, []byte, []byte, []byte) { //make some test ID docs seed, _ := cryptowallet.RandomBytes(16) @@ -206,7 +203,7 @@ func BuildTestIDDoc() (IDDoc, string, []byte, []byte, []byte, []byte) { iddoc := &IDDoc{} rawDocI, _ := proto.Marshal(&signedEnvelope) _ = DecodeIDDocument(rawDocI, ipfsID, iddoc) - return *iddoc, ipfsID, sikePK, sikeSK, blsPK, blsSK + return iddoc, ipfsID, sikePK, sikeSK, blsPK, blsSK } //createIDForSignedEnvelope - create a hash for the document to be used as an ID diff --git a/pkg/bitcoinplugin/helpers.go b/pkg/bitcoinplugin/helpers.go index eb65167..3a7880c 100644 --- a/pkg/bitcoinplugin/helpers.go +++ b/pkg/bitcoinplugin/helpers.go @@ -99,7 +99,7 @@ func adhocEncryptedEnvelopeEncode(s *Service, nodeID string, beneficiaryIDDocume } secretBody := &documents.SimpleString{Content: privateKeyPart1of2} header := &documents.Header{} - recipients := map[string]documents.IDDoc{ + recipients := map[string]*documents.IDDoc{ beneficiaryIDDocumentCID: beneficiaryIDDocument, } docEnv, err := documents.Encode(nodeID, nil, secretBody, header, blsSK, recipients) diff --git a/pkg/common/common.go b/pkg/common/common.go index b8b6b0c..6fefee7 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -22,9 +22,7 @@ package common import ( "encoding/hex" - "fmt" "io" - "sync" "time" "github.com/apache/incubator-milagro-dta/libs/cryptowallet" @@ -35,8 +33,6 @@ import ( "github.com/pkg/errors" ) -var previousIDMutex = &sync.Mutex{} - //IdentitySecrets - keys required for decryption and signing type IdentitySecrets struct { Name string `json:"Name"` @@ -74,14 +70,14 @@ func RetrieveOrderFromIPFS(ipfs ipfs.Connector, ipfsID string, sikeSK []byte, re } // RetrieveIDDocFromIPFS finds and parses the IDDocument -func RetrieveIDDocFromIPFS(ipfs ipfs.Connector, ipfsID string) (documents.IDDoc, error) { +func RetrieveIDDocFromIPFS(ipfs ipfs.Connector, ipfsID string) (*documents.IDDoc, error) { iddoc := &documents.IDDoc{} rawDocI, err := ipfs.Get(ipfsID) if err != nil { - return documents.IDDoc{}, err + return nil, err } err = documents.DecodeIDDocument(rawDocI, ipfsID, iddoc) - return *iddoc, err + return iddoc, err } // MakeRandomSeedAndStore genefates and stores a random seed @@ -112,7 +108,7 @@ func RetrieveSeed(store *datastore.Store, reference string) (seedHex string, err } // CreateAndStoreOrderPart2 - -func CreateAndStoreOrderPart2(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, orderPart1CID, commitmentPublicKey, nodeID string, recipients map[string]documents.IDDoc) (orderPart2CID string, err error) { +func CreateAndStoreOrderPart2(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, orderPart1CID, commitmentPublicKey, nodeID string, recipients map[string]*documents.IDDoc) (orderPart2CID string, err error) { Part2 := documents.OrderPart2{ CommitmentPublicKey: commitmentPublicKey, PreviousOrderCID: orderPart1CID, @@ -128,7 +124,7 @@ func CreateAndStoreOrderPart2(ipfs ipfs.Connector, store *datastore.Store, order } // CreateAndStorePart3 adds part 3 "redemption request" to the order doc -func CreateAndStorePart3(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, orderPart2CID, nodeID string, beneficiaryEncryptedData []byte, recipients map[string]documents.IDDoc) (orderPart3CID string, err error) { +func CreateAndStorePart3(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, orderPart2CID, nodeID string, beneficiaryEncryptedData []byte, recipients map[string]*documents.IDDoc) (orderPart3CID string, err error) { //Add part 3 "redemption request" to the order doc redemptionRequest := documents.OrderPart3{ //TODO @@ -147,7 +143,7 @@ func CreateAndStorePart3(ipfs ipfs.Connector, store *datastore.Store, order *doc } // CreateAndStoreOrderPart4 - -func CreateAndStoreOrderPart4(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, commitmentPrivateKey, orderPart3CID, nodeID string, recipients map[string]documents.IDDoc) (orderPart4CID string, err error) { +func CreateAndStoreOrderPart4(ipfs ipfs.Connector, store *datastore.Store, order *documents.OrderDoc, commitmentPrivateKey, orderPart3CID, nodeID string, recipients map[string]*documents.IDDoc) (orderPart4CID string, err error) { Part4 := documents.OrderPart4{ Secret: commitmentPrivateKey, PreviousOrderCID: orderPart3CID, @@ -163,7 +159,7 @@ func CreateAndStoreOrderPart4(ipfs ipfs.Connector, store *datastore.Store, order } // WriteOrderToIPFS writes the order document to IPFS network -func WriteOrderToIPFS(nodeID string, ipfs ipfs.Connector, store *datastore.Store, id string, order *documents.OrderDoc, recipients map[string]documents.IDDoc) (ipfsAddress string, err error) { // Get the secret keys +func WriteOrderToIPFS(nodeID string, ipfs ipfs.Connector, store *datastore.Store, id string, order *documents.OrderDoc, recipients map[string]*documents.IDDoc) (ipfsAddress string, err error) { // Get the secret keys secrets := &IdentitySecrets{} if err := store.Get("id-doc", nodeID, secrets); err != nil { return "", errors.New("load secrets from store") @@ -173,18 +169,7 @@ func WriteOrderToIPFS(nodeID string, ipfs ipfs.Connector, store *datastore.Store return "", errors.Wrap(err, "Decode identity secrets") } - ////Mutex Lock - only one thread at once can write to IPFS as we need to keep track of the previous ID and put it into the next doc to create a chain - previousIDMutex.Lock() - previousIDKey := fmt.Sprintf("previous-id-%s", nodeID) - var previousID string - if err := store.Get("id-doc", previousIDKey, &previousID); err != nil { - previousID = "genesis" - if err := store.Set("id-doc", previousIDKey, previousID, nil); err != nil { - return "", err - } - } - - rawDoc, err := documents.EncodeOrderDocument(nodeID, *order, blsSecretKey, previousID, recipients) + rawDoc, err := documents.EncodeOrderDocument(nodeID, *order, blsSecretKey, recipients) if err != nil { return "", errors.Wrap(err, "Failed to encode IDDocument") } @@ -192,13 +177,7 @@ func WriteOrderToIPFS(nodeID string, ipfs ipfs.Connector, store *datastore.Store if err != nil { return "", errors.Wrap(err, "Failed to Save Raw Document into IPFS") } - if err := store.Set("id-doc", previousIDKey, ipfsAddress, nil); err != nil { - return "", err - } - previousIDMutex.Unlock() - //Write order to store - //orderRef := fmt.Sprintf("order-ref-%s", order.Reference) if err := store.Set("order", order.Reference, ipfsAddress, map[string]string{"time": time.Now().UTC().Format(time.RFC3339)}); err != nil { return "", errors.New("Save Order to store") } @@ -241,7 +220,7 @@ func RetrieveIdentitySecrets(store *datastore.Store, nodeID string) (name string } // BuildRecipientList builds a list of recipients who are able to decrypt the encrypted envelope -func BuildRecipientList(ipfs ipfs.Connector, localNodeDocCID, remoteNodeDocCID string) (map[string]documents.IDDoc, error) { +func BuildRecipientList(ipfs ipfs.Connector, localNodeDocCID, remoteNodeDocCID string) (map[string]*documents.IDDoc, error) { remoteNodeDoc, err := RetrieveIDDocFromIPFS(ipfs, remoteNodeDocCID) if err != nil { return nil, err @@ -252,7 +231,7 @@ func BuildRecipientList(ipfs ipfs.Connector, localNodeDocCID, remoteNodeDocCID s return nil, err } - recipients := map[string]documents.IDDoc{ + recipients := map[string]*documents.IDDoc{ remoteNodeDocCID: remoteNodeDoc, localNodeDocCID: localNodeDoc, } diff --git a/pkg/defaultservice/identity.go b/pkg/defaultservice/identity.go index d58aee8..ae256e5 100644 --- a/pkg/defaultservice/identity.go +++ b/pkg/defaultservice/identity.go @@ -19,67 +19,19 @@ package defaultservice import ( "encoding/hex" - "time" - "github.com/apache/incubator-milagro-dta/libs/crypto" - "github.com/apache/incubator-milagro-dta/libs/cryptowallet" "github.com/apache/incubator-milagro-dta/libs/documents" "github.com/apache/incubator-milagro-dta/pkg/api" "github.com/apache/incubator-milagro-dta/pkg/common" + "github.com/apache/incubator-milagro-dta/pkg/identity" "github.com/pkg/errors" ) // CreateIdentity creates a new identity func (s *Service) CreateIdentity(req *api.CreateIdentityRequest) (*api.CreateIdentityResponse, error) { - name := req.Name - - //generate crypto random seed - seed, err := cryptowallet.RandomBytes(48) - if err != nil { - return nil, errors.Wrap(err, "Failed to Generate random seed") - } - - //Generate SIKE keys - rc1, sikePublicKey, sikeSecretKey := crypto.SIKEKeys(seed) - if rc1 != 0 { - return nil, errors.New("Failed to generate SIKE keys") - } - - //Generate BLS keys - rc1, blsPublicKey, blsSecretKey := crypto.BLSKeys(seed, nil) - if rc1 != 0 { - return nil, errors.New("Failed to generate BLS keys") - } - - ecPubKey, err := common.InitECKeys(seed) + idDocumentCID, err := identity.CreateIdentity(req.Name, s.Ipfs, s.Store) if err != nil { - return nil, errors.Wrap(err, "Failed to Generate EC Pub Key from random seed") - } - //build ID Doc - idDocument := documents.NewIDDoc() - idDocument.AuthenticationReference = name - idDocument.BeneficiaryECPublicKey = ecPubKey - idDocument.SikePublicKey = sikePublicKey - idDocument.BLSPublicKey = blsPublicKey - idDocument.Timestamp = time.Now().Unix() - //Encode the IDDoc to envelope byte stream - rawDoc, err := documents.EncodeIDDocument(idDocument, blsSecretKey) - if err != nil { - return nil, errors.Wrap(err, "Failed to encode IDDocument") - } - idDocumentCID, err := s.Ipfs.Add(rawDoc) - if err != nil { - return nil, errors.Wrap(err, "Failed to Save Raw Document into IPFS") - } - secrets := common.IdentitySecrets{ - Name: name, - Seed: hex.EncodeToString(seed), - BLSSecretKey: hex.EncodeToString(blsSecretKey), - SikeSecretKey: hex.EncodeToString(sikeSecretKey), - } - - if err := s.Store.Set("id-doc", idDocumentCID, secrets, map[string]string{"time": time.Now().UTC().Format(time.RFC3339)}); err != nil { - return nil, errors.Wrap(err, "Failed to Save ID Document - Write to Store") + return nil, err } return &api.CreateIdentityResponse{ diff --git a/pkg/identity/identity.go b/pkg/identity/identity.go new file mode 100644 index 0000000..edbba97 --- /dev/null +++ b/pkg/identity/identity.go @@ -0,0 +1,98 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/* +Package identity - manage Identity document and keys +*/ +package identity + +import ( + "encoding/hex" + "time" + + "github.com/apache/incubator-milagro-dta/libs/crypto" + "github.com/apache/incubator-milagro-dta/libs/cryptowallet" + "github.com/apache/incubator-milagro-dta/libs/datastore" + "github.com/apache/incubator-milagro-dta/libs/documents" + "github.com/apache/incubator-milagro-dta/libs/ipfs" + "github.com/apache/incubator-milagro-dta/pkg/common" + "github.com/pkg/errors" +) + +// CreateIdentity creates a new identity +// returns Identity secrets and Identity document +func CreateIdentity(name string, ipfsConn ipfs.Connector, store *datastore.Store) (idDocumentCID string, err error) { + //generate crypto random seed + seed, err := cryptowallet.RandomBytes(48) + if err != nil { + err = errors.Wrap(err, "Failed to generate random seed") + return + } + + //Generate SIKE keys + rc1, sikePublicKey, sikeSecretKey := crypto.SIKEKeys(seed) + if rc1 != 0 { + err = errors.New("Failed to generate SIKE keys") + return + } + + //Generate BLS keys + rc1, blsPublicKey, blsSecretKey := crypto.BLSKeys(seed, nil) + if rc1 != 0 { + err = errors.New("Failed to generate BLS keys") + return + } + + ecPubKey, err := common.InitECKeys(seed) + if err != nil { + err = errors.Wrap(err, "Failed to generate EC Public Key") + return + } + + //build ID Doc + idDocument := documents.NewIDDoc() + idDocument.AuthenticationReference = name + idDocument.BeneficiaryECPublicKey = ecPubKey + idDocument.SikePublicKey = sikePublicKey + idDocument.BLSPublicKey = blsPublicKey + idDocument.Timestamp = time.Now().Unix() + + rawIDDoc, err := documents.EncodeIDDocument(idDocument, blsSecretKey) + if err != nil { + err = errors.Wrap(err, "Failed to encode IDDocument") + return + } + + idDocumentCID, err = ipfsConn.Add(rawIDDoc) + + secrets := common.IdentitySecrets{ + Name: name, + Seed: hex.EncodeToString(seed), + BLSSecretKey: hex.EncodeToString(blsSecretKey), + SikeSecretKey: hex.EncodeToString(sikeSecretKey), + } + + if store != nil { + err = store.Set("id-doc", idDocumentCID, secrets, map[string]string{"time": time.Now().UTC().Format(time.RFC3339)}) + if err != nil { + err = errors.Wrap(err, "Failed to store ID Document") + return + } + } + + return idDocumentCID, nil +}
