mirror of
https://github.com/cloudflare/redoctober.git
synced 2026-01-08 07:11:48 +00:00
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:
22
core/core.go
22
core/core.go
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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>' }) );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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>' }) );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user