Decrypt returns the list of users used for delegation

When decrypting a chunk of data, red october will now report the users
whose keys were used in the decryption.
This commit is contained in:
Kyle Isom
2014-09-10 09:22:04 -07:00
committed by Kyle
parent 886bd0d623
commit 91cd67f267
5 changed files with 69 additions and 20 deletions

View File

@@ -8,10 +8,11 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"github.com/cloudflare/redoctober/cryptor"
"github.com/cloudflare/redoctober/keycache"
"github.com/cloudflare/redoctober/passvault"
"log"
)
// Each of these structures corresponds to the JSON expected on the
@@ -60,6 +61,11 @@ type decrypt struct {
Data []byte
}
type decryptWithDelegates struct {
Data []byte
Delegates []string
}
type modify struct {
Name string
Password string
@@ -283,13 +289,23 @@ func Decrypt(jsonIn []byte) ([]byte, error) {
return jsonStatusError(err)
}
resp, err := cryptor.Decrypt(s.Data)
data, names, err := cryptor.Decrypt(s.Data)
if err != nil {
log.Println("Error decrypting:", err)
return jsonStatusError(err)
}
return jsonResponse(resp)
resp := &decryptWithDelegates{
Data: data,
Delegates: names,
}
out, err := json.Marshal(resp)
if err != nil {
return jsonStatusError(err)
}
return jsonResponse(out)
}
// Modify processes a modify request.

View File

@@ -7,10 +7,11 @@ package core
import (
"bytes"
"encoding/json"
"github.com/cloudflare/redoctober/keycache"
"github.com/cloudflare/redoctober/passvault"
"os"
"testing"
"github.com/cloudflare/redoctober/keycache"
"github.com/cloudflare/redoctober/passvault"
)
func TestCreate(t *testing.T) {
@@ -449,8 +450,21 @@ func TestEncryptDecrypt(t *testing.T) {
if s.Status != "ok" {
t.Fatalf("Error in decrypt, %v", s.Status)
}
if string(s.Response) != "Hello Jello" {
t.Fatalf("Error in decrypt, %v", string(s.Response))
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)
}
}
keycache.FlushCache()
@@ -707,7 +721,13 @@ func TestStatic(t *testing.T) {
t.Fatalf("Error in summary, %v", r.Status)
}
if bytes.Compare(expected, r.Response) != 0 {
var d decryptWithDelegates
err = json.Unmarshal(r.Response, &d)
if err != nil {
t.Fatalf("Error in decrypt, %v", err)
}
if bytes.Compare(expected, d.Data) != 0 {
t.Fatalf("Error in summary, %v, %v", expected, r.Response)
}

View File

@@ -12,12 +12,13 @@ import (
"crypto/sha1"
"encoding/json"
"errors"
"sort"
"strconv"
"github.com/cloudflare/redoctober/keycache"
"github.com/cloudflare/redoctober/padding"
"github.com/cloudflare/redoctober/passvault"
"github.com/cloudflare/redoctober/symcrypt"
"sort"
"strconv"
)
const (
@@ -111,15 +112,16 @@ func encryptKey(nameInner, nameOuter string, clearKey []byte, pubKeys map[string
}
// unwrapKey decrypts first key in keys whose encryption keys are in keycache
func unwrapKey(keys []MultiWrappedKey, pubKeys map[string]SingleWrappedKey) (unwrappedKey []byte, err error) {
func unwrapKey(keys []MultiWrappedKey, pubKeys map[string]SingleWrappedKey) (unwrappedKey []byte, names []string, err error) {
var (
keyFound error
fullMatch bool = false
nameSet = map[string]bool{}
)
for _, mwKey := range keys {
if err != nil {
return nil, err
return nil, nil, err
}
tmpKeyValue := mwKey.Key
@@ -130,6 +132,7 @@ func unwrapKey(keys []MultiWrappedKey, pubKeys map[string]SingleWrappedKey) (unw
if tmpKeyValue, keyFound = keycache.DecryptKey(tmpKeyValue, mwName, pubEncrypted.Key); keyFound != nil {
break
}
nameSet[mwName] = true
}
if keyFound == nil {
fullMatch = true
@@ -141,6 +144,12 @@ func unwrapKey(keys []MultiWrappedKey, pubKeys map[string]SingleWrappedKey) (unw
if !fullMatch {
err = errors.New("Need more delegated keys")
names = nil
}
names = make([]string, 0, len(nameSet))
for name := range nameSet {
names = append(names, name)
}
return
}
@@ -339,14 +348,14 @@ func Encrypt(in []byte, names []string, min int) (resp []byte, err error) {
}
// Decrypt decrypts a file using the keys in the key cache.
func Decrypt(in []byte) (resp []byte, err error) {
func Decrypt(in []byte) (resp []byte, names []string, err error) {
// unwrap encrypted file
var encrypted EncryptedData
if err = json.Unmarshal(in, &encrypted); err != nil {
return
}
if encrypted.Version != DEFAULT_VERSION {
return nil, errors.New("Unknown version")
return nil, nil, errors.New("Unknown version")
}
// make sure file was encrypted with the active vault
@@ -355,7 +364,7 @@ func Decrypt(in []byte) (resp []byte, err error) {
return
}
if encrypted.VaultId != vaultId {
return nil, errors.New("Wrong vault")
return nil, nil, errors.New("Wrong vault")
}
// validate the size of the keys
@@ -379,7 +388,7 @@ func Decrypt(in []byte) (resp []byte, err error) {
// decrypt file key with delegate keys
var unwrappedKey = make([]byte, 16)
if unwrappedKey, err = unwrapKey(encrypted.KeySet, encrypted.KeySetRSA); err != nil {
if unwrappedKey, names, err = unwrapKey(encrypted.KeySet, encrypted.KeySetRSA); err != nil {
return
}
@@ -393,5 +402,6 @@ func Decrypt(in []byte) (resp []byte, err error) {
// decrypt contents of file
aesCBC.CryptBlocks(clearData, encrypted.Data)
return padding.RemovePadding(clearData)
resp, err = padding.RemovePadding(clearData)
return
}

View File

@@ -403,7 +403,8 @@
submit( $form, {
data : data,
success : function(d){
$form.find('.feedback').empty().append( makeAlert({ type: 'success', message: '<p>Successfully decrypted data:</p><pre>'+ window.atob(d.Response)+'</pre>' }) );
d = JSON.parse(window.atob(d.Response));
$form.find('.feedback').empty().append( makeAlert({ type: 'success', message: '<p>Successfully decrypted data:</p><pre>'+ window.atob(d.Data)+'</pre><p>Delegates: '+d.Delegates.sort().join(', ')+'</p>' }) );
}
});
});

View File

@@ -12,7 +12,6 @@ import (
"encoding/pem"
"flag"
"fmt"
"github.com/cloudflare/redoctober/core"
"io"
"io/ioutil"
"log"
@@ -21,6 +20,8 @@ import (
"os"
"runtime"
"time"
"github.com/cloudflare/redoctober/core"
)
// List of URLs to register and their related functions
@@ -633,7 +634,8 @@ var indexHtml = []byte(`<!DOCTYPE html>
submit( $form, {
data : data,
success : function(d){
$form.find('.feedback').empty().append( makeAlert({ type: 'success', message: '<p>Successfully decrypted data:</p><pre>'+ window.atob(d.Response)+'</pre>' }) );
d = JSON.parse(window.atob(d.Response));
$form.find('.feedback').empty().append( makeAlert({ type: 'success', message: '<p>Successfully decrypted data:</p><pre>'+ window.atob(d.Data)+'</pre><p>Delegates: '+d.Delegates.sort().join(', ')+'</p>' }) );
}
});
});