Skip to content

Commit

Permalink
Restructure project and integrate didcomm-jvm with multi-recipient su…
Browse files Browse the repository at this point in the history
…pport
  • Loading branch information
tdiesler committed Dec 20, 2022
1 parent f7f5ac1 commit db3031f
Show file tree
Hide file tree
Showing 50 changed files with 1,931 additions and 113 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

### Mac OS ###
.DS_Store
data/

### Maven
target/

### Python
__pycache__/
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
# Nessus DIDComm
## Nessus DIDComm

Nessus DIDComm is about digital identy and VCs based on [DIDComm](https://identity.foundation/didcomm-messaging/spec/v2.0).

[<img src="docs/img/ssi-book.png" height="200" alt="self sovereign identity">](https://www.manning.com/books/self-sovereign-identity)

## External Documentation
### External Documentation

* [The Story of Open SSI Standards](https://www.youtube.com/watch?v=RllH91rcFdE)
* [DIDComm Messaging](https://identity.foundation/didcomm-messaging/spec/v2.0)
* [DIDComm JVM](https://github.com/sicpa-dlab/didcomm-jvm)
* [Aries Cloud Agent](https://github.com/hyperledger/aries-cloudagent-python)
* [Aries Protocol RFCs](https://github.com/hyperledger/aries-rfcs/tree/main/features)

### Ledger with VON-Network

This project requires access to a Hyperledger Indy Network. Is is recommended to use the [VON Network](https://github.com/bcgov/von-network), developed as a portable Indy Node Network implementation for local development. Instructions for setting up the von-network can be viewed [here](https://github.com/bcgov/von-network#running-the-network-locally).

Basic instructions for using the VON Network are [here](https://github.com/bcgov/von-network/blob/main/docs/UsingVONNetwork.md).

### Start Hyperledger Aries Cloud Agent

Use this when you want to run the tests.

```
docker compose up --detach && docker compose logs -f acapy
```
86 changes: 86 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
#%L
Nessus Aries
%%
Copyright (C) 2021 - 2022 RedHat
%%
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#L%
-->


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.nessus.didcomm</groupId>
<artifactId>nessus-didcomm</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<name>Nessus DIDComm :: Core</name>

<artifactId>nessus-didcomm-core</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink</artifactId>
</dependency>
<dependency>
<groupId>id.walt</groupId>
<artifactId>waltid-ssi-kit</artifactId>
</dependency>
<dependency>
<groupId>io.github.microutils</groupId>
<artifactId>kotlin-logging-jvm</artifactId>
</dependency>
<dependency>
<groupId>network.idu.acapy</groupId>
<artifactId>aries-client-python</artifactId>
</dependency>
<dependency>
<groupId>org.didcommx</groupId>
<artifactId>didcomm</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>

<!-- Test -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
102 changes: 102 additions & 0 deletions core/src/main/kotlin/org/nessus/didcomm/aries/AriesAgent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.nessus.didcomm.aries

import org.hyperledger.aries.AriesClient
import org.hyperledger.aries.api.multitenancy.WalletRecord
import java.net.MalformedURLException
import java.net.URL

class AgentConfiguration(val adminUrl: String?, val userUrl: String?, val apiKey: String?) {

companion object {
private val host = System.getenv("ACAPY_HOSTNAME") ?: "localhost"
private val adminPort = System.getenv("ACAPY_ADMIN_PORT") ?: "8031"
private val userPort = System.getenv("ACAPY_USER_PORT") ?: "8030"
private val apiKey = System.getenv("ACAPY_ADMIN_API_KEY") ?: "adminkey"
val defaultConfiguration= AgentConfigurationBuilder()
.adminUrl(String.format("http://%s:%s", host, adminPort))
.userUrl(String.format("http://%s:%s", host, userPort))
.apiKey(apiKey)
.build()
}

val webSocketUrl: String
get() = try {
val url = URL(adminUrl)
String.format("ws://%s:%d/ws", url.host, url.port)
} catch (ex: MalformedURLException) {
throw IllegalArgumentException(ex)
}

override fun toString(): String {
val reductedApiKey = if (apiKey != null) apiKey.substring(0, 4) + "..." else null
return "AgentConfiguration [agentAdminUrl=$adminUrl, agentUserUrl=$userUrl, agentApiKey=$reductedApiKey]"
}

fun builder(): AgentConfigurationBuilder {
return AgentConfigurationBuilder()
}

class AgentConfigurationBuilder {
private var adminUrl: String? = null
private var userUrl: String? = null
private var apiKey: String? = null
fun adminUrl(adminUrl: String?): AgentConfigurationBuilder {
this.adminUrl = adminUrl
return this
}

fun userUrl(userUrl: String?): AgentConfigurationBuilder {
this.userUrl = userUrl
return this
}

fun apiKey(apiKey: String?): AgentConfigurationBuilder {
this.apiKey = apiKey
return this
}

fun build(): AgentConfiguration {
return AgentConfiguration(adminUrl, userUrl, apiKey)
}
}

private fun getSystemEnv(key: String?, defaultValue: String?): String? {
var value = System.getenv(key)
if (value == null || value.isBlank() || value.isEmpty()) value = defaultValue
return value
}
}

object AriesClientFactory {
/**
* Create a client for the admin wallet
*/
fun adminClient(): AriesClient {
return createClient(AgentConfiguration.defaultConfiguration, null)
}

/**
* Create a client for the admin wallet
*/
fun adminClient(config: AgentConfiguration): AriesClient {
return createClient(config, null)
}

/**
* Create a client for a multitenant wallet
*/
fun createClient(wallet: WalletRecord?): AriesClient {
return createClient(AgentConfiguration.defaultConfiguration, wallet)
}

/**
* Create a client for a multitenant wallet
*/
fun createClient(config: AgentConfiguration, wallet: WalletRecord?): AriesClient {
return AriesClient.builder()
.url(config.adminUrl)
.apiKey(config.apiKey)
.bearerToken(wallet?.token)
.build()
}
}
23 changes: 23 additions & 0 deletions core/src/main/kotlin/org/nessus/didcomm/wallet/Did.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.nessus.didcomm.wallet

import id.walt.crypto.KeyAlgorithm

val DEFAULT_KEY_ALGORITHM = KeyAlgorithm.EdDSA_Ed25519

enum class DidMethod(mname : String) {
KEY("key"),
SOV("sov");

fun supportedAlgorithms() : Set<KeyAlgorithm> {
return setOf(KeyAlgorithm.EdDSA_Ed25519)
}
}

open class Did(method: DidMethod) {
}

class DidKey() : Did(DidMethod.KEY) {
}

class DidSov() : Did(DidMethod.SOV) {
}
76 changes: 76 additions & 0 deletions core/src/main/kotlin/org/nessus/didcomm/wallet/Wallet.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

package org.nessus.didcomm.wallet

import id.walt.crypto.KeyAlgorithm
import id.walt.crypto.decBase64
import id.walt.crypto.keyPairGeneratorEd25519
import id.walt.crypto.toBase64
import id.walt.crypto.toHexString
import io.ipfs.multibase.Base58
import mu.KotlinLogging
import java.security.SecureRandom


class WalletError(message: String) : Exception(message)

fun ByteArray.encodeBase58(): String = Base58.encode(this)

fun String.decodeBase58(): ByteArray = Base58.decode(this)

class Wallet {

private val log = KotlinLogging.logger {}

/**
* Create and store a new local DID.
*/
fun createLocalDID(method: String, keyType: String = DEFAULT_KEY_ALGORITHM.name, seed: String? = null) {

val didMethod = DidMethod.valueOf(method.uppercase())
val keyAlgorithm = KeyAlgorithm.fromString(keyType)
var seedBytes = validateSeed(seed)
log.info(seedBytes.toHexString())

// validate key_type
if (keyAlgorithm !in didMethod.supportedAlgorithms())
throw WalletError("Invalid key type $keyType for method $method")

var secureRandom = SecureRandom.getInstance("SHA1PRNG")
secureRandom.setSeed(seedBytes)

val randomBytes = ByteArray(32)
secureRandom.nextBytes(randomBytes)
log.info(randomBytes.toHexString())

val keyPairGenerator = keyPairGeneratorEd25519()
keyPairGenerator.initialize(255, secureRandom)

val keypair = keyPairGenerator.generateKeyPair()
log.info("pubk {}", keypair.public.encoded.toHexString())
val verkey64 = keypair.public.toBase64()
val verkeyBytes = decBase64(verkey64)
val verkey58 = verkeyBytes.encodeBase58()

log.info("$verkey64")
log.info("$verkey58")
}

/**
* Convert a seed parameter to standard format and check length.
*
* @property seed the seed to validate.
* @return The validated and encoded seed
*/
private fun validateSeed(seed: String? = null): ByteArray {
var byteArray = ByteArray(32);
if (seed != null) {
byteArray = seed.toByteArray(Charsets.UTF_8)
} else {
SecureRandom().nextBytes(byteArray);
}
if (byteArray.size != 32) {
throw WalletError("Seed value must be 32 bytes in length")
}
return byteArray
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package org.didcommx.didcomm.diddoc
package org.didcommx.didcomm.test.diddoc

import org.didcommx.didcomm.common.VerificationMaterial
import org.didcommx.didcomm.common.VerificationMaterialFormat
import org.didcommx.didcomm.common.VerificationMethodType
import org.didcommx.didcomm.diddoc.DIDCommService
import org.didcommx.didcomm.diddoc.DIDDoc
import org.didcommx.didcomm.diddoc.VerificationMethod
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_AIP2_ENV_RFC587
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_V2

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package org.didcommx.didcomm.diddoc
package org.didcommx.didcomm.test.diddoc

import org.didcommx.didcomm.common.VerificationMaterial
import org.didcommx.didcomm.common.VerificationMaterialFormat
import org.didcommx.didcomm.common.VerificationMethodType
import org.didcommx.didcomm.diddoc.DIDCommService
import org.didcommx.didcomm.diddoc.DIDDoc
import org.didcommx.didcomm.diddoc.VerificationMethod
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_AIP2_ENV_RFC587
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_V2

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package org.didcommx.didcomm.diddoc
package org.didcommx.didcomm.test.diddoc

import org.didcommx.didcomm.common.VerificationMaterial
import org.didcommx.didcomm.common.VerificationMaterialFormat
import org.didcommx.didcomm.common.VerificationMethodType
import org.didcommx.didcomm.diddoc.DIDCommService
import org.didcommx.didcomm.diddoc.DIDDoc
import org.didcommx.didcomm.diddoc.VerificationMethod
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_AIP2_ENV_RFC587
import org.didcommx.didcomm.protocols.routing.PROFILE_DIDCOMM_V2

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package org.didcommx.didcomm.diddoc
package org.didcommx.didcomm.test.diddoc

import org.didcommx.didcomm.diddoc.DIDDoc

val DID_DOC_ELLIE = DIDDoc(
did = "did:example:ellie",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.didcommx.didcomm.diddoc
package org.didcommx.didcomm.test.diddoc

import org.didcommx.didcomm.common.VerificationMaterial
import org.didcommx.didcomm.common.VerificationMaterialFormat
import org.didcommx.didcomm.common.VerificationMethodType
import org.didcommx.didcomm.diddoc.DIDDoc
import org.didcommx.didcomm.diddoc.VerificationMethod

val MEDIATOR1_VERIFICATION_METHOD_KEY_AGREEM_X25519_1 = VerificationMethod(
id = "did:example:mediator1#key-x25519-1",
Expand Down
Loading

0 comments on commit db3031f

Please sign in to comment.