> For the complete documentation index, see [llms.txt](https://docs.sudoplatform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sudoplatform.com/guides/decentralized-identity/decentralized-identity/edge-agent-sdk/utilize-alternative-cryptography-providers.md).

# Utilize Alternative Cryptography Providers

By default, the **Edge Agent SDK** utilizes software for cryptographic key management. These keys are managed by [Askar](https://github.com/openwallet-foundation/askar), and encrypted at rest. However, in some use cases, such as those where higher assurance is required, alternative cryptography providers may be injected into the Edge Agent, allowing key management to occur outside of the agent's software.&#x20;

These custom cryptography providers may utilize whatever provider is desired, such as: device embedded hardware security modules (HSMs), external HSMs (e.g. hardware tokens), cloud HSMs, etc.

&#x20;In addition to allowing custom cryptography providers, we provide default cryptography provider implementations for **iOS** and **Android** which utilize the **device's secure hardware** for key management.

## Implement a Custom Provider

Custom cryptography providers must conform to the `ExternalCryptoProvider` interface/protocol. To implement `ExternalCryptoProvider`, essential key usage and management functionality must be fulfilled:

* `createKeyPair` - method to create and store a key pair with the provider
* `deleteKeyPair`- method to delete a key pair from the provider
* `sign`- method to sign over some block of data with the given key pair within the provider

Notably, `ExternalCryptoProvider`s must also implement a unique `enclaveId` identifier. This identifier should be kept unique and constant.

{% hint style="info" %}
The iOS and Android SDK provides extensive documentation about how each method and variable of the interface must be implemented. Additionally, the `AndroidHardwareCryptoProvider` and `iOSHardwareCryptoProvider` default implementations can be used as a reference.
{% endhint %}

## Register the Provider

After implementing a custom provider, or if simply using the default `AndroidHardwareCryptoProvider`/`iOSHardwareCryptoProvider` implementations, an instance of that provider must be registered when building the agent instance.

To do this, the additional `registerExternalCryptoProvider` method should be used with the agent builder (see [Agent Management](/guides/decentralized-identity/decentralized-identity/edge-agent-sdk/agent-management.md#builder)). Multiple crypto providers can be registered, so long as they are unique.

{% tabs %}
{% tab title="Swift" %}

```swift
let myCustomCryptoProvider: any ExternalCryptoProvider // some implementation of the protocol

let networkConfiguration = NetworkConfiguration(
    sovConfiguration: nil,
    cheqdConfiguration: NetworkConfiguration.Cheqd()
)
let agentConfiguration = AgentConfiguration(networkConfiguration: networkConfiguration)
let agent = try SudoDIEdgeAgentBuilder()
    .setAgentConfiguration(agentConfiguration: agentConfiguration)
    .registerExternalCryptoProvider(provider: myCustomCryptoProvider)
    .registerExternalCryptoProvider(provider: IOSHardwareCryptoProvider())
    .build()
```

{% endtab %}

{% tab title="Kotlin" %}

<pre class="language-kotlin"><code class="lang-kotlin"><strong>val appContext: Context // Android application context
</strong>val myCustomCryptoProvider: ExternalCryptoProvider&#x3C;*,*> // some implementation of the interface

val networkConfiguration = NetworkConfiguration(
    sovConfiguration = null,
    cheqdConfiguration = NetworkConfiguration.Cheqd()
)

val agentConfiguration = AgentConfiguration(
    networkConfiguration = networkConfiguration
)

val agent: SudoDIEdgeAgent = SudoDIEdgeAgent.builder()
    .setContext(appContext)
    .setAgentConfiguration(agentConfiguration)
    .registerExternalCryptoProvider(myCustomCryptoProvider)
    .registerExternalCryptoProvider(AndroidHardwareCryptoProvider())
    .build()
</code></pre>

{% endtab %}
{% endtabs %}

## Utilizing the Provider

Once a provider instance is registered with the agent, the agent can be instructed to utilize that specific provider class via the configuration options for some operations.

### Create a DID backed by a Custom Cryptography Provider

One such operation where custom cryptography providers can be utilized, is during DID creation when the underlying DID key is generated. Utilizing a custom provider here means that the created DID will have a cryptographic key which is backed by that provider. Then in subsequent usages of that DID, such as binding it to an incoming credential or presenting a credential, the custom provider will be invoked whenever the DID's signature is required.

By default, the key pair for a new DID will be generated using the agent's internal software (see [Manage DIDs](/guides/decentralized-identity/decentralized-identity/edge-agent-sdk/manage-dids.md#create-dids)). However this can be changed with the `CreateKeyPairEnclaveOptions` options in the `CreateDidOptions` for did:key and did:jwk DIDs. For instance, to create a did:key using the device's secure hardware key management:

{% tabs %}
{% tab title="Swift" %}

```swift
let agent: SudoDIEdgeAgent

do {
    let createdDid = try await agent.dids.createDid(
        options: .didKey(
            keyType: .ed25519,
            enclaveOptions: .external(.init(
                providerClass: IOSHardwareCryptoProvider.self,
                providerOptions: .init()
            ))
        )
    )
} catch {
    // handle error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val agent: SudoDIEdgeAgent

val hardwareEnclaveOptions = CreateKeyPairEnclaveOptions.External(
    providerClass = AndroidHardwareCryptoProvider::class,
    providerOptions = AndroidHardwareCryptoProvider.CreateKeyPairOptions(
        hardwarePreference = AndroidHardwareCryptoProvider.HardwarePreference.STRONGBOX_TEE_FALLBACK
    )
)

try {
    val createdDid = agent.dids.createDid(
        options = CreateDidOptions.DidKey(
            keyType = DidKeyType.ED25519,
            enclaveOptions = hardwareEnclaveOptions
        )
    )
} catch (e: DidsModule.CreateDidException) {
    // handle error
}
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Check out our [sample apps](/guides/decentralized-identity/decentralized-identity/edge-agent-sdk/sdk-releases.md) for a reference on how these secure hardware cryptography providers can be utilized.
{% endhint %}
