Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hoodie-plugin-store-crypto

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hoodie-plugin-store-crypto - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0

lib/helpers/change-password-and-update-docs.js

1

lib/bind-functions.js

@@ -55,2 +55,3 @@ 'use strict'

api.changePassword = require('./change-password').bind(null, store, state)
api.resetPassword = require('./reset-password').bind(null, store, state)
api.isEncrypted = require('./is-encrypted')

@@ -57,0 +58,0 @@

103

lib/change-password.js

@@ -7,9 +7,13 @@ 'use strict'

var createKey = require('./create-key')
var createPasswordCheck = require('./utils/create-password-check')
var isEncryptedObject = require('./utils/is-encrypted-object')
var decryptOne = require('./helpers/decrypt-one')
var encryptMany = require('./helpers/encrypt-many')
var changePasswordAndUpdateDocs = require('./helpers/change-password-and-update-docs')
module.exports = changePassword
/**
* Changes the encryption and updates old docs.
* @param {object} store Instance of the Hoodie-Client-Store.
* @param {object} state Internal state of hoodie-plugin-crypto-store.
* @param {string} oldPassword Old password.
* @param {string} newPassword New password.
*/
function changePassword (store, state, oldPassword, newPassword) {

@@ -42,93 +46,4 @@ if (newPassword == null || typeof newPassword !== 'string' || newPassword.length === 0) {

.then(function (oldKey) {
// create new key and salt
return createKey(newPassword, null)
.then(function (res) {
// set new state
state.key = res.key
state.salt = res.salt
return {
oldKey: oldKey,
newKey: res.key,
newSalt: res.salt
}
})
return changePasswordAndUpdateDocs(store, state, oldKey, newPassword)
})
.then(function (data) {
var notDecrypted = [] // will store the ids of docs that couldn't be decrypted/updated
// update old encrypted docs
return store.db.allDocs({ include_docs: true })
.then(function (rows) {
var docs = rows.rows // update all encrypted docs! _design/* too!
.map(function (row) {
return row.doc
})
return docs
})
.catch(function (err) { // TODO: remove if Store-client with db as getter is published
if (err.message === 'database is destroyed') {
return store.findAll()
}
throw err
})
.then(function (docs) {
var decrypted = docs
.filter(isEncryptedObject)
.map(function (doc) {
return decryptOne(data.oldKey, doc)
.catch(function (error) {
if (error.message === 'Unsupported state or unable to authenticate data') {
return doc._id
}
throw error
})
})
return Promise.all(decrypted)
})
.then(function (decrypted) {
return decrypted.reduce(function (all, doc) {
if (typeof doc === 'string') {
all.notDecrypted.push(doc)
} else {
all.decrypted.push(doc)
}
return all
}, {
decrypted: [],
notDecrypted: []
})
})
.then(function (result) {
notDecrypted = result.notDecrypted
return encryptMany(data.newKey, null, result.decrypted)
})
.then(function (toUpdate) {
return createPasswordCheck(data.newKey)
.then(function (check) {
toUpdate.push({
_id: 'hoodiePluginCryptoStore/salt',
salt: data.newSalt,
check: check
})
return store.update(toUpdate)
})
})
.then(function (updated) {
return {
salt: data.newSalt,
notUpdated: notDecrypted
}
})
})
}

@@ -18,3 +18,3 @@ 'use strict'

_id: '',
_rev: '',
_rev: null,
hoodie: null,

@@ -21,0 +21,0 @@ tag: '',

@@ -8,2 +8,3 @@ 'use strict'

var createPasswordCheck = require('./utils/create-password-check')
var createResetKeys = require('./helpers/create-reset-keys')

@@ -72,3 +73,3 @@ module.exports = setup

.then(function (result) {
return createPasswordCheck(result.key)
var saltDoc = createPasswordCheck(result.key)

@@ -83,5 +84,12 @@ .then(function (check) {

})
var resetKeys = createResetKeys(store, result.key)
return Promise.all([saltDoc, resetKeys])
})
.then(function (obj) {
.then(function (objs) {
var obj = objs[0]
var resetKeys = objs[1]
// if there was an deleted salt doc: undelete it

@@ -92,5 +100,9 @@ if (obj._deleted) {

.then(function () {}) // no result
.then(function () {
return resetKeys
})
}
return resetKeys
})
}
{
"name": "hoodie-plugin-store-crypto",
"version": "2.1.0",
"version": "2.2.0",
"description": "End-to-end crypto plugin for the Hoodie client store.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -25,10 +25,10 @@ # hoodie-plugin-store-crypto

hoodie.store.add({foo: 'bar'})
.then(function (obj) {console.log(obj)})
.then(function (obj) { console.log(obj) })
hoodie.cryptoStore.setup('secret')
.then(async () => {
const salt = await hoodie.cryptoStore.unlock('secret')
await hoodie.cryptoStore.unlock('secret')
const obj = await hoodie.cryptoStore.add({foo: 'bar'}) // adds the object encrypted
console.log(obj) // returns it unencrypted!
const obj = await hoodie.cryptoStore.add({ foo: 'bar' }) // add the object encrypted
console.log(obj) // returns it unencrypted!
})

@@ -116,3 +116,3 @@ ```

There are 4 use-cases you must put in place:
There are 5 use-cases you must put in place:

@@ -123,2 +123,3 @@ - [Sign up / setup / start of using encryption](#setup)

- [changing the password for encryption](#changing-the-password)
- [reset the password](#reset-the-password)

@@ -144,4 +145,6 @@ #### Setup

await hoodie.cryptoStore.setup(cryptoPassword)
const resetKeys = await hoodie.cryptoStore.setup(cryptoPassword)
displayResetKeys(resetKeys)
return signIn(username, password, cryptoPassword) // Call your signIn function

@@ -157,4 +160,3 @@ }

`unlock` will try to pull `hoodiePluginCryptoStore/salt` from the server,
to have the latest version of it.
`unlock` will try to pull `hoodiePluginCryptoStore/salt` from the server, to have the latest version of it.

@@ -186,4 +188,5 @@ Example:

// do your cleanup
hoodie.cryptoStore.lock() // lock the cryptoStore in an cryptographic saver way.
// It overwrites the key data 10 times.
// lock the cryptoStore in an cryptographic saver way.
// It overwrites the key data 10 times.
hoodie.cryptoStore.lock()
})

@@ -225,5 +228,35 @@ ```

console.log(result.notUpdated) // array of ids of all docs that weren't updated
displayResetKeys(result.resetKeys)
}
```
#### Reset the password
This works like [changing the password](#changing-the-password). With the difference of:
The user must enter a __reset-key__ not the old password, and calling `resetPassword()`!
`setup()`, `changePassword()` and `resetPassword()` result 10 reset-keys. You should display them to your user.
Or/and generate a text-file for your user to download.
```javascript
// Generate a text file with the reset keys in it.
function generateResetKeysFile (resetKeys) {
const text = resetKeys.join('\n')
const file = new Blob([text], { type: 'text/plain' })
const url = URL.createObjectURL(file)
const a = document.getElementById('yourDownloadLink')
a.href = url
a.download = '[Your app name] reset-keys.txt' // This will be the standard file name.
// then call later URL.revokeObjectURL(url) with the url of the file.
// To remove it from memory.
}
```
Then, when the user did forget their encryption password, call `cryptoStore.resetPassword(aResetKey, newPassword)`.
Every resetKey has a doc. Their `_id` starts with `hoodiePluginCryptoStore/pwReset_`, followed with the number 0 to 9. Please don't change them!
## v2 Update Notes

@@ -299,2 +332,14 @@

## v2.2 Update Notes
This version adds __password-resetKeys__. Display them to your user. If the user forgets their password, they can
reset their password, using one of the 10 reset keys.
They get generated by:
- `setup`
- `changePassword`
- `resetPassword`
__If the user was already setup, then no reset key will get generated, until the next password change!__
## About the cryptography

@@ -417,2 +462,3 @@

- [cryptoStore.changePassword(oldPassword, newPassword)](#cryptostorechangepasswordoldpassword-newpassword)
- [cryptoStore.resetPassword(resetKey, newPassword)](#cryptostoreresetpasswordresetkey-newpassword)
- [cryptoStore.lock()](#cryptostorelock)

@@ -498,2 +544,5 @@ - [cryptoStore.add(properties)](#cryptostoreaddproperties)

Results with an Array of 10 `resetKeys` (Strings). `crytoStore.resetPassword()` requires them, in case the
user did forget their encryption-password.
Sets up the encryption, generates a salt and saves it in `hoodiePluginCryptoStore/salt`.

@@ -525,4 +574,8 @@ A salt is a string that will get used with the password together for the encryption. [More about what the salt is](http://www.passwordbreeder.com/page/salt).

}
await hoodie.cryptoStore.setup(cryptoPassword)
const resetKeys = await hoodie.cryptoStore.setup(cryptoPassword)
// This can be: displaying the 10 keys to the user
// or/and generate a text-file for the user to download.
displayResetKeys(resetKeys)
return signIn(username, password, cryptoPassword) // Call your signIn function

@@ -545,2 +598,5 @@ }

Results with an Array of 10 `resetKeys` (Strings). `crytoStore.resetPassword()` requires them, in case the
user did forget their encryption-password.
Sets up the encryption and saves the salt in `hoodiePluginCryptoStore/salt`.

@@ -574,4 +630,8 @@ A salt is a string that will get used with the password together for the encryption.

}
await hoodie.cryptoStore.setup(cryptoPassword, salt)
const resetKeys = await hoodie.cryptoStore.setup(cryptoPassword, salt)
// This can be: displaying the 10 keys to the user
// or/and generate a text-file for the user to download.
displayResetKeys(resetKeys)
return signIn(username, password, cryptoPassword) // Call your signIn function

@@ -637,3 +697,5 @@ }

Resolves with an object with the new `salt` and an array (`notUpdated`) with the ids of not updated docs.
Resolves with an object with the new `salt`, an array (`notUpdated`) with the ids of not updated docs and
an Array of 10 new `resetKeys`.
It will update all with `oldPassword` encrypted documents. And encrypt them with with the help of

@@ -647,3 +709,3 @@ the `newPassword`. It also updates the `salt` in `hoodiePluginCryptoStore/salt`.

badarg | 500 | New password must be a string! | The new password wasn't a string.
badarg | 500 | password is to short! | The password must be longer than 2 chars.
badarg | 500 | password is to short! | The new password must be longer than 2 chars.
unauthorized | 401 | Name or password is incorrect. | The entered old password is wrong.

@@ -657,2 +719,6 @@

console.log(report.notUpdated) // array with all ids of encrypted docs that have not been updated
// This can be: displaying the 10 keys to the user
// or/and generate a text-file for the user to download.
displayResetKeys(report.resetKeys)
}).catch(function (error) {

@@ -663,2 +729,51 @@ console.error(error)

### cryptoStore.resetPassword(resetKey, newPassword)
```javascript
cryptoStore.resetPassword(resetKey, newPassword)
```
This is for when the __user did forget their password__.
Changes the encryption password and salt. Then it will update all encrypted documents.
All encrypted documents, that couldn't get decrypted, will not get updated! The Array, at the `notUpdated` field, will include all their `_id`s.
Argument | Type | Description | Required
--------------|--------|----------------|---------
`resetKey` | String | One of the `resetKeys` generated by `setup()`, `changePassword()` and `resetPassword()` | Yes
`newPassword` | String | New password, with which the docs will be encrypted | Yes
Resolves with an object with the new `salt`, an array (`notUpdated`) with the ids of not updated docs and
an Array of 10 new `resetKeys`.
It will update all with the main password encrypted documents. And encrypt them with with the help of
the `newPassword`. It also updates the `salt` in `hoodiePluginCryptoStore/salt`.
Rejects with:
Name | Status | Description | Why
------|--------|-------------|----
badarg | 500 | New password must be a string! | The new password wasn't a string.
badarg | 500 | password is to short! | The new password must be longer than 2 chars.
unauthorized | 401 | Reset-key is incorrect. | The entered `resetKey` is wrong.
Example
```javascript
async function userDidForgetPassword (resetKey) {
try {
const report = await hoodie.cryptoStore.resetPassword('my-old-password', 'secret')
console.log('all documents are updated!')
console.log(report.salt) // the new salt
console.log(report.notUpdated) // array with all ids of encrypted docs that have not been updated
// This can be: displaying the 10 keys to the user
// or/and generate a text-file for the user to download.
displayResetKeys(report.resetKeys)
} catch (error) {
console.error(error)
}
}
```
### cryptoStore.lock()

@@ -665,0 +780,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc