Skip to content

Commit

Permalink
feat(credentials): use appInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
s1fr0 committed Feb 6, 2023
1 parent b57c6ba commit af90ba5
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 61 deletions.
42 changes: 20 additions & 22 deletions tests/v2/test_utils_credentials.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{.used.}

import
std/[algorithm, options, os],
std/[algorithm, json, options, os],
testutils/unittests, chronos, stint,
../../waku/v2/utils/credentials,
../test_helpers
Expand All @@ -12,16 +12,15 @@ procSuite "Credentials test suite":

# We initialize the RNG in test_helpers
let rng = rng()
let testAppInfo = AppInfo(application: "test", appIdentifier: "1234", version: "0.1")

asyncTest "Create keystore":

let filepath = "./testAppKeystore.txt"
defer: removeFile(filepath)

let keystoreRes = createAppKeystore(path = filepath,
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
keystoreRes.isOk()
Expand All @@ -31,14 +30,23 @@ procSuite "Credentials test suite":
let filepath = "./testAppKeystore.txt"
defer: removeFile(filepath)

# If no keystore exists at filepath, a new one is created for appInfo and empty credentials
let keystoreRes = loadAppKeystore(path = filepath,
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
keystoreRes.isOk()

let keystore = keystoreRes.get()

check:
keystore.hasKeys(["application", "appIdentifier", "version", "credentials"])
keystore["application"].getStr() == testAppInfo.application
keystore["appIdentifier"].getStr() == testAppInfo.appIdentifier
keystore["version"].getStr() == testAppInfo.version
# We assume the loaded keystore to not have credentials set (previous tests delete the keystore at filepath)
keystore["credentials"].getElems().len() == 0

asyncTest "Add credentials to keystore":

let filepath = "./testAppKeystore.txt"
Expand Down Expand Up @@ -79,9 +87,7 @@ procSuite "Credentials test suite":
let keystoreRes = addMembershipCredentials(path = filepath,
credentials = @[membershipCredentials1, membershipCredentials2],
password = password,
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
keystoreRes.isOk()
Expand Down Expand Up @@ -135,9 +141,7 @@ procSuite "Credentials test suite":
let keystoreRes = addMembershipCredentials(path = filepath,
credentials = @[membershipCredentials1, membershipCredentials2, membershipCredentials3, membershipCredentials4],
password = password,
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
keystoreRes.isOk()
Expand All @@ -158,9 +162,7 @@ procSuite "Credentials test suite":
# We retrieve all credentials stored under password (no filter)
var recoveredCredentialsRes = getMembershipCredentials(path = filepath,
password = password,
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
recoveredCredentialsRes.isOk()
Expand All @@ -171,9 +173,7 @@ procSuite "Credentials test suite":
recoveredCredentialsRes = getMembershipCredentials(path = filepath,
password = password,
filterIdentityCredentials = @[idCredential1],
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
recoveredCredentialsRes.isOk()
Expand All @@ -183,9 +183,7 @@ procSuite "Credentials test suite":
recoveredCredentialsRes = getMembershipCredentials(path = filepath,
password = password,
filterIdentityCredentials = @[idCredential1, idCredential2],
application = "test",
appIdentifier = "1234",
version = "0.1")
appInfo = testAppInfo)

check:
recoveredCredentialsRes.isOk()
Expand Down
8 changes: 2 additions & 6 deletions tests/v2/test_waku_rln_relay.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1059,16 +1059,12 @@ suite "Waku rln relay":
addMembershipCredentials(path = filepath,
credentials = @[rlnMembershipCredentials],
password = password,
application = RLNKeystoreApplication,
appIdentifier = RLNKeystoreAppIdentifier,
version = RLNKeystoreVersion).isOk()
appInfo = RLNAppInfo).isOk()

let readCredentialsResult = getMembershipCredentials(path = filepath,
password = password,
filterMembershipContracts = @[rlnMembershipContract],
application = RLNKeystoreApplication,
appIdentifier = RLNKeystoreAppIdentifier,
version = RLNKeystoreVersion)
appInfo = RLNAppInfo)

require:
readCredentialsResult.isOk()
Expand Down
7 changes: 4 additions & 3 deletions waku/v2/protocol/waku_rln_relay/constants.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import
stint

import
../../utils/credentials

# Acceptable roots for merkle root validation of incoming messages
const AcceptableRootWindowSize* = 5

Expand Down Expand Up @@ -51,8 +54,6 @@ const MaxEpochGap* = uint64(MaxClockGapSeconds/EpochUnitSeconds)

# RLN Keystore defaults
const
RLNKeystoreApplication* = "nwaku-rln-relay"
RLNKeystoreAppIdentifier* = "01234567890abcdef"
RLNKeystoreVersion* = "0.1"
RLNAppInfo* = AppInfo(application: "nwaku-rln-relay", appIdentifier: "01234567890abcdef", version: "0.1")
# NOTE: 256-bytes long credentials are due to the use of BN254 in RLN. Other implementations/curves might have a different byte size
CredentialByteSize* = 256
8 changes: 2 additions & 6 deletions waku/v2/protocol/waku_rln_relay/utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -937,9 +937,7 @@ proc mount(wakuRelay: WakuRelay,
password = conf.rlnRelayCredentialsPassword,
filterMembershipContracts = @[rlnMembershipContract],
# TODO: the following can be embedded in conf
application = RLNKeystoreApplication,
appIdentifier = RLNKeystoreAppIdentifier,
version = RLNKeystoreVersion)
appInfo = RLNAppInfo)

if readCredentialsRes.isErr():
return err("RLN credentials cannot be read")
Expand Down Expand Up @@ -1011,9 +1009,7 @@ proc mount(wakuRelay: WakuRelay,
credentials = @[credentials.get()],
password = conf.rlnRelayCredentialsPassword,
# TODO: the following can be embedded in conf
application = RLNKeystoreApplication,
appIdentifier = RLNKeystoreAppIdentifier,
version = RLNKeystoreVersion).isErr():
appInfo = RLNAppInfo).isErr():
return err("error in storing rln credentials")
return ok(wakuRlnRelay)

Expand Down
45 changes: 21 additions & 24 deletions waku/v2/utils/credentials.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ else:
{.push raises: [].}

import
chronicles, options, json, strutils,
options, json, strutils,
stew/byteutils,
std/[algorithm, os, sequtils, sets],
./keyfile
Expand Down Expand Up @@ -42,6 +42,11 @@ type MembershipCredentials* = object
identityCredential*: IdentityCredential
membershipGroups*: seq[MembershipGroup]

type AppInfo* = object
application*: string
appIdentifier*: string
version*: string

type AppKeystore* = object
application*: string
appIdentifier*: string
Expand Down Expand Up @@ -84,12 +89,12 @@ proc decode*(encodedCredential: seq[byte]): KeystoreResult[MembershipCredentials
return err(OsError)

# Checks if a JsonNode has all keys contained in "keys"
proc hasKeys(data: JsonNode, keys: openArray[string]): bool =
proc hasKeys*(data: JsonNode, keys: openArray[string]): bool =
return all(keys, proc (key: string): bool = return data.hasKey(key))

# Safely saves a JsonNode to disk.
# If exists, the destination file is renamed with extension .bkp; the file is written at its destination and the .bkp file is removed if write is successful, otherwise is restored
proc save(json: JsonNode, path: string, separator: string): KeystoreResult[void] =
proc save*(json: JsonNode, path: string, separator: string): KeystoreResult[void] =

# We first backup the current keystore
if fileExists(path):
Expand Down Expand Up @@ -137,15 +142,13 @@ proc sortMembershipGroup*(a,b: MembershipGroup): int =

# This proc creates an empty keystore (i.e. with no credentials)
proc createAppKeystore*(path: string,
application: string,
appIdentifier: string,
version: string,
appInfo: AppInfo,
separator: string = "\n"): KeystoreResult[void] =

let keystore = AppKeystore(application: application,
appIdentifier: appIdentifier,
let keystore = AppKeystore(application: appInfo.application,
appIdentifier: appInfo.appIdentifier,
credentials: @[],
version: version)
version: appInfo.version)

var jsonKeystore: string
jsonKeystore.toUgly(%keystore)
Expand All @@ -169,9 +172,7 @@ proc createAppKeystore*(path: string,
# This proc load a keystore based on the application, appIdentifier and version filters.
# If none is found, it automatically creates an empty keystore for the passed parameters
proc loadAppKeystore*(path: string,
application: string,
appIdentifier: string,
version: string,
appInfo: AppInfo,
separator: string = "\n"): KeystoreResult[JsonNode] =

## Load and decode JSON keystore from pathname
Expand All @@ -180,7 +181,7 @@ proc loadAppKeystore*(path: string,

# If no keystore exists at path we create a new empty one with passed keystore parameters
if fileExists(path) == false:
let newKeystore = createAppKeystore(path, application, appIdentifier, version, separator)
let newKeystore = createAppKeystore(path, appInfo, separator)
if newKeystore.isErr():
return err(CreateKeystoreError)

Expand Down Expand Up @@ -209,9 +210,9 @@ proc loadAppKeystore*(path: string,
# We check if parsed json contains the relevant keystore credentials fields and if these are set to the passed parameters
# (note that "if" is lazy, so if one of the .contains() fails, the json fields contents will not be checked and no ResultDefect will be raised due to accessing unavailable fields)
if data.hasKeys(["application", "appIdentifier", "credentials", "version"]) and
data["application"].getStr() == application and
data["appIdentifier"].getStr() == appIdentifier and
data["version"].getStr() == version:
data["application"].getStr() == appInfo.application and
data["appIdentifier"].getStr() == appInfo.appIdentifier and
data["version"].getStr() == appInfo.version:
# We return the first json keystore that matches the passed app parameters
# We assume a unique kesytore with such parameters is present in the file
matchingAppKeystore = data
Expand All @@ -236,14 +237,12 @@ proc loadAppKeystore*(path: string,
proc addMembershipCredentials*(path: string,
credentials: seq[MembershipCredentials],
password: string,
application: string,
appIdentifier: string,
version: string,
appInfo: AppInfo,
separator: string = "\n"): KeystoreResult[void] =

# We load the keystore corresponding to the desired parameters
# This call ensures that JSON has all required fields
let jsonKeystoreRes = loadAppKeystore(path, application, appIdentifier, version, separator)
let jsonKeystoreRes = loadAppKeystore(path, appInfo, separator)

if jsonKeystoreRes.isErr():
return err(LoadKeystoreError)
Expand Down Expand Up @@ -359,15 +358,13 @@ proc getMembershipCredentials*(path: string,
password: string,
filterIdentityCredentials: seq[IdentityCredential] = @[],
filterMembershipContracts: seq[MembershipContract] = @[],
application: string,
appIdentifier: string,
version: string): KeystoreResult[seq[MembershipCredentials]] =
appInfo: AppInfo): KeystoreResult[seq[MembershipCredentials]] =

var outputMembershipCredentials: seq[MembershipCredentials] = @[]

# We load the keystore corresponding to the desired parameters
# This call ensures that JSON has all required fields
let jsonKeystoreRes = loadAppKeystore(path, application, appIdentifier, version)
let jsonKeystoreRes = loadAppKeystore(path, appInfo)

if jsonKeystoreRes.isErr():
return err(LoadKeystoreError)
Expand Down

0 comments on commit af90ba5

Please sign in to comment.