mirror of
https://github.com/cloudflare/redoctober.git
synced 2026-01-05 04:56:07 +00:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
45
core/core.go
45
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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user