Return to idiomatic style & Backwards compatible left&right owners

This commit is contained in:
Brendan Mc
2015-05-04 02:37:42 -07:00
parent 7e08548caf
commit 935b929dd5
3 changed files with 127 additions and 67 deletions

View File

@@ -57,9 +57,11 @@ type EncryptRequest struct {
Name string
Password string
Minimum int
Owners []string
Data []byte
Owners []string
LeftOwners []string
RightOwners []string
Data []byte
Labels []string
}
@@ -277,8 +279,9 @@ func Encrypt(jsonIn []byte) ([]byte, error) {
return jsonStatusError(err)
}
// Encrypt file with list of owners
if resp, err := crypt.Encrypt(s.Data, s.Labels, s.Owners, s.Minimum); err != nil {
// Encrypt file
access := cryptor.AccessStructure{s.Owners, s.LeftOwners, s.RightOwners}
if resp, err := crypt.Encrypt(s.Data, s.Labels, access); err != nil {
log.Println("Error encrypting:", err)
return jsonStatusError(err)
} else {

View File

@@ -34,6 +34,18 @@ func New(records *passvault.Records, cache *keycache.Cache) Cryptor {
return Cryptor{records, cache}
}
// AccessStructure represents different possible access structures for
// encrypted data. If len(Names) > 0, then at least 2 of the users in the list
// must be delegated to decrypt. If len(LeftNames) > 0 & len(RightNames) > 0,
// then at least one from each list must be delegated (if the same user is in
// both, then he can decrypt it alone).
type AccessStructure struct {
Names []string
LeftNames []string
RightNames []string
}
// MultiWrappedKey is a structure containing a 16-byte key encrypted
// once for each of the keys corresponding to the names of the users
// in Name in order.
@@ -179,61 +191,117 @@ func (encrypted *EncryptedData) unlock(key []byte) (err error) {
// wrapKey encrypts the clear key such that a minimum number of delegated keys
// are required to decrypt. NOTE: Currently the max value for min is 2.
func (encrypted *EncryptedData) wrapKey(records *passvault.Records, clearKey []byte, names []string, min int) (err error) {
// Generate a random AES key for each user and RSA/ECIES encrypt it
encrypted.KeySetRSA = make(map[string]SingleWrappedKey, len(names))
for _, name := range names {
func (encrypted *EncryptedData) wrapKey(records *passvault.Records, clearKey []byte, access AccessStructure) (err error) {
generateRandomKey := func(name string) (singleWrappedKey SingleWrappedKey, err error) {
rec, ok := records.GetRecord(name)
if !ok {
err = errors.New("Missing user on disk")
return
}
var singleWrappedKey SingleWrappedKey
if singleWrappedKey.aesKey, err = symcrypt.MakeRandom(16); err != nil {
return err
return
}
if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil {
return err
return
}
encrypted.KeySetRSA[name] = singleWrappedKey
return
}
// encrypt file key with every combination of two keys
encrypted.KeySet = make([]MultiWrappedKey, 0)
encryptKey := func(outer, inner string, clearKey []byte) (keyBytes []byte, err error) {
var outerCrypt, innerCrypt cipher.Block
keyBytes = make([]byte, 16)
for i := 0; i < len(names); i++ {
for j := i + 1; j < len(names); j++ {
var outerCrypt, innerCrypt cipher.Block
keyBytes := make([]byte, 16)
outerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[names[i]].aesKey)
if err != nil {
return
}
innerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[names[j]].aesKey)
if err != nil {
return
}
innerCrypt.Encrypt(keyBytes, clearKey)
outerCrypt.Encrypt(keyBytes, keyBytes)
out := MultiWrappedKey{
Name: []string{names[i], names[j]},
Key: keyBytes,
}
encrypted.KeySet = append(encrypted.KeySet, out)
outerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[outer].aesKey)
if err != nil {
return
}
innerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[inner].aesKey)
if err != nil {
return
}
innerCrypt.Encrypt(keyBytes, clearKey)
outerCrypt.Encrypt(keyBytes, keyBytes)
return
}
return nil
if len(access.Names) > 0 {
// Generate a random AES key for each user and RSA/ECIES encrypt it
encrypted.KeySetRSA = make(map[string]SingleWrappedKey)
for _, name := range access.Names {
encrypted.KeySetRSA[name], err = generateRandomKey(name)
if err != nil {
return err
}
}
// encrypt file key with every combination of two keys
encrypted.KeySet = make([]MultiWrappedKey, 0)
for i := 0; i < len(access.Names); i++ {
for j := i + 1; j < len(access.Names); j++ {
keyBytes, err := encryptKey(access.Names[i], access.Names[j], clearKey)
if err != nil {
return err
}
out := MultiWrappedKey{
Name: []string{access.Names[i], access.Names[j]},
Key: keyBytes,
}
encrypted.KeySet = append(encrypted.KeySet, out)
}
}
return nil
} else if len(access.LeftNames) > 0 && len(access.RightNames) > 0 {
// Generate a random AES key for each user and RSA/ECIES encrypt it
encrypted.KeySetRSA = make(map[string]SingleWrappedKey)
for _, name := range access.LeftNames {
encrypted.KeySetRSA[name], err = generateRandomKey(name)
if err != nil {
return err
}
}
for _, name := range access.RightNames {
encrypted.KeySetRSA[name], err = generateRandomKey(name)
if err != nil {
return err
}
}
// encrypt file key with every combination of one left key and one right key
encrypted.KeySet = make([]MultiWrappedKey, 0)
for _, leftName := range access.LeftNames {
for _, rightName := range access.RightNames {
keyBytes, err := encryptKey(leftName, rightName, clearKey)
if err != nil {
return err
}
out := MultiWrappedKey{
Name: []string{leftName, rightName},
Key: keyBytes,
}
encrypted.KeySet = append(encrypted.KeySet, out)
}
}
return nil
} else {
return errors.New("Invalid access structure.")
}
}
// unwrapKey decrypts first key in keys whose encryption keys are in keycache
@@ -287,11 +355,7 @@ func (encrypted *EncryptedData) unwrapKey(cache *keycache.Cache, user string) (u
// Encrypt encrypts data with the keys associated with names. This
// requires a minimum of min keys to decrypt. NOTE: as currently
// implemented, the maximum value for min is 2.
func (c *Cryptor) Encrypt(in []byte, labels, names []string, min int) (resp []byte, err error) {
if min > 2 {
return nil, errors.New("Minimum restricted to 2")
}
func (c *Cryptor) Encrypt(in []byte, labels []string, access AccessStructure) (resp []byte, err error) {
var encrypted EncryptedData
encrypted.Version = DEFAULT_VERSION
if encrypted.VaultId, err = c.records.GetVaultId(); err != nil {
@@ -309,7 +373,7 @@ func (c *Cryptor) Encrypt(in []byte, labels, names []string, min int) (resp []by
return
}
err = encrypted.wrapKey(c.records, clearKey, names, min)
err = encrypted.wrapKey(c.records, clearKey, access)
if err != nil {
return
}
@@ -361,7 +425,6 @@ func (c *Cryptor) Decrypt(in []byte, user string) (resp []byte, names []string,
return
}
// make sure file was encrypted with the active vault
vaultId, err := c.records.GetVaultId()
if err != nil {

View File

@@ -343,13 +343,13 @@ func InitFrom(path string) (records Records, err error) {
func (records *Records) WriteRecordsToDisk() error {
if records.localPath == "memory" {
return nil
} else {
jsonDiskRecord, err := json.Marshal(records)
if err != nil {
return err
}
return ioutil.WriteFile(records.localPath, jsonDiskRecord, 0644)
}
jsonDiskRecord, err := json.Marshal(records)
if err != nil {
return err
}
return ioutil.WriteFile(records.localPath, jsonDiskRecord, 0644)
}
// AddNewRecord adds a new record for a given username and password.
@@ -429,9 +429,8 @@ func (records *Records) DeleteRecord(name string) error {
if _, ok := records.GetRecord(name); ok {
delete(records.Passwords, name)
return records.WriteRecordsToDisk()
} else {
return errors.New("Record missing")
}
return errors.New("Record missing")
}
// RevokeRecord removes admin status from a record.
@@ -440,9 +439,8 @@ func (records *Records) RevokeRecord(name string) error {
rec.Admin = false
records.SetRecord(rec, name)
return records.WriteRecordsToDisk()
} else {
return errors.New("Record missing")
}
return errors.New("Record missing")
}
// MakeAdmin adds admin status to a given record.
@@ -451,9 +449,8 @@ func (records *Records) MakeAdmin(name string) error {
rec.Admin = true
records.SetRecord(rec, name)
return records.WriteRecordsToDisk()
} else {
return errors.New("Record missing")
}
return errors.New("Record missing")
}
// SetRecord puts a record into the global status.
@@ -516,18 +513,16 @@ func (pr *PasswordRecord) EncryptKey(in []byte) (out []byte, err error) {
func (pr *PasswordRecord) GetKeyRSAPub() (out *rsa.PublicKey, err error) {
if pr.Type != RSARecord {
return out, errors.New("Invalid function for record type")
} else {
return &pr.RSAKey.RSAPublic, err
}
return &pr.RSAKey.RSAPublic, err
}
// GetKeyECCPub returns the ECDSA public key out of the record.
func (pr *PasswordRecord) GetKeyECCPub() (out *ecdsa.PublicKey, err error) {
if pr.Type != ECCRecord {
return out, errors.New("Invalid function for record type")
} else {
return pr.ECKey.ECPublic.toECDSA(), err
}
return pr.ECKey.ECPublic.toECDSA(), err
}
// GetKeyECC returns the ECDSA private key of the record given the correct password.
@@ -623,7 +618,6 @@ func (pr *PasswordRecord) ValidatePassword(password string) error {
if bytes.Compare(h, pr.HashedPassword) != 0 {
return errors.New("Wrong Password")
} else {
return nil
}
return nil
}