From b1ac8b4cc0198a5b7c117c70e11d3857ee57e12f Mon Sep 17 00:00:00 2001 From: Zi Lin Date: Tue, 11 Aug 2015 16:31:30 -0700 Subject: [PATCH] Add new operation: re-encrypt 're-encrypt' allows us to re-encrypt an RO encryption to a different set of owners and labels. Currently two delegations are sufficient to carry out this operation. --- client/client.go | 15 ++++ cmd/ro/main.go | 39 ++++++++-- core/core.go | 45 ++++++++++++ core/core_test.go | 180 ++++++++++++++++++++++++++++++++++++++++++++++ redoctober.go | 21 +++--- 5 files changed, 285 insertions(+), 15 deletions(-) diff --git a/client/client.go b/client/client.go index 2b843bc..dae88bd 100644 --- a/client/client.go +++ b/client/client.go @@ -189,6 +189,21 @@ func (c *RemoteServer) Encrypt(req core.EncryptRequest) (*core.ResponseData, err return unmarshalResponseData(respBytes) } +// ReEncrypt issues an re-encrypt request to the remote server +func (c *RemoteServer) ReEncrypt(req core.ReEncryptRequest) (*core.ResponseData, error) { + reqBytes, err := json.Marshal(req) + if err != nil { + return nil, err + } + + respBytes, err := c.doAction("re-encrypt", reqBytes) + if err != nil { + return nil, err + } + + return unmarshalResponseData(respBytes) +} + // Decrypt issues an decrypt request to the remote server func (c *RemoteServer) Decrypt(req core.DecryptRequest) (*core.ResponseData, error) { reqBytes, err := json.Marshal(req) diff --git a/cmd/ro/main.go b/cmd/ro/main.go index b3a91d3..a40439d 100644 --- a/cmd/ro/main.go +++ b/cmd/ro/main.go @@ -31,11 +31,12 @@ type command struct { var roServer *client.RemoteServer var commandSet = map[string]command{ - "create": command{Run: runCreate, Desc: "create a user account"}, - "summary": command{Run: runSummary, Desc: "list the user and delegation summary"}, - "delegate": command{Run: runDelegate, Desc: "do decryption delegation"}, - "encrypt": command{Run: runEncrypt, Desc: "encrypt a file"}, - "decrypt": command{Run: runDecrypt, Desc: "decrypt a file"}, + "create": command{Run: runCreate, Desc: "create a user account"}, + "summary": command{Run: runSummary, Desc: "list the user and delegation summary"}, + "delegate": command{Run: runDelegate, Desc: "do decryption delegation"}, + "encrypt": command{Run: runEncrypt, Desc: "encrypt a file"}, + "decrypt": command{Run: runDecrypt, Desc: "decrypt a file"}, + "re-encrypt": command{Run: runReEncrypt, Desc: "re-encrypt a file"}, } func registerFlags() { @@ -137,6 +138,34 @@ func runEncrypt() { ioutil.WriteFile(outPath, outBytes, 0644) } +func runReEncrypt() { + inBytes, err := ioutil.ReadFile(inPath) + processError(err) + + // base64 decode the input + encBytes, err := base64.StdEncoding.DecodeString(string(inBytes)) + if err != nil { + log.Println("fail to base64 decode the data, proceed with raw data") + encBytes = inBytes + } + + req := core.ReEncryptRequest{ + Name: user, + Password: pswd, + Owners: processCSL(owners), + LeftOwners: processCSL(lefters), + RightOwners: processCSL(righters), + Labels: processCSL(labels), + Data: encBytes, + } + + resp, err := roServer.ReEncrypt(req) + processError(err) + fmt.Println("Response Status:", resp.Status) + outBytes := []byte(base64.StdEncoding.EncodeToString(resp.Response)) + ioutil.WriteFile(outPath, outBytes, 0644) +} + func runDecrypt() { inBytes, err := ioutil.ReadFile(inPath) processError(err) diff --git a/core/core.go b/core/core.go index 2a5ab3c..a645c22 100644 --- a/core/core.go +++ b/core/core.go @@ -71,6 +71,8 @@ type EncryptRequest struct { Labels []string } +type ReEncryptRequest EncryptRequest + type DecryptRequest struct { Name string Password string @@ -402,6 +404,49 @@ func Encrypt(jsonIn []byte) ([]byte, error) { return jsonResponse(resp) } +// ReEncrypt processes an Re-encrypt request. +func ReEncrypt(jsonIn []byte) ([]byte, error) { + var s ReEncryptRequest + var err error + + defer func() { + if err != nil { + log.Printf("core.re-encrypt failed: user=%s size=%d %v", s.Name, len(s.Data), err) + } else { + log.Printf("core.re-encrypt success: user=%s size=%d", s.Name, len(s.Data)) + } + }() + + err = json.Unmarshal(jsonIn, &s) + if err != nil { + return jsonStatusError(err) + } + + if err = validateUser(s.Name, s.Password, false); err != nil { + return jsonStatusError(err) + } + + data, _, secure, err := crypt.Decrypt(s.Data, s.Name) + if err != nil { + return jsonStatusError(err) + } + if !secure { + return jsonStatusError(errors.New("decryption's secure bit is false")) + } + + access := cryptor.AccessStructure{ + Names: s.Owners, + LeftNames: s.LeftOwners, + RightNames: s.RightOwners, + } + + resp, err := crypt.Encrypt(data, s.Labels, access) + if err != nil { + return jsonStatusError(err) + } + return jsonResponse(resp) +} + // Decrypt processes a decrypt request. func Decrypt(jsonIn []byte) ([]byte, error) { var s DecryptRequest diff --git a/core/core_test.go b/core/core_test.go index e665d18..0215a31 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -507,6 +507,186 @@ func TestEncryptDecrypt(t *testing.T) { } } +func TestReEncrypt(t *testing.T) { + delegateJson := []byte(`{"Name":"Alice","Password":"Hello","Time":"0s","Uses":0}`) + delegateJson2 := []byte(`{"Name":"Bob","Password":"Hello","Time":"0s","Uses":0}`) + delegateJson3 := []byte(`{"Name":"Carol","Password":"Hello","Time":"0s","Uses":0}`) + delegateJson4 := []byte(`{"Name":"Bob","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["blue"]}`) + delegateJson5 := []byte(`{"Name":"Carol","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["blue"]}`) + delegateJson6 := []byte(`{"Name":"Bob","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["red"]}`) + delegateJson7 := []byte(`{"Name":"Carol","Password":"Hello","Time":"10s","Uses":2,"Users":["Alice"],"Labels":["red"]}`) + encryptJson := []byte(`{"Name":"Carol","Password":"Hello","Minumum":2,"Owners":["Alice","Bob","Carol"],"Data":"SGVsbG8gSmVsbG8=","Labels":["blue"]}`) + + Init("memory") + + // check for summary of initialized vault with new member + var s ResponseData + respJson, err := Create(delegateJson) + if err != nil { + t.Fatalf("Error in creating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in creating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in creating account, %v", s.Status) + } + + respJson, err = Delegate(delegateJson2) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + respJson, err = Delegate(delegateJson3) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + // delegate two valid decryptors for label blue + respJson, err = Delegate(delegateJson4) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + respJson, err = Delegate(delegateJson5) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + // Encrypt + respJson, err = Encrypt(encryptJson) + if err != nil { + t.Fatalf("Error in encrypt, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in encrypt, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in encrypt, %v", s.Status) + } + + // Prepare ReEncryptRequest + reEncryptJson, err := json.Marshal( + ReEncryptRequest{ + Name: "Alice", + Password: "Hello", + Data: s.Response, + Owners: []string{"Alice", "Bob", "Carol"}, + Labels: []string{"red"}, + }) + if err != nil { + t.Fatalf("Error in re-encrypt, %v", err) + } + + // Re-Encrypt + respJson, err = ReEncrypt(reEncryptJson) + if err != nil { + t.Fatalf("Error in re-encrypt, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in re-encrypt, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in re-encrypt, %v", s.Status) + } + + // Prepare DecryptRequest + decryptJson, err := json.Marshal( + DecryptRequest{ + Name: "Alice", + Password: "Hello", + Data: s.Response, + }) + if err != nil { + t.Fatalf("Error in dencrypt, %v", err) + } + + // delegate two valid decryptors for label red + respJson, err = Delegate(delegateJson6) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + respJson, err = Delegate(delegateJson7) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in delegating account, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in delegating account, %v", s.Status) + } + + // Decrypt + respJson, err = Decrypt(decryptJson) + if err != nil { + t.Fatalf("Error in decrypt, %v", err) + } + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in decrypt, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in decrypt, %v", s.Status) + } + + var d DecryptWithDelegates + err = json.Unmarshal(s.Response, &d) + if err != nil { + t.Fatalf("Error in decrypt, %v", err) + } + + if string(d.Data) != "Hello Jello" { + t.Fatalf("Error in decrypt, %v", string(d.Data)) + } + + if d.Delegates[0] != "Bob" && d.Delegates[1] != "Carol" { + if d.Delegates[1] != "Bob" && d.Delegates[0] != "Carol" { + t.Fatalf("Error in decrypt, %v", d.Delegates) + } + } +} + func TestOwners(t *testing.T) { delegateJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Time\":\"0s\",\"Uses\":0}") delegateJson2 := []byte("{\"Name\":\"Bob\",\"Password\":\"Hello\",\"Time\":\"0s\",\"Uses\":0}") diff --git a/redoctober.go b/redoctober.go index d2b9d3a..e70eb5b 100644 --- a/redoctober.go +++ b/redoctober.go @@ -27,16 +27,17 @@ import ( // List of URLs to register and their related functions var functions = map[string]func([]byte) ([]byte, error){ - "/create": core.Create, - "/summary": core.Summary, - "/purge": core.Purge, - "/delegate": core.Delegate, - "/password": core.Password, - "/encrypt": core.Encrypt, - "/decrypt": core.Decrypt, - "/owners": core.Owners, - "/modify": core.Modify, - "/export": core.Export, + "/create": core.Create, + "/summary": core.Summary, + "/purge": core.Purge, + "/delegate": core.Delegate, + "/password": core.Password, + "/encrypt": core.Encrypt, + "/re-encrypt": core.ReEncrypt, + "/decrypt": core.Decrypt, + "/owners": core.Owners, + "/modify": core.Modify, + "/export": core.Export, } type userRequest struct {