Skip to content

Commit

Permalink
fix: remove named capture groups (openwallet-foundation#1378)
Browse files Browse the repository at this point in the history
named capture groups are only supported in more recent versions of hermes

Signed-off-by: Timo Glastra <timo@animo.id>
  • Loading branch information
TimoGlastra committed Mar 11, 2023
1 parent dd6c020 commit a4204ef
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

describe('identifiers', () => {
describe('indySdkAnonCredsRegistryIdentifierRegex', () => {
test('matches against a legacy indy did, schema id, credential definition id and revocation registry id', () => {
test('matches against a legacy schema id, credential definition id and revocation registry id', () => {
const did = '7Tqg6BwSSWapxgUDm9KKgg'
const schemaId = 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0'
const credentialDefinitionId = 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID'
Expand Down
128 changes: 92 additions & 36 deletions packages/indy-sdk/src/anoncreds/utils/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,28 @@
import { DID_INDY_REGEX } from '../../utils/did'

const didIndyAnonCredsBase =
/(?<did>did:indy:(?<namespace>((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)?)):(?<namespaceIdentifier>([1-9A-HJ-NP-Za-km-z]{21,22})))\/anoncreds\/v0/
/(did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)?):([1-9A-HJ-NP-Za-km-z]{21,22}))\/anoncreds\/v0/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/SCHEMA/<schemaName>/<schemaVersion>
const didIndySchemaIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/SCHEMA/(?<schemaName>.+)/(?<schemaVersion>[0-9.]+)$`
)
const didIndySchemaIdRegex = new RegExp(`^${didIndyAnonCredsBase.source}/SCHEMA/(.+)/([0-9.]+)$`)

// <namespaceIdentifier>:2:<schemaName>:<schemaVersion>
const legacyIndySchemaIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):2:(?<schemaName>.+):(?<schemaVersion>[0-9.]+)$/
const legacyIndySchemaIdRegex = /^([a-zA-Z0-9]{21,22}):2:(.+):([0-9.]+)$/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/CLAIM_DEF/<schemaSeqNo>/<tag>
const didIndyCredentialDefinitionIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/CLAIM_DEF/(?<schemaSeqNo>[1-9][0-9]*)/(?<tag>.+)$`
)
const didIndyCredentialDefinitionIdRegex = new RegExp(`^${didIndyAnonCredsBase.source}/CLAIM_DEF/([1-9][0-9]*)/(.+)$`)

// <namespaceIdentifier>:3:CL:<schemaSeqNo>:<tag>
const legacyIndyCredentialDefinitionIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):3:CL:(?<schemaSeqNo>[1-9][0-9]*):(?<tag>.+)$/
const legacyIndyCredentialDefinitionIdRegex = /^([a-zA-Z0-9]{21,22}):3:CL:([1-9][0-9]*):(.+)$/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/REV_REG_DEF/<schemaSeqNo>/<credentialDefinitionTag>/<revocationRegistryTag>
const didIndyRevocationRegistryIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/REV_REG_DEF/(?<schemaSeqNo>[1-9][0-9]*)/(?<credentialDefinitionTag>.+)/(?<revocationRegistryTag>.+)$`
`^${didIndyAnonCredsBase.source}/REV_REG_DEF/([1-9][0-9]*)/(.+)/(.+)$`
)

// <namespaceIdentifier>:4:<schemaSeqNo>:3:CL:<credentialDefinitionTag>:CL_ACCUM:<revocationRegistryTag>
const legacyIndyRevocationRegistryIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):4:[a-zA-Z0-9]{21,22}:3:CL:(?<schemaSeqNo>[1-9][0-9]*):(?<credentialDefinitionTag>.+):CL_ACCUM:(?<revocationRegistryTag>.+)$/
/^([a-zA-Z0-9]{21,22}):4:[a-zA-Z0-9]{21,22}:3:CL:([1-9][0-9]*):(.+):CL_ACCUM:(.+)$/

// combines both legacy and did:indy anoncreds identifiers and also the issuer id
const indySdkAnonCredsRegexes = [
Expand All @@ -58,7 +52,7 @@ const indySdkAnonCredsRegexes = [
]

export const indySdkAnonCredsRegistryIdentifierRegex = new RegExp(
indySdkAnonCredsRegexes.map((r) => r.source.replace(/(\?<[a-zA-Z]+>)?/g, '')).join('|')
indySdkAnonCredsRegexes.map((r) => r.source).join('|')
)

export function getDidIndySchemaId(namespace: string, unqualifiedDid: string, name: string, version: string) {
Expand Down Expand Up @@ -110,12 +104,33 @@ interface ParsedSchemaId {
namespace?: string
}

export function parseSchemaId(schemaId: string) {
const match = schemaId.match(didIndySchemaIdRegex) ?? schemaId.match(legacyIndySchemaIdRegex)

if (!match) throw new Error(`Invalid schema id: ${schemaId}`)

return match.groups as unknown as ParsedSchemaId
export function parseSchemaId(schemaId: string): ParsedSchemaId {
const didIndyMatch = schemaId.match(didIndySchemaIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaName, schemaVersion] = didIndyMatch

return {
did,
namespaceIdentifier,
schemaName,
schemaVersion,
namespace,
}
}

const legacyMatch = schemaId.match(legacyIndySchemaIdRegex)
if (legacyMatch) {
const [, did, schemaName, schemaVersion] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaName,
schemaVersion,
}
}

throw new Error(`Invalid schema id: ${schemaId}`)
}

interface ParsedCredentialDefinitionId {
Expand All @@ -126,14 +141,33 @@ interface ParsedCredentialDefinitionId {
namespace?: string
}

export function parseCredentialDefinitionId(credentialDefinitionId: string) {
const match =
credentialDefinitionId.match(didIndyCredentialDefinitionIdRegex) ??
credentialDefinitionId.match(legacyIndyCredentialDefinitionIdRegex)

if (!match) throw new Error(`Invalid credential definition id: ${credentialDefinitionId}`)

return match.groups as unknown as ParsedCredentialDefinitionId
export function parseCredentialDefinitionId(credentialDefinitionId: string): ParsedCredentialDefinitionId {
const didIndyMatch = credentialDefinitionId.match(didIndyCredentialDefinitionIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaSeqNo, tag] = didIndyMatch

return {
did,
namespaceIdentifier,
schemaSeqNo,
tag,
namespace,
}
}

const legacyMatch = credentialDefinitionId.match(legacyIndyCredentialDefinitionIdRegex)
if (legacyMatch) {
const [, did, schemaSeqNo, tag] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaSeqNo,
tag,
}
}

throw new Error(`Invalid credential definition id: ${credentialDefinitionId}`)
}

interface ParsedRevocationRegistryId {
Expand All @@ -145,12 +179,34 @@ interface ParsedRevocationRegistryId {
namespace?: string
}

export function parseRevocationRegistryId(revocationRegistryId: string) {
const match =
revocationRegistryId.match(didIndyRevocationRegistryIdRegex) ??
revocationRegistryId.match(legacyIndyRevocationRegistryIdRegex)

if (!match) throw new Error(`Invalid revocation registry id: ${revocationRegistryId}`)

return match.groups as unknown as ParsedRevocationRegistryId
export function parseRevocationRegistryId(revocationRegistryId: string): ParsedRevocationRegistryId {
const didIndyMatch = revocationRegistryId.match(didIndyRevocationRegistryIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag] =
didIndyMatch

return {
did,
namespaceIdentifier,
schemaSeqNo,
credentialDefinitionTag,
revocationRegistryTag,
namespace,
}
}

const legacyMatch = revocationRegistryId.match(legacyIndyRevocationRegistryIdRegex)
if (legacyMatch) {
const [, did, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaSeqNo,
credentialDefinitionTag,
revocationRegistryTag,
}
}

throw new Error(`Invalid revocation registry id: ${revocationRegistryId}`)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

describe('identifiers', () => {
describe('indyVdrAnonCredsRegistryIdentifierRegex', () => {
test('matches against a legacy indy did, schema id, credential definition id and revocation registry id', () => {
test('matches against a legacy schema id, credential definition id and revocation registry id', () => {
const did = '7Tqg6BwSSWapxgUDm9KKgg'
const schemaId = 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0'
const credentialDefinitionId = 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID'
Expand Down
128 changes: 92 additions & 36 deletions packages/indy-vdr/src/anoncreds/utils/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,28 @@
import { DID_INDY_REGEX } from '../../utils/did'

const didIndyAnonCredsBase =
/(?<did>did:indy:(?<namespace>((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)?)):(?<namespaceIdentifier>([1-9A-HJ-NP-Za-km-z]{21,22})))\/anoncreds\/v0/
/(did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)?):([1-9A-HJ-NP-Za-km-z]{21,22}))\/anoncreds\/v0/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/SCHEMA/<schemaName>/<schemaVersion>
const didIndySchemaIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/SCHEMA/(?<schemaName>.+)/(?<schemaVersion>[0-9.]+)$`
)
const didIndySchemaIdRegex = new RegExp(`^${didIndyAnonCredsBase.source}/SCHEMA/(.+)/([0-9.]+)$`)

// <namespaceIdentifier>:2:<schemaName>:<schemaVersion>
const legacyIndySchemaIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):2:(?<schemaName>.+):(?<schemaVersion>[0-9.]+)$/
const legacyIndySchemaIdRegex = /^([a-zA-Z0-9]{21,22}):2:(.+):([0-9.]+)$/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/CLAIM_DEF/<schemaSeqNo>/<tag>
const didIndyCredentialDefinitionIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/CLAIM_DEF/(?<schemaSeqNo>[1-9][0-9]*)/(?<tag>.+)$`
)
const didIndyCredentialDefinitionIdRegex = new RegExp(`^${didIndyAnonCredsBase.source}/CLAIM_DEF/([1-9][0-9]*)/(.+)$`)

// <namespaceIdentifier>:3:CL:<schemaSeqNo>:<tag>
const legacyIndyCredentialDefinitionIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):3:CL:(?<schemaSeqNo>[1-9][0-9]*):(?<tag>.+)$/
const legacyIndyCredentialDefinitionIdRegex = /^([a-zA-Z0-9]{21,22}):3:CL:([1-9][0-9]*):(.+)$/

// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/REV_REG_DEF/<schemaSeqNo>/<credentialDefinitionTag>/<revocationRegistryTag>
const didIndyRevocationRegistryIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/REV_REG_DEF/(?<schemaSeqNo>[1-9][0-9]*)/(?<credentialDefinitionTag>.+)/(?<revocationRegistryTag>.+)$`
`^${didIndyAnonCredsBase.source}/REV_REG_DEF/([1-9][0-9]*)/(.+)/(.+)$`
)

// <namespaceIdentifier>:4:<schemaSeqNo>:3:CL:<credentialDefinitionTag>:CL_ACCUM:<revocationRegistryTag>
const legacyIndyRevocationRegistryIdRegex =
/^(?<did>(?<namespaceIdentifier>[a-zA-Z0-9]{21,22})):4:[a-zA-Z0-9]{21,22}:3:CL:(?<schemaSeqNo>[1-9][0-9]*):(?<credentialDefinitionTag>.+):CL_ACCUM:(?<revocationRegistryTag>.+)$/
/^([a-zA-Z0-9]{21,22}):4:[a-zA-Z0-9]{21,22}:3:CL:([1-9][0-9]*):(.+):CL_ACCUM:(.+)$/

// combines both legacy and did:indy anoncreds identifiers and also the issuer id
const indyVdrAnonCredsRegexes = [
Expand All @@ -58,7 +52,7 @@ const indyVdrAnonCredsRegexes = [
]

export const indyVdrAnonCredsRegistryIdentifierRegex = new RegExp(
indyVdrAnonCredsRegexes.map((r) => r.source.replace(/(\?<[a-zA-Z]+>)?/g, '')).join('|')
indyVdrAnonCredsRegexes.map((r) => r.source).join('|')
)

export function getDidIndySchemaId(namespace: string, unqualifiedDid: string, name: string, version: string) {
Expand Down Expand Up @@ -110,12 +104,33 @@ interface ParsedSchemaId {
namespace?: string
}

export function parseSchemaId(schemaId: string) {
const match = schemaId.match(didIndySchemaIdRegex) ?? schemaId.match(legacyIndySchemaIdRegex)

if (!match) throw new Error(`Invalid schema id: ${schemaId}`)

return match.groups as unknown as ParsedSchemaId
export function parseSchemaId(schemaId: string): ParsedSchemaId {
const didIndyMatch = schemaId.match(didIndySchemaIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaName, schemaVersion] = didIndyMatch

return {
did,
namespaceIdentifier,
schemaName,
schemaVersion,
namespace,
}
}

const legacyMatch = schemaId.match(legacyIndySchemaIdRegex)
if (legacyMatch) {
const [, did, schemaName, schemaVersion] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaName,
schemaVersion,
}
}

throw new Error(`Invalid schema id: ${schemaId}`)
}

interface ParsedCredentialDefinitionId {
Expand All @@ -126,14 +141,33 @@ interface ParsedCredentialDefinitionId {
namespace?: string
}

export function parseCredentialDefinitionId(credentialDefinitionId: string) {
const match =
credentialDefinitionId.match(didIndyCredentialDefinitionIdRegex) ??
credentialDefinitionId.match(legacyIndyCredentialDefinitionIdRegex)

if (!match) throw new Error(`Invalid credential definition id: ${credentialDefinitionId}`)

return match.groups as unknown as ParsedCredentialDefinitionId
export function parseCredentialDefinitionId(credentialDefinitionId: string): ParsedCredentialDefinitionId {
const didIndyMatch = credentialDefinitionId.match(didIndyCredentialDefinitionIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaSeqNo, tag] = didIndyMatch

return {
did,
namespaceIdentifier,
schemaSeqNo,
tag,
namespace,
}
}

const legacyMatch = credentialDefinitionId.match(legacyIndyCredentialDefinitionIdRegex)
if (legacyMatch) {
const [, did, schemaSeqNo, tag] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaSeqNo,
tag,
}
}

throw new Error(`Invalid credential definition id: ${credentialDefinitionId}`)
}

interface ParsedRevocationRegistryId {
Expand All @@ -145,12 +179,34 @@ interface ParsedRevocationRegistryId {
namespace?: string
}

export function parseRevocationRegistryId(revocationRegistryId: string) {
const match =
revocationRegistryId.match(didIndyRevocationRegistryIdRegex) ??
revocationRegistryId.match(legacyIndyRevocationRegistryIdRegex)

if (!match) throw new Error(`Invalid revocation registry id: ${revocationRegistryId}`)

return match.groups as unknown as ParsedRevocationRegistryId
export function parseRevocationRegistryId(revocationRegistryId: string): ParsedRevocationRegistryId {
const didIndyMatch = revocationRegistryId.match(didIndyRevocationRegistryIdRegex)
if (didIndyMatch) {
const [, did, namespace, namespaceIdentifier, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag] =
didIndyMatch

return {
did,
namespaceIdentifier,
schemaSeqNo,
credentialDefinitionTag,
revocationRegistryTag,
namespace,
}
}

const legacyMatch = revocationRegistryId.match(legacyIndyRevocationRegistryIdRegex)
if (legacyMatch) {
const [, did, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag] = legacyMatch

return {
did,
namespaceIdentifier: did,
schemaSeqNo,
credentialDefinitionTag,
revocationRegistryTag,
}
}

throw new Error(`Invalid revocation registry id: ${revocationRegistryId}`)
}

0 comments on commit a4204ef

Please sign in to comment.