Skip to content

Commit

Permalink
Update identity 0.6 to Stronghold 2.0 (#1174)
Browse files Browse the repository at this point in the history
* Use stronghold migration branch as dependency

* Deal with stronghold breaking changes

* Apply rustfmt

* Use the `2.0` stronghold branch

* Update Cargo.lock of stronghold-nodejs

* Remove outdated lint

* Use stronghold 2.0 rc version

* Bump to rc.1

* Bump stronghold to `2.0.0`
  • Loading branch information
PhilippGackstatter authored Aug 3, 2023
1 parent 40b9fb2 commit 9845be0
Show file tree
Hide file tree
Showing 10 changed files with 959 additions and 476 deletions.
1,251 changes: 884 additions & 367 deletions bindings/stronghold-nodejs/Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bindings/stronghold-nodejs/src/types/key_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use identity_core::crypto::KeyType;
use napi::bindgen_prelude::ToNapiValue;
use napi::bindgen_prelude::FromNapiValue;
use napi_derive::napi;

#[napi]
Expand Down
33 changes: 0 additions & 33 deletions bindings/wasm/build/lints.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,10 @@ function lintBigInt(content) {
}
}

/**
* Rejects any `<obj>.ptr = 0;` occurrence, excluding `this.ptr = 0;` in `free()` implementations.
*
* Prevents generated code that nulls out Wasm pointers without de-registering the finalizer, since they cause
* runtime errors during automatic garbage collection from WasmRefCell thinking the instance is still borrowed.
*
* Functions which take owned parameters cause this situation; the solution is to borrow and clone the parameter
* instead.
**/
function lintPtrNullWithoutFree(content) {
// Find line numbers of offending code.
const lines = content.split(/\r?\n/);
const matches = lines.flatMap(function (line, number) {
if (/(?<!this).ptr = 0;/.test(line)) {
return [(number + 1) + " " + line.trim()];
} else {
return [];
}
});
if (matches.length > 0) {
throw(`ERROR: generated Javascript should not include 'obj.ptr = 0;'.
When weak references are enabled with '--weak-refs', WasmRefCell in wasm-bindgen causes
runtime errors from automatic garbage collection trying to free objects taken as owned parameters.
Matches:
${matches}
SUGGESTION: change any exported functions which take an owned parameter (excluding flat enums) to use a borrow instead.
See: https://github.com/rustwasm/wasm-bindgen/pull/2677`);
}
}

/** Runs all custom lints on the generated code. Exits the process immediately with code 1 if any fail. **/
function lintAll(content) {
try {
lintBigInt(content);
lintPtrNullWithoutFree(content);
} catch (err) {
console.error("Custom lint failed!");
console.error(err);
Expand Down
126 changes: 63 additions & 63 deletions bindings/wasm/docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ See <code>IVerifierOptions</code>.</p>
## Members

<dl>
<dt><a href="#MethodRelationship">MethodRelationship</a></dt>
<dd></dd>
<dt><a href="#KeyType">KeyType</a></dt>
<dd></dd>
<dt><a href="#DIDMessageEncoding">DIDMessageEncoding</a></dt>
<dd></dd>
<dt><a href="#StatusCheck">StatusCheck</a></dt>
Expand Down Expand Up @@ -197,10 +201,6 @@ This variant is the default used if no other variant is specified when construct
<dt><a href="#FirstError">FirstError</a></dt>
<dd><p>Return after the first error occurs.</p>
</dd>
<dt><a href="#KeyType">KeyType</a></dt>
<dd></dd>
<dt><a href="#MethodRelationship">MethodRelationship</a></dt>
<dd></dd>
</dl>

## Functions
Expand All @@ -222,9 +222,6 @@ publishing to the Tangle.
**Kind**: global class

* [Account](#Account)
* [.attachMethodRelationships(options)](#Account+attachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>
* [.createMethod(options)](#Account+createMethod) ⇒ <code>Promise.&lt;void&gt;</code>
* [.detachMethodRelationships(options)](#Account+detachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>
* [.did()](#Account+did)[<code>DID</code>](#DID)
* [.autopublish()](#Account+autopublish) ⇒ <code>boolean</code>
* [.autosave()](#Account+autosave)[<code>AutoSave</code>](#AutoSave)
Expand All @@ -242,47 +239,14 @@ publishing to the Tangle.
* [.unrevokeCredentials(fragment, credentialIndices)](#Account+unrevokeCredentials) ⇒ <code>Promise.&lt;void&gt;</code>
* [.encryptData(plaintext, associated_data, encryption_algorithm, cek_algorithm, public_key)](#Account+encryptData)[<code>Promise.&lt;EncryptedData&gt;</code>](#EncryptedData)
* [.decryptData(data, encryption_algorithm, cek_algorithm, fragment)](#Account+decryptData) ⇒ <code>Promise.&lt;Uint8Array&gt;</code>
* [.setAlsoKnownAs(options)](#Account+setAlsoKnownAs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.deleteMethod(options)](#Account+deleteMethod) ⇒ <code>Promise.&lt;void&gt;</code>
* [.deleteService(options)](#Account+deleteService) ⇒ <code>Promise.&lt;void&gt;</code>
* [.setAlsoKnownAs(options)](#Account+setAlsoKnownAs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.setController(options)](#Account+setController) ⇒ <code>Promise.&lt;void&gt;</code>
* [.createService(options)](#Account+createService) ⇒ <code>Promise.&lt;void&gt;</code>

<a name="Account+attachMethodRelationships"></a>

### account.attachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Attach one or more verification relationships to a method.

Note: the method must exist and be in the set of verification methods;
it cannot be an embedded method.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>AttachMethodRelationshipOptions</code> |

<a name="Account+createMethod"></a>

### account.createMethod(options) ⇒ <code>Promise.&lt;void&gt;</code>
Adds a new verification method to the DID document.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>CreateMethodOptions</code> |

<a name="Account+detachMethodRelationships"></a>

### account.detachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Detaches the given relationship from the given method, if the method exists.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>DetachMethodRelationshipOptions</code> |
* [.attachMethodRelationships(options)](#Account+attachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>
* [.createMethod(options)](#Account+createMethod) ⇒ <code>Promise.&lt;void&gt;</code>
* [.detachMethodRelationships(options)](#Account+detachMethodRelationships) ⇒ <code>Promise.&lt;void&gt;</code>

<a name="Account+did"></a>

Expand Down Expand Up @@ -475,17 +439,6 @@ Returns the decrypted text.
| cek_algorithm | [<code>CekAlgorithm</code>](#CekAlgorithm) |
| fragment | <code>string</code> |

<a name="Account+setAlsoKnownAs"></a>

### account.setAlsoKnownAs(options) ⇒ <code>Promise.&lt;void&gt;</code>
Sets the `alsoKnownAs` property in the DID document.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>SetAlsoKnownAsOptions</code> |

<a name="Account+deleteMethod"></a>

### account.deleteMethod(options) ⇒ <code>Promise.&lt;void&gt;</code>
Expand All @@ -508,6 +461,17 @@ Deletes a Service if it exists.
| --- | --- |
| options | <code>DeleteServiceOptions</code> |

<a name="Account+setAlsoKnownAs"></a>

### account.setAlsoKnownAs(options) ⇒ <code>Promise.&lt;void&gt;</code>
Sets the `alsoKnownAs` property in the DID document.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>SetAlsoKnownAsOptions</code> |

<a name="Account+setController"></a>

### account.setController(options) ⇒ <code>Promise.&lt;void&gt;</code>
Expand All @@ -530,6 +494,42 @@ Adds a new Service to the DID Document.
| --- | --- |
| options | <code>CreateServiceOptions</code> |

<a name="Account+attachMethodRelationships"></a>

### account.attachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Attach one or more verification relationships to a method.

Note: the method must exist and be in the set of verification methods;
it cannot be an embedded method.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>AttachMethodRelationshipOptions</code> |

<a name="Account+createMethod"></a>

### account.createMethod(options) ⇒ <code>Promise.&lt;void&gt;</code>
Adds a new verification method to the DID document.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>CreateMethodOptions</code> |

<a name="Account+detachMethodRelationships"></a>

### account.detachMethodRelationships(options) ⇒ <code>Promise.&lt;void&gt;</code>
Detaches the given relationship from the given method, if the method exists.

**Kind**: instance method of [<code>Account</code>](#Account)

| Param | Type |
| --- | --- |
| options | <code>DetachMethodRelationshipOptions</code> |

<a name="AccountBuilder"></a>

## AccountBuilder
Expand Down Expand Up @@ -4857,6 +4857,14 @@ This is possible because Ed25519 is birationally equivalent to Curve25519 used b
| --- | --- |
| publicKey | <code>Uint8Array</code> |

<a name="MethodRelationship"></a>

## MethodRelationship
**Kind**: global variable
<a name="KeyType"></a>

## KeyType
**Kind**: global variable
<a name="DIDMessageEncoding"></a>

## DIDMessageEncoding
Expand Down Expand Up @@ -4938,14 +4946,6 @@ Return all errors that occur during validation.
## FirstError
Return after the first error occurs.

**Kind**: global variable
<a name="KeyType"></a>

## KeyType
**Kind**: global variable
<a name="MethodRelationship"></a>

## MethodRelationship
**Kind**: global variable
<a name="start"></a>

Expand Down
2 changes: 1 addition & 1 deletion identity_account_storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ identity_core = { version = "=0.6.2", path = "../identity_core", default-feature
identity_did = { version = "=0.6.2", path = "../identity_did", default-features = false }
identity_iota_core = { version = "=0.6.2", path = "../identity_iota_core", default-features = false }
iota-crypto = { version = ">=0.7, <0.10", default-features = false, features = ["hmac", "pbkdf", "sha", "std", "aes", "aes-kw"] }
iota_stronghold = { version = "1.0.5", default-features = false, features = ["std"], optional = true }
iota_stronghold = { version = "2.0.0", default-features = false, features = ["std"], optional = true }
once_cell = { version = "1.7", default-features = false, features = ["std"], optional = true }
parking_lot = { version = "0.12" }
rand = { version = "0.8", default-features = false, features = ["std", "std_rng"], optional = true }
Expand Down
3 changes: 2 additions & 1 deletion identity_account_storage/src/storage/stronghold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use rand::distributions::DistString;
use tokio::sync::RwLockReadGuard;
use tokio::sync::RwLockWriteGuard;
use zeroize::Zeroize;
use zeroize::Zeroizing;

use crate::error::Error;
use crate::error::Result;
Expand Down Expand Up @@ -468,7 +469,7 @@ pub(crate) fn insert_private_key(client: &Client, mut private_key: PrivateKey, l
private_key.zeroize();

vault
.write_secret(stronghold_location, private_key_vec)
.write_secret(stronghold_location, Zeroizing::new(private_key_vec))
.map_err(|err| StrongholdError::Vault(VaultOperation::WriteSecret, err))
.map_err(Into::into)
}
Expand Down
2 changes: 2 additions & 0 deletions identity_account_storage/src/stronghold/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum StrongholdError {
Snapshot(SnapshotOperation, SnapshotPath, #[source] ClientError),
#[error("failed to load password into key provider")]
Memory(#[source] MemoryError),
#[error("failed to construct a key provider from a password")]
Key(#[source] ClientError),
}

#[non_exhaustive]
Expand Down
3 changes: 2 additions & 1 deletion identity_account_storage/src/stronghold/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use iota_stronghold::procedures::GenerateKey;
use iota_stronghold::Client;
use iota_stronghold::ClientVault;
use iota_stronghold::Location;
use zeroize::Zeroizing;

use crate::storage::stronghold::aead_decrypt;
use crate::storage::stronghold::aead_encrypt;
Expand Down Expand Up @@ -54,7 +55,7 @@ async fn test_mutate_client_persists_client_into_snapshot() {
let vault: ClientVault = client.vault(b"vault");

vault
.write_secret(location.into(), keypair.private().as_ref().to_vec())
.write_secret(location.into(), Zeroizing::new(keypair.private().as_ref().to_vec()))
.unwrap();

Ok(())
Expand Down
12 changes: 3 additions & 9 deletions identity_account_storage/src/stronghold/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@ use iota_stronghold::KeyProvider;
use iota_stronghold::SnapshotPath;
use iota_stronghold::Stronghold as IotaStronghold;
use tokio::sync::RwLock;
use zeroize::Zeroize;

use crate::stronghold::error::ClientOperation;
use crate::stronghold::error::SnapshotOperation;
use crate::stronghold::error::StrongholdError;
use crate::stronghold::ClientPath;
use crate::stronghold::StrongholdResult;
use crate::utils::derive_encryption_key;
use crate::utils::EncryptionKey;
use crate::Result;

/// The implementation of the `Storage` interface using `Stronghold`.
Expand All @@ -44,17 +41,14 @@ impl Stronghold {
/// * `password`: password for the Stronghold snapshot file. If this is cloned from a reference,
/// zeroization of that reference is strongly recommended.
/// * `dropsave`: persist all changes when the instance is dropped. Default: true.
pub async fn new<T>(path: &T, mut password: String, dropsave: Option<bool>) -> Result<Self>
pub async fn new<T>(path: &T, password: String, dropsave: Option<bool>) -> Result<Self>
where
T: AsRef<Path> + ?Sized,
{
let stronghold: IotaStronghold = IotaStronghold::default();

let mut key: EncryptionKey = derive_encryption_key(&password);
password.zeroize();

let key_provider = KeyProvider::try_from(key.to_vec()).map_err(StrongholdError::Memory)?;
key.zeroize();
let key_provider =
KeyProvider::with_passphrase_hashed_blake2b(password).map_err(|err| StrongholdError::Key(err))?;

// If the snapshot file exists, we load it.
// If it doesn't we write data into the in memory `Stronghold` and only persist to disk on first write.
Expand Down
2 changes: 1 addition & 1 deletion identity_iota/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,4 @@ pub mod prelude {
pub use identity_iota_client::tangle::Client;
pub use identity_iota_client::Result;
pub use identity_iota_core::document::IotaDocument;
}
}

0 comments on commit 9845be0

Please sign in to comment.