lib/uplink-gomobile: extend encryption key capabilities

Change-Id: Id10b14cc34ff983ec451440fe4b0305651115022
This commit is contained in:
Michal Niewrzal 2020-04-03 17:13:27 +02:00 committed by Kaloyan Raev
parent a4c554f2ed
commit d23e03f8a2
3 changed files with 44 additions and 4 deletions

View File

@ -4,6 +4,7 @@
package mobile package mobile
import ( import (
"storj.io/common/encryption"
"storj.io/common/paths" "storj.io/common/paths"
"storj.io/common/storj" "storj.io/common/storj"
libuplink "storj.io/storj/lib/uplink" libuplink "storj.io/storj/lib/uplink"
@ -27,12 +28,12 @@ func NewEncryptionAccessWithRoot(bucket, unencryptedPath, encryptedPath string,
if err != nil { if err != nil {
return nil, safeError(err) return nil, safeError(err)
} }
encAccess := libuplink.NewEncryptionAccess() encAccess := NewEncryptionAccess()
err = encAccess.Store().Add(bucket, paths.NewUnencrypted(unencryptedPath), paths.NewEncrypted(encryptedPath), *key) err = encAccess.lib.Store().Add(bucket, paths.NewUnencrypted(unencryptedPath), paths.NewEncrypted(encryptedPath), *key)
if err != nil { if err != nil {
return nil, safeError(err) return nil, safeError(err)
} }
return &EncryptionAccess{lib: encAccess}, nil return &EncryptionAccess{lib: encAccess.lib}, nil
} }
// SetDefaultKey sets the default key to use when no matching keys are found // SetDefaultKey sets the default key to use when no matching keys are found
@ -94,6 +95,23 @@ func (e *EncryptionAccess) Import(other *EncryptionAccess) error {
return e.lib.Import(other.lib) return e.lib.Import(other.lib)
} }
// OverrideEncryptionKey overrides the root encryption key for the prefix with encryptionKey.
func (e *EncryptionAccess) OverrideEncryptionKey(bucket, prefix string, encryptionKey []byte) error {
store := e.lib.Store()
unencPath := paths.NewUnencrypted(prefix)
encPath, err := encryption.EncryptPathWithStoreCipher(bucket, unencPath, store)
if err != nil {
return err
}
key, err := storj.NewKey(encryptionKey)
if err != nil {
return err
}
return store.Add(bucket, unencPath, encPath, *key)
}
// EncryptionRestriction represents a scenario where some set of objects // EncryptionRestriction represents a scenario where some set of objects
// may need to be encrypted/decrypted // may need to be encrypted/decrypted
type EncryptionRestriction struct { type EncryptionRestriction struct {
@ -126,3 +144,12 @@ func NewEncryptionRestrictions() *EncryptionRestrictions {
func (e *EncryptionRestrictions) Add(restriction *EncryptionRestriction) { func (e *EncryptionRestrictions) Add(restriction *EncryptionRestriction) {
e.restrictions = append(e.restrictions, *restriction.lib) e.restrictions = append(e.restrictions, *restriction.lib)
} }
// DeriveEncryptionKey derives a salted root key for password using the salt.
func DeriveEncryptionKey(password, salt []byte) ([]byte, error) {
key, err := encryption.DeriveRootKey(password, salt, "", 1)
if err != nil {
return nil, err
}
return key[:], nil
}

View File

@ -444,6 +444,10 @@ public class LibuplinkInstrumentedTest {
assertNotNull(scope.encryptionAccess()); assertNotNull(scope.encryptionAccess());
assertEquals(scopeString, scope.serialize()); assertEquals(scopeString, scope.serialize());
byte[] key = Mobile.deriveEncryptionKey("mypass".getBytes(), "salt".getBytes());
scope.encryptionAccess().overrideEncryptionKey("bucket", "userid", key);
} }

View File

@ -4,6 +4,8 @@
package uplink package uplink
import ( import (
"strings"
"github.com/btcsuite/btcutil/base58" "github.com/btcsuite/btcutil/base58"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/zeebo/errs" "github.com/zeebo/errs"
@ -90,9 +92,16 @@ func (s *EncryptionAccess) Restrict(apiKey APIKey, restrictions ...EncryptionRes
access := NewEncryptionAccess() access := NewEncryptionAccess()
access.SetDefaultPathCipher(s.store.GetDefaultPathCipher()) access.SetDefaultPathCipher(s.store.GetDefaultPathCipher())
if len(restrictions) == 0 {
access.Store().SetDefaultKey(s.store.GetDefaultKey())
}
for _, res := range restrictions { for _, res := range restrictions {
unencPath := paths.NewUnencrypted(res.PathPrefix) // If the share prefix ends in a `/` we need to remove this final slash.
// Otherwise, if we the shared prefix is `/bob/`, the encrypted shared
// prefix results in `enc("")/enc("bob")/enc("")`. This is an incorrect
// encrypted prefix, what we really want is `enc("")/enc("bob")`.
unencPath := paths.NewUnencrypted(strings.TrimSuffix(res.PathPrefix, "/"))
encPath, err := encryption.EncryptPathWithStoreCipher(res.Bucket, unencPath, s.store) encPath, err := encryption.EncryptPathWithStoreCipher(res.Bucket, unencPath, s.store)
if err != nil { if err != nil {