diff --git a/go.mod b/go.mod index 64e7faf19cfe40e9cca7ed94b7fcb81d4c9170b4..20f6d4531cc9844803e8bd01dc87bbd6892b85b9 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/jwalterweatherman v1.1.0 github.com/stretchr/testify v1.8.2 - gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84 + gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5 gitlab.com/elixxir/crypto v0.0.7-0.20230531164732-6951a4e33a55 gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2 diff --git a/go.sum b/go.sum index 979c9e7e0a90d280a5d703d5c0a55fa3b865f4f0..a8792a64aa88a2f90f4b2f9f14ca86f8566659e5 100644 --- a/go.sum +++ b/go.sum @@ -407,8 +407,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8 h1:uAFCyBkXprQoPkcDDfxXtaMyL5x+xSGrAWzR907xROQ= gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8/go.mod h1:1X8gRIAPDisS3W6Vtr/ymiUmZMJUIwDV1o5DEOo/pzw= -gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84 h1:dwJ65HKgc7yAjoW8tpuzwaEDZIeG3eKuUWdAT+1TTmA= -gitlab.com/elixxir/client/v4 v4.6.4-0.20230531170755-2174efc87f84/go.mod h1:c1QPbv7Qr7r7Es5h0NoziawiIgVS24VYhbY7WQm1w8Q= +gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5 h1:+l53p9Dy735OIJPI/v9XloWJk5Ql+/DqzHQrtvVTjxA= +gitlab.com/elixxir/client/v4 v4.6.4-0.20230606172346-f59d48cefbc5/go.mod h1:c1QPbv7Qr7r7Es5h0NoziawiIgVS24VYhbY7WQm1w8Q= gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938 h1:f27+QUFiGWrprKm+fstOg3ABkYLpWcZi3+8Lf5eDnqY= gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938/go.mod h1:z+qW0D9VpY5QKTd7wRlb5SK4kBNqLYsa4DXBcUXue9Q= gitlab.com/elixxir/crypto v0.0.7-0.20230531164732-6951a4e33a55 h1:J0h3APo7OcIWPnmtIJCyeMOkE9wT6vI8Bw+oZq53S8E= diff --git a/main.go b/main.go index 60aa541cc9e704bb78c06e8657291796f781bdc7..0699d66476a9cbea03bfe5ea3f452619720b9162 100644 --- a/main.go +++ b/main.go @@ -152,7 +152,7 @@ func setGlobals() { js.Global().Set("NewDMClientWithIndexedDbUnsafe", js.FuncOf(wasm.NewDMClientWithIndexedDbUnsafe)) js.Global().Set("NewDMsDatabaseCipher", - js.FuncOf(wasm.NewDMsDatabaseCipher)) + js.FuncOf(wasm.NewDatabaseCipher)) // wasm/cmix.go js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix)) diff --git a/wasm/channels.go b/wasm/channels.go index b1e27a2129abb4f4c7cf01931396ac0e6bfa280d..843b3a55af5f6d38efb7109fcc2b2ae85dd92ea7 100644 --- a/wasm/channels.go +++ b/wasm/channels.go @@ -386,7 +386,7 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any { cUI := newChannelUI(args[5]) cipherID := args[6].Int() - cipher, err := bindings.GetDbCipherTrackerFromID(cipherID) + cipher, err := dbCipherTrackerSingleton.get(cipherID) if err != nil { exception.ThrowTrace(err) } @@ -444,10 +444,10 @@ func NewChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any { func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string, privateIdentity, extensionBuilderIDsJSON []byte, notificationsID int, channelsCbs bindings.ChannelUICallbacks, - cipher *bindings.DbCipher) any { + cipher *DbCipher) any { model := channelsDb.NewWASMEventModelBuilder( - wasmJsPath, cipher, channelsCbs) + wasmJsPath, cipher.api, channelsCbs) promiseFn := func(resolve, reject func(args ...any) js.Value) { cm, err := bindings.NewChannelsManagerGoEventModel(cmixID, @@ -504,7 +504,7 @@ func LoadChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any { channelsCbs := newChannelUI(args[5]) cipherID := args[6].Int() - cipher, err := bindings.GetDbCipherTrackerFromID(cipherID) + cipher, err := dbCipherTrackerSingleton.get(cipherID) if err != nil { exception.ThrowTrace(err) } @@ -557,10 +557,10 @@ func LoadChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any { func loadChannelsManagerWithIndexedDb(cmixID int, wasmJsPath, storageTag string, extensionBuilderIDsJSON []byte, notificationsID int, channelsCbs bindings.ChannelUICallbacks, - cipher *bindings.DbCipher) any { + cipher *DbCipher) any { model := channelsDb.NewWASMEventModelBuilder( - wasmJsPath, cipher, channelsCbs) + wasmJsPath, cipher.api, channelsCbs) promiseFn := func(resolve, reject func(args ...any) js.Value) { cm, err := bindings.LoadChannelsManagerGoEventModel( @@ -2315,145 +2315,6 @@ type MessageAndError struct { Error string } -//////////////////////////////////////////////////////////////////////////////// -// Channel Cipher // -//////////////////////////////////////////////////////////////////////////////// - -// DbCipher wraps the [bindings.DbCipher] object so its methods -// can be wrapped to be Javascript compatible. -type DbCipher struct { - api *bindings.DbCipher -} - -// newDbCipherJS creates a new Javascript compatible object -// (map[string]any) that matches the [DbCipher] structure. -func newDbCipherJS(api *bindings.DbCipher) map[string]any { - c := DbCipher{api} - DbCipherMap := map[string]any{ - "GetID": js.FuncOf(c.GetID), - "Encrypt": js.FuncOf(c.Encrypt), - "Decrypt": js.FuncOf(c.Decrypt), - "MarshalJSON": js.FuncOf(c.MarshalJSON), - "UnmarshalJSON": js.FuncOf(c.UnmarshalJSON), - } - - return DbCipherMap -} - -// NewDatabaseCipher constructs a [DbCipher] object. -// -// Parameters: -// - args[0] - The tracked [Cmix] object ID (int). -// - args[1] - The password for storage. This should be the same password -// passed into [NewCmix] (Uint8Array). -// - args[2] - The maximum size of a payload to be encrypted. A payload passed -// into [DbCipher.Encrypt] that is larger than this value will result -// in an error (int). -// -// Returns: -// - JavaScript representation of the [DbCipher] object. -// - Throws an error if creating the cipher fails. -func NewDatabaseCipher(_ js.Value, args []js.Value) any { - cmixId := args[0].Int() - password := utils.CopyBytesToGo(args[1]) - plaintTextBlockSize := args[2].Int() - - cipher, err := bindings.NewDatabaseCipher( - cmixId, password, plaintTextBlockSize) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return newDbCipherJS(cipher) -} - -// GetID returns the ID for this [bindings.DbCipher] in the -// DbCipherTracker. -// -// Returns: -// - Tracker ID (int). -func (c *DbCipher) GetID(js.Value, []js.Value) any { - return c.api.GetID() -} - -// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is -// done on the plaintext so all encrypted data looks uniform at rest. -// -// Parameters: -// - args[0] - The data to be encrypted (Uint8Array). This must be smaller -// than the block size passed into [NewDatabaseCipher]. If it is -// larger, this will return an error. -// -// Returns: -// - The ciphertext of the plaintext passed in (Uint8Array). -// - Throws an error if it fails to encrypt the plaintext. -func (c *DbCipher) Encrypt(_ js.Value, args []js.Value) any { - ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(ciphertext) -} - -// Decrypt will decrypt the passed in encrypted value. The plaintext will be -// returned by this function. Any padding will be discarded within this -// function. -// -// Parameters: -// - args[0] - the encrypted data returned by [DbCipher.Encrypt] -// (Uint8Array). -// -// Returns: -// - The plaintext of the ciphertext passed in (Uint8Array). -// - Throws an error if it fails to encrypt the plaintext. -func (c *DbCipher) Decrypt(_ js.Value, args []js.Value) any { - plaintext, err := c.api.Decrypt(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(plaintext) -} - -// MarshalJSON marshals the cipher into valid JSON. -// -// Returns: -// - JSON of the cipher (Uint8Array). -// - Throws an error if marshalling fails. -func (c *DbCipher) MarshalJSON(js.Value, []js.Value) any { - data, err := c.api.MarshalJSON() - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(data) -} - -// UnmarshalJSON unmarshalls JSON into the cipher. -// -// Note that this function does not transfer the internal RNG. Use -// [channel.NewCipherFromJSON] to properly reconstruct a cipher from JSON. -// -// Parameters: -// - args[0] - JSON data to unmarshal (Uint8Array). -// -// Returns: -// - JSON of the cipher (Uint8Array). -// - Throws an error if marshalling fails. -func (c *DbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any { - err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - return nil -} - // newChannelUI maps the methods on the Javascript object to the // channelUI callbacks implementation struct. func newChannelUI(cbImpl js.Value) *channelUI { diff --git a/wasm/channels_test.go b/wasm/channels_test.go index f56f33fb6fc11d8bd93ae98fb3638a8dfd64e267..1aa9b7fa7ca1872f28908f884b038bdd14eca601 100644 --- a/wasm/channels_test.go +++ b/wasm/channels_test.go @@ -65,7 +65,7 @@ func Test_ChannelsManagerMethods(t *testing.T) { func Test_newChannelDbCipherJS(t *testing.T) { cipherType := reflect.TypeOf(&DbCipher{}) - cipher := newDbCipherJS(&bindings.DbCipher{}) + cipher := newDbCipherJS(&DbCipher{}) if len(cipher) != cipherType.NumMethod() { t.Errorf("ChannelDbCipher JS object does not have all methods."+ "\nexpected: %d\nreceived: %d", cipherType.NumMethod(), len(cipher)) @@ -84,7 +84,7 @@ func Test_newChannelDbCipherJS(t *testing.T) { // [bindings.ChannelDbCipher] has. func Test_ChannelDbCipherMethods(t *testing.T) { cipherType := reflect.TypeOf(&DbCipher{}) - binCipherType := reflect.TypeOf(&bindings.DbCipher{}) + binCipherType := reflect.TypeOf(&DbCipher{}) if binCipherType.NumMethod() != cipherType.NumMethod() { t.Errorf("WASM ChannelDbCipher object does not have all methods from "+ diff --git a/wasm/cipher.go b/wasm/cipher.go new file mode 100644 index 0000000000000000000000000000000000000000..ab5223984e874261a1b274667fb1205edd15e773 --- /dev/null +++ b/wasm/cipher.go @@ -0,0 +1,232 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package wasm + +import ( + "github.com/pkg/errors" + "gitlab.com/elixxir/client/v4/bindings" + "gitlab.com/elixxir/client/v4/storage/utility" + "gitlab.com/elixxir/crypto/indexedDb" + "gitlab.com/elixxir/wasm-utils/exception" + "gitlab.com/elixxir/wasm-utils/utils" + "sync" + "syscall/js" +) + +// dbCipherTrackerSingleton is used to track DbCipher objects +// so that they can be referenced by ID back over the bindings. +var dbCipherTrackerSingleton = &DbCipherTracker{ + tracked: make(map[int]*DbCipher), + count: 0, +} + +// DbCipherTracker is a singleton used to keep track of extant +// DbCipher objects, preventing race conditions created by passing it +// over the bindings. +type DbCipherTracker struct { + tracked map[int]*DbCipher + count int + mux sync.RWMutex +} + +// create creates a DbCipher from a [indexedDb.Cipher], assigns it a unique +// ID, and adds it to the DbCipherTracker. +func (ct *DbCipherTracker) create(c indexedDb.Cipher) *DbCipher { + ct.mux.Lock() + defer ct.mux.Unlock() + + chID := ct.count + ct.count++ + + ct.tracked[chID] = &DbCipher{ + api: c, + id: chID, + } + + return ct.tracked[chID] +} + +// get an DbCipher from the DbCipherTracker given its ID. +func (ct *DbCipherTracker) get(id int) (*DbCipher, error) { + ct.mux.RLock() + defer ct.mux.RUnlock() + + c, exist := ct.tracked[id] + if !exist { + return nil, errors.Errorf( + "Cannot get DbCipher for ID %d, does not exist", id) + } + + return c, nil +} + +// delete removes a DMDbCipher from the DMDbCipherTracker. +func (ct *DbCipherTracker) delete(id int) { + ct.mux.Lock() + defer ct.mux.Unlock() + + delete(ct.tracked, id) +} + +// DbCipher wraps the [indexedDb.Cipher] object so its methods +// can be wrapped to be Javascript compatible. +type DbCipher struct { + api indexedDb.Cipher + salt []byte + id int +} + +// newDbCipherJS creates a new Javascript compatible object +// (map[string]any) that matches the [DbCipher] structure. +func newDbCipherJS(c *DbCipher) map[string]any { + DbCipherMap := map[string]any{ + "GetID": js.FuncOf(c.GetID), + "Encrypt": js.FuncOf(c.Encrypt), + "Decrypt": js.FuncOf(c.Decrypt), + "MarshalJSON": js.FuncOf(c.MarshalJSON), + "UnmarshalJSON": js.FuncOf(c.UnmarshalJSON), + } + + return DbCipherMap +} + +// NewDatabaseCipher constructs a [DbCipher] object. +// +// Parameters: +// - args[0] - The tracked [Cmix] object ID (int). +// - args[1] - The password for storage. This should be the same password +// passed into [NewCmix] (Uint8Array). +// - args[2] - The maximum size of a payload to be encrypted. A payload passed +// into [DbCipher.Encrypt] that is larger than this value will result +// in an error (int). +// +// Returns: +// - JavaScript representation of the [DbCipher] object. +// - Throws an error if creating the cipher fails. +func NewDatabaseCipher(_ js.Value, args []js.Value) any { + cmixId := args[0].Int() + password := utils.CopyBytesToGo(args[1]) + plaintTextBlockSize := args[2].Int() + + // Get user from singleton + user, err := bindings.GetCMixInstance(cmixId) + if err != nil { + exception.ThrowTrace(err) + return nil + } + + // Generate RNG + stream := user.GetRng().GetStream() + + // Load or generate a salt + salt, err := utility.NewOrLoadSalt( + user.GetStorage().GetKV(), stream) + if err != nil { + exception.ThrowTrace(err) + return nil + } + + // Construct a cipher + c, err := indexedDb.NewCipher( + password, salt, plaintTextBlockSize, stream) + if err != nil { + exception.ThrowTrace(err) + return nil + } + + // Add to singleton and return + return newDbCipherJS(dbCipherTrackerSingleton.create(c)) +} + +// GetID returns the ID for this [DbCipher] in the +// DbCipherTracker. +// +// Returns: +// - Tracker ID (int). +func (c *DbCipher) GetID(js.Value, []js.Value) any { + return c.id +} + +// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is +// done on the plaintext so all encrypted data looks uniform at rest. +// +// Parameters: +// - args[0] - The data to be encrypted (Uint8Array). This must be smaller +// than the block size passed into [NewDatabaseCipher]. If it is +// larger, this will return an error. +// +// Returns: +// - The ciphertext of the plaintext passed in (String). +// - Throws an error if it fails to encrypt the plaintext. +func (c *DbCipher) Encrypt(_ js.Value, args []js.Value) any { + ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0])) + if err != nil { + exception.ThrowTrace(err) + return nil + } + + return ciphertext +} + +// Decrypt will decrypt the passed in encrypted value. The plaintext will be +// returned by this function. Any padding will be discarded within this +// function. +// +// Parameters: +// - args[0] - the encrypted data returned by [DbCipher.Encrypt] +// (String). +// +// Returns: +// - The plaintext of the ciphertext passed in (Uint8Array). +// - Throws an error if it fails to encrypt the plaintext. +func (c *DbCipher) Decrypt(_ js.Value, args []js.Value) any { + plaintext, err := c.api.Decrypt(args[0].String()) + if err != nil { + exception.ThrowTrace(err) + return nil + } + + return utils.CopyBytesToJS(plaintext) +} + +// MarshalJSON marshals the cipher into valid JSON. +// +// Returns: +// - JSON of the cipher (Uint8Array). +// - Throws an error if marshalling fails. +func (c *DbCipher) MarshalJSON(js.Value, []js.Value) any { + data, err := c.api.MarshalJSON() + if err != nil { + exception.ThrowTrace(err) + return nil + } + + return utils.CopyBytesToJS(data) +} + +// UnmarshalJSON unmarshalls JSON into the cipher. +// +// Note that this function does not transfer the internal RNG. Use +// [indexedDb.NewCipherFromJSON] to properly reconstruct a cipher from JSON. +// +// Parameters: +// - args[0] - JSON data to unmarshal (Uint8Array). +// +// Returns: +// - JSON of the cipher (Uint8Array). +// - Throws an error if marshalling fails. +func (c *DbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any { + err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0])) + if err != nil { + exception.ThrowTrace(err) + return nil + } + return nil +} diff --git a/wasm/dm.go b/wasm/dm.go index e834502567bc54222fb14cad378b521d335a5647..ce64a45442b2df4029371d754778721c137bb5be 100644 --- a/wasm/dm.go +++ b/wasm/dm.go @@ -142,7 +142,7 @@ func NewDMClientWithIndexedDb(_ js.Value, args []js.Value) any { messageReceivedCB := args[3] cipherID := args[4].Int() - cipher, err := bindings.GetDbCipherTrackerFromID(cipherID) + cipher, err := dbCipherTrackerSingleton.get(cipherID) if err != nil { exception.ThrowTrace(err) } @@ -190,7 +190,7 @@ func NewDMClientWithIndexedDbUnsafe(_ js.Value, args []js.Value) any { } func newDMClientWithIndexedDb(cmixID int, wasmJsPath string, - privateIdentity []byte, cb js.Value, cipher *bindings.DbCipher) any { + privateIdentity []byte, cb js.Value, cipher *DbCipher) any { messageReceivedCB := func(uuid uint64, pubKey ed25519.PublicKey, messageUpdate, conversationUpdate bool) { @@ -206,7 +206,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string, } dmPath := base64.RawStdEncoding.EncodeToString(pi.PubKey[:]) model, err := indexDB.NewWASMEventModel( - dmPath, wasmJsPath, cipher, messageReceivedCB) + dmPath, wasmJsPath, cipher.api, messageReceivedCB) if err != nil { reject(exception.NewTrace(err)) } @@ -671,35 +671,6 @@ func DecodeDMShareURL(_ js.Value, args []js.Value) any { return utils.CopyBytesToJS(report) } -//////////////////////////////////////////////////////////////////////////////// -// Channel Receiving Logic and Callback Registration // -//////////////////////////////////////////////////////////////////////////////// - -// channelMessageReceptionCallback wraps Javascript callbacks to adhere to the -// [bindings.ChannelMessageReceptionCallback] interface. -type dmReceptionCallback struct { - callback func(args ...any) js.Value -} - -// Callback returns the context for a channel message. -// -// Parameters: -// - receivedChannelMessageReport - Returns the JSON of -// [bindings.ReceivedChannelMessageReport] (Uint8Array). -// - err - Returns an error on failure (Error). -// -// Returns: -// - It must return a unique UUID for the message that it can be referenced by -// later (int). -func (cmrCB *dmReceptionCallback) Callback( - receivedChannelMessageReport []byte, err error) int { - uuid := cmrCB.callback( - utils.CopyBytesToJS(receivedChannelMessageReport), - exception.NewTrace(err)) - - return uuid.Int() -} - //////////////////////////////////////////////////////////////////////////////// // Event Model Logic // //////////////////////////////////////////////////////////////////////////////// @@ -990,146 +961,6 @@ func (em *dmReceiver) GetConversations() []byte { return conversationsBytes } -//////////////////////////////////////////////////////////////////////////////// -// DM DB Cipher // -//////////////////////////////////////////////////////////////////////////////// - -// DMDbCipher wraps the [bindings.DMDbCipher] object so its methods -// can be wrapped to be Javascript compatible. -type DMDbCipher struct { - api *bindings.DbCipher -} - -// newDMDbCipherJS creates a new Javascript compatible object -// (map[string]any) that matches the [DMDbCipher] structure. -func newDMDbCipherJS(api *bindings.DbCipher) map[string]any { - c := DMDbCipher{api} - channelDbCipherMap := map[string]any{ - "GetID": js.FuncOf(c.GetID), - "Encrypt": js.FuncOf(c.Encrypt), - "Decrypt": js.FuncOf(c.Decrypt), - "MarshalJSON": js.FuncOf(c.MarshalJSON), - "UnmarshalJSON": js.FuncOf(c.UnmarshalJSON), - } - - return channelDbCipherMap -} - -// NewDMsDatabaseCipher constructs a [DMDbCipher] object. -// -// Parameters: -// - args[0] - The tracked [Cmix] object ID (int). -// - args[1] - The password for storage. This should be the same password -// passed into [NewCmix] (Uint8Array). -// - args[2] - The maximum size of a payload to be encrypted. A payload passed -// into [DMDbCipher.Encrypt] that is larger than this value will result -// in an error (int). -// -// Returns: -// - JavaScript representation of the [DMDbCipher] object. -// - Throws an error if creating the cipher fails. -func NewDMsDatabaseCipher(_ js.Value, args []js.Value) any { - cmixId := args[0].Int() - password := utils.CopyBytesToGo(args[1]) - plaintTextBlockSize := args[2].Int() - - cipher, err := bindings.NewDatabaseCipher( - cmixId, password, plaintTextBlockSize) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return newDMDbCipherJS(cipher) -} - -// GetID returns the ID for this [bindings.DMDbCipher] in the -// channelDbCipherTracker. -// -// Returns: -// - Tracker ID (int). -func (c *DMDbCipher) GetID(js.Value, []js.Value) any { - return c.api.GetID() -} - -// Encrypt will encrypt the raw data. It will return a ciphertext. Padding is -// done on the plaintext so all encrypted data looks uniform at rest. -// -// Parameters: -// - args[0] - The data to be encrypted (Uint8Array). This must be smaller -// than the block size passed into [NewDMsDatabaseCipher]. If it is -// larger, this will return an error. -// -// Returns: -// - The ciphertext of the plaintext passed in (Uint8Array). -// - Throws an error if it fails to encrypt the plaintext. -func (c *DMDbCipher) Encrypt(_ js.Value, args []js.Value) any { - ciphertext, err := c.api.Encrypt(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(ciphertext) -} - -// Decrypt will decrypt the passed in encrypted value. The plaintext will be -// returned by this function. Any padding will be discarded within this -// function. -// -// Parameters: -// - args[0] - the encrypted data returned by [DMDbCipher.Encrypt] -// (Uint8Array). -// -// Returns: -// - The plaintext of the ciphertext passed in (Uint8Array). -// - Throws an error if it fails to encrypt the plaintext. -func (c *DMDbCipher) Decrypt(_ js.Value, args []js.Value) any { - plaintext, err := c.api.Decrypt(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(plaintext) -} - -// MarshalJSON marshals the cipher into valid JSON. -// -// Returns: -// - JSON of the cipher (Uint8Array). -// - Throws an error if marshalling fails. -func (c *DMDbCipher) MarshalJSON(js.Value, []js.Value) any { - data, err := c.api.MarshalJSON() - if err != nil { - exception.ThrowTrace(err) - return nil - } - - return utils.CopyBytesToJS(data) -} - -// UnmarshalJSON unmarshalls JSON into the cipher. This function adheres to the -// json.Unmarshaler interface. -// -// Note that this function does not transfer the internal RNG. Use -// [channel.NewCipherFromJSON] to properly reconstruct a cipher from JSON. -// -// Parameters: -// - args[0] - JSON data to unmarshal (Uint8Array). -// -// Returns: -// - JSON of the cipher (Uint8Array). -// - Throws an error if marshalling fails. -func (c *DMDbCipher) UnmarshalJSON(_ js.Value, args []js.Value) any { - err := c.api.UnmarshalJSON(utils.CopyBytesToGo(args[0])) - if err != nil { - exception.ThrowTrace(err) - return nil - } - return nil -} - // truncate truncates the string to length n. If the string is trimmed, then // ellipses (...) are appended. func truncate(s string, n int) string { diff --git a/wasm/dm_test.go b/wasm/dm_test.go index ff5fbb1ca0947a868c2b76ee53de69011269a372..b6c5aff7c2a37b81a51391581ee1257c8b23ecf9 100644 --- a/wasm/dm_test.go +++ b/wasm/dm_test.go @@ -66,9 +66,9 @@ func Test_DMClientMethods(t *testing.T) { // Tests that the map representing DMDbCipher returned by newDMDbCipherJS // contains all of the methods on DMDbCipher. func Test_newDMDbCipherJS(t *testing.T) { - cipherType := reflect.TypeOf(&DMDbCipher{}) + cipherType := reflect.TypeOf(&DbCipher{}) - cipher := newDMDbCipherJS(&bindings.DbCipher{}) + cipher := newDbCipherJS(&DbCipher{}) if len(cipher) != cipherType.NumMethod() { t.Errorf("DMDbCipher JS object does not have all methods."+ "\nexpected: %d\nreceived: %d", cipherType.NumMethod(), len(cipher)) @@ -85,8 +85,8 @@ func Test_newDMDbCipherJS(t *testing.T) { // Tests that DMDbCipher has all the methods that [bindings.DMDbCipher] has. func Test_DMDbCipherMethods(t *testing.T) { - cipherType := reflect.TypeOf(&DMDbCipher{}) - binCipherType := reflect.TypeOf(&bindings.DbCipher{}) + cipherType := reflect.TypeOf(&DbCipher{}) + binCipherType := reflect.TypeOf(&DbCipher{}) if binCipherType.NumMethod() != cipherType.NumMethod() { t.Errorf("WASM DMDbCipher object does not have all methods from "+