@solidus-network/auth 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -18
- package/demo/unlinkability-demo.mjs +159 -0
- package/package.json +39 -7
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# @solidus-network/auth
|
|
2
2
|
|
|
3
|
-
DID-based authentication
|
|
3
|
+
DID-based authentication and DID-less BBS+ selective-disclosure verification for the [Solidus Network](https://solidus.network) protocol.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Two independent surfaces, one package:
|
|
6
|
+
|
|
7
|
+
- **DID-bound auth** — Ed25519 challenge / signature / verification, for backends that authenticate the holder of a known DID without operating a user database.
|
|
8
|
+
- **DID-less presentations** — the relying-party surface for Solidus's unlinkable credential presentations: verify "a valid KYC credential from this issuer, disclosing exactly these claims" without ever learning who presented it.
|
|
6
9
|
|
|
7
10
|
## Install
|
|
8
11
|
|
|
@@ -12,39 +15,146 @@ npm install @solidus-network/auth
|
|
|
12
15
|
pnpm add @solidus-network/auth
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
## Quick start
|
|
18
|
+
## Quick start — DID-bound challenge
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { createChallenge, verifyPresentation } from '@solidus-network/auth'
|
|
22
|
+
|
|
23
|
+
// Server: issue a challenge for a known DID (TTL in seconds, default 300)
|
|
24
|
+
const challenge = createChallenge('did:solidus:testnet:abc123', 300)
|
|
25
|
+
|
|
26
|
+
// Client answers with a W3C Verifiable Presentation whose proof signs
|
|
27
|
+
// the challenge nonce; the server verifies:
|
|
28
|
+
const result = await verifyPresentation(challenge, presentation, getPublicKey)
|
|
29
|
+
|
|
30
|
+
if (result.valid) {
|
|
31
|
+
// authenticated — result.checks itemizes expiry/holder/nonce/signature
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## DID-less selective-disclosure presentations (BBS+)
|
|
36
|
+
|
|
37
|
+
The verifier surface for Solidus's **unlinkable** presentations: a wallet
|
|
38
|
+
proves it holds a valid KYC credential from a trusted issuer and disclosed
|
|
39
|
+
exactly the claims you asked for — without revealing the holder's DID, a
|
|
40
|
+
credential ID, or anything two relying parties could later compare to
|
|
41
|
+
discover they served the same person.
|
|
42
|
+
|
|
43
|
+
### How it works
|
|
44
|
+
|
|
45
|
+
- The issuer signs an 8-message KYC vector with BBS+ under a **header that
|
|
46
|
+
is constant per (issuer, credential-type, epoch)** — no per-credential
|
|
47
|
+
entropy, so the header places a holder in a cohort, never identifies one.
|
|
48
|
+
- The issuer publishes its per-epoch public keys at
|
|
49
|
+
`https://verify.solidus.network/.well-known/solidus-bbs-issuer.json`.
|
|
50
|
+
Credentials live as long as their epoch (+ a grace window); revocation is
|
|
51
|
+
bounded-lifetime — a lapsed epoch's key disappears from the document and
|
|
52
|
+
every verifier fails closed.
|
|
53
|
+
- The wallet answers a verifier's challenge with a **randomized proof**
|
|
54
|
+
bound to that verifier's domain + nonce. Replaying it under any other
|
|
55
|
+
challenge fails cryptographically.
|
|
56
|
+
- The envelope (`BbsSelectiveDisclosurePresentation`) has **no `holder`
|
|
57
|
+
field by construction**, and the verifier rejects any envelope that
|
|
58
|
+
discloses `subject_did`, `verification_id`, or `document_hash` even when
|
|
59
|
+
the proof itself is valid.
|
|
60
|
+
|
|
61
|
+
### Verifier quickstart (a complete relying party)
|
|
16
62
|
|
|
17
63
|
```ts
|
|
18
|
-
import {
|
|
64
|
+
import {
|
|
65
|
+
createBbsChallenge,
|
|
66
|
+
verifyBbsPresentation,
|
|
67
|
+
createIssuerKeyResolver,
|
|
68
|
+
parseBbsPresentation,
|
|
69
|
+
decodeDisclosedKycFields,
|
|
70
|
+
} from '@solidus-network/auth'
|
|
19
71
|
|
|
20
|
-
//
|
|
21
|
-
const challenge =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
72
|
+
// 1. Issue a DID-less challenge (store it; enforce single use).
|
|
73
|
+
const challenge = createBbsChallenge({
|
|
74
|
+
domain: 'your-app.example.com', // your authenticated origin
|
|
75
|
+
credentialType: 'kyc',
|
|
76
|
+
requiredIndices: [4, 5], // kyc_level, country
|
|
25
77
|
})
|
|
26
78
|
|
|
27
|
-
//
|
|
79
|
+
// 2. The wallet answers with a serialized envelope.
|
|
80
|
+
const presentation = parseBbsPresentation(envelopeJson)
|
|
28
81
|
|
|
29
|
-
//
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
82
|
+
// 3. Verify — stateless, against the issuer's published epoch keys.
|
|
83
|
+
const resolveIssuerKey = createIssuerKeyResolver({
|
|
84
|
+
issuerBaseUrl: 'https://verify.solidus.network',
|
|
85
|
+
})
|
|
86
|
+
const result = await verifyBbsPresentation(challenge, presentation, {
|
|
87
|
+
issuerDid: 'did:solidus:testnet:2FDp7gH5qyb66jjsXAbFQYwLygqQ',
|
|
88
|
+
resolveIssuerKey,
|
|
89
|
+
used: false, // your storage-side single-use flag
|
|
34
90
|
})
|
|
35
91
|
|
|
36
|
-
if (result.
|
|
37
|
-
|
|
92
|
+
if (result.valid) {
|
|
93
|
+
const fields = decodeDisclosedKycFields(presentation.disclosed)
|
|
94
|
+
// e.g. { issuer_did: '…', kyc_level: '2', country: 'TR' } — and nothing else
|
|
38
95
|
}
|
|
39
96
|
```
|
|
40
97
|
|
|
98
|
+
The resolver is fail-closed: an unknown or lapsed epoch, an unreachable
|
|
99
|
+
issuer, or a malformed key document all resolve to `null` and the
|
|
100
|
+
presentation is rejected — never accepted on error.
|
|
101
|
+
|
|
102
|
+
### Verify the unlinkability claim yourself
|
|
103
|
+
|
|
104
|
+
Don't take our word for it — the demonstration ships in this package and
|
|
105
|
+
runs in under a minute:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
node node_modules/@solidus-network/auth/demo/unlinkability-demo.mjs
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
It issues one credential, presents it to two relying parties, verifies
|
|
112
|
+
both presentations, then pools everything both RPs received and shows the
|
|
113
|
+
complete correlation surface: cohort-level constants and the disclosed
|
|
114
|
+
claims — no per-holder value in common, randomized proofs sharing no
|
|
115
|
+
bytes, and cross-challenge replay failing.
|
|
116
|
+
|
|
117
|
+
### Re-recognition (pairwise DIDs)
|
|
118
|
+
|
|
119
|
+
When a returning user *wants* to be recognized by one relying party, the
|
|
120
|
+
wallet can attach a **pairwise DID** — deterministically derived from the
|
|
121
|
+
holder's seed *and that verifier's identity*, so the same user shows a
|
|
122
|
+
different, uncorrelatable pairwise DID to every other verifier. See
|
|
123
|
+
`buildPairwiseAttachment` / `buildPairwiseDid`. Two caveats, stated
|
|
124
|
+
plainly: the wallet must derive against the verifier's *authenticated*
|
|
125
|
+
origin (never an ID copied blindly from the challenge), and the pairwise
|
|
126
|
+
signature sits *beside* the credential proof rather than being
|
|
127
|
+
cryptographically bound to the same seed — assurance is "a returning
|
|
128
|
+
controller of this key who also holds a valid credential", which is right
|
|
129
|
+
for convenience and analytics, not for access-control-grade identity.
|
|
130
|
+
|
|
131
|
+
### What this does and does not protect
|
|
132
|
+
|
|
133
|
+
**Protected (cryptographic presentation layer):** two relying parties —
|
|
134
|
+
or the same one twice — cannot link presentations by anything in the
|
|
135
|
+
envelopes: no subject DID, no credential ID, no document hash, randomized
|
|
136
|
+
proofs, cohort-constant headers, challenge-bound replay protection.
|
|
137
|
+
|
|
138
|
+
**NOT protected (out of scope — be honest with your users):** network-level
|
|
139
|
+
correlation (IP address, timing, TLS/device fingerprints, cookies), and
|
|
140
|
+
relying parties pooling out-of-band data they each collected themselves
|
|
141
|
+
(email, phone, payment details). If your application hands every RP the
|
|
142
|
+
user's email address, unlinkable credentials will not make them unlinkable.
|
|
143
|
+
|
|
144
|
+
**Status:** the underlying `@solidus-network/bbs` implementation is
|
|
145
|
+
**testnet-grade and audit-pending** (external audit via NLnet NGI Zero,
|
|
146
|
+
H2 2026 target). `did:solidus` is submitted to the W3C DID method registry
|
|
147
|
+
and under review. This runs on the Solidus testnet — do not represent it
|
|
148
|
+
as audited or production-assured until those complete.
|
|
149
|
+
|
|
41
150
|
## Features
|
|
42
151
|
|
|
43
152
|
- Ed25519 signature verification via [@noble/ed25519](https://www.npmjs.com/package/@noble/ed25519)
|
|
44
153
|
- BLAKE3 hashing for challenge digests via [@noble/hashes](https://www.npmjs.com/package/@noble/hashes)
|
|
45
154
|
- Time-bounded challenges with TTL enforcement
|
|
46
155
|
- Domain-bound challenges (prevents replay across origins)
|
|
47
|
-
-
|
|
156
|
+
- DID-less BBS+ selective-disclosure verification with fail-closed epoch-key resolution
|
|
157
|
+
- A runnable unlinkability demonstration (`demo/unlinkability-demo.mjs`)
|
|
48
158
|
|
|
49
159
|
## License
|
|
50
160
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Solidus unlinkability demonstration — runnable by anyone, from npm alone.
|
|
2
|
+
//
|
|
3
|
+
// npm i @solidus-network/auth @solidus-network/bbs
|
|
4
|
+
// node node_modules/@solidus-network/auth/demo/unlinkability-demo.mjs
|
|
5
|
+
//
|
|
6
|
+
// You play every role: issuer, holder, and two relying parties who later
|
|
7
|
+
// collude. The issuer keypair is generated locally; the FORMAT — header v2,
|
|
8
|
+
// the 8-message KYC vector, the envelope, the presentation-header binding —
|
|
9
|
+
// is exactly what verify.solidus.network issues in production (Part 1
|
|
10
|
+
// fetches its live epoch-key document so you can see that for yourself).
|
|
11
|
+
// Production differs only in whose secret key signs, never in what a
|
|
12
|
+
// relying party receives — so the correlation analysis below transfers.
|
|
13
|
+
//
|
|
14
|
+
// HONESTY BOUNDARY (read before quoting this): this demonstrates
|
|
15
|
+
// unlinkability at the cryptographic presentation layer ONLY. It does NOT
|
|
16
|
+
// defend against network-level correlation (IP address, timing, device
|
|
17
|
+
// fingerprint, cookies) or relying parties pooling out-of-band data they
|
|
18
|
+
// collected themselves (email, phone number). @solidus-network/bbs is
|
|
19
|
+
// testnet-grade; external audit pending (NLnet NGI Zero, H2 2026 target).
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
createBbsChallenge,
|
|
23
|
+
verifyBbsPresentation,
|
|
24
|
+
buildBbsPresentation,
|
|
25
|
+
createIssuerKeyResolver,
|
|
26
|
+
KYC_MESSAGE_FIELDS,
|
|
27
|
+
} from '@solidus-network/auth'
|
|
28
|
+
import {
|
|
29
|
+
BbsSecretKey,
|
|
30
|
+
buildV2Header,
|
|
31
|
+
derivePresentationHeader,
|
|
32
|
+
utf8,
|
|
33
|
+
} from '@solidus-network/bbs'
|
|
34
|
+
|
|
35
|
+
const hex = (b) => Buffer.from(b).toString('hex')
|
|
36
|
+
const line = (s = '') => console.log(s)
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// PART 1 — the production issuer publishes epoch keys at a public URL.
|
|
40
|
+
// Anyone can resolve them; unknown or lapsed epochs fail closed to null.
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
line('== PART 1: production issuer key document (public URL) ==')
|
|
43
|
+
const PROD = 'https://verify.solidus.network'
|
|
44
|
+
try {
|
|
45
|
+
const doc = await (await fetch(`${PROD}/.well-known/solidus-bbs-issuer.json`)).json()
|
|
46
|
+
line(`issuer_did: ${doc.issuer_did}`)
|
|
47
|
+
line(`current epoch: ${doc.current.epoch} (notAfter ${doc.current.notAfter})`)
|
|
48
|
+
const resolve = createIssuerKeyResolver({ issuerBaseUrl: PROD })
|
|
49
|
+
const key = await resolve(doc.current.epoch)
|
|
50
|
+
line(`resolver → epoch ${doc.current.epoch}: ${key ? key.slice(0, 32) + '… (96-byte BLS12-381 G2 key)' : 'null'}`)
|
|
51
|
+
const lapsed = await resolve(9999)
|
|
52
|
+
line(`resolver → epoch 9999 (unknown): ${lapsed === null ? 'null (fail-closed)' : 'UNEXPECTED KEY'}`)
|
|
53
|
+
} catch {
|
|
54
|
+
line('(offline — skipping the live fetch; the local demonstration below is unaffected)')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// PART 2 — one credential, two relying parties.
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
line()
|
|
61
|
+
line('== PART 2: one credential, presented to two relying parties ==')
|
|
62
|
+
const issuerDid = 'did:solidus:testnet:demo-issuer'
|
|
63
|
+
const credentialType = 'kyc'
|
|
64
|
+
const epoch = 2
|
|
65
|
+
const sk = await BbsSecretKey.generate()
|
|
66
|
+
const pk = await sk.publicKey()
|
|
67
|
+
const header = buildV2Header(issuerDid, credentialType, epoch)
|
|
68
|
+
|
|
69
|
+
// The production message vector (order frozen). Demo values only — no PII.
|
|
70
|
+
const messages = [
|
|
71
|
+
utf8('did:solidus:testnet:demoHolderSubjectDid0000'), // 0 subject_did — ALWAYS hidden
|
|
72
|
+
utf8(issuerDid), // 1 issuer_did
|
|
73
|
+
utf8('vrf_demo_0001'), // 2 verification_id — ALWAYS hidden
|
|
74
|
+
utf8('2026-07-01T09:30:00Z'), // 3 verified_at
|
|
75
|
+
utf8('2'), // 4 kyc_level
|
|
76
|
+
utf8('TR'), // 5 country
|
|
77
|
+
utf8('passport'), // 6 document_type
|
|
78
|
+
utf8('deadbeefdeadbeefdeadbeefdeadbeef'), // 7 document_hash — ALWAYS hidden
|
|
79
|
+
]
|
|
80
|
+
const sig = await sk.sign(header, messages)
|
|
81
|
+
line(`issued: 1 credential, 8 messages, header v2 = "${Buffer.from(header).toString()}"`)
|
|
82
|
+
line('(header v2 is issuer/type/epoch-constant — identical for every holder in the cohort)')
|
|
83
|
+
|
|
84
|
+
const resolveLocal = async (e) => (e === epoch ? pk.toHex() : null)
|
|
85
|
+
const rpA = createBbsChallenge({ domain: 'rp-a.example.com', credentialType, requiredIndices: [4, 5] })
|
|
86
|
+
const rpB = createBbsChallenge({ domain: 'rp-b.example.com', credentialType, requiredIndices: [4] })
|
|
87
|
+
|
|
88
|
+
async function present(challenge) {
|
|
89
|
+
const ph = derivePresentationHeader(challenge.domain, Buffer.from(challenge.nonce, 'hex'))
|
|
90
|
+
const disclosedIndices = [1, ...challenge.requiredIndices].sort((x, y) => x - y)
|
|
91
|
+
const proof = await sig.createProof({ pk, header, presentationHeader: ph, messages, disclosedIndices })
|
|
92
|
+
return buildBbsPresentation({
|
|
93
|
+
challengeId: challenge.id,
|
|
94
|
+
epoch,
|
|
95
|
+
proofHex: proof.toHex(),
|
|
96
|
+
totalMessageCount: messages.length,
|
|
97
|
+
disclosed: disclosedIndices.map((i) => ({ index: i, message: hex(messages[i]) })),
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
const presA = await present(rpA)
|
|
101
|
+
const presB = await present(rpB)
|
|
102
|
+
|
|
103
|
+
const opts = () => ({ issuerDid, resolveIssuerKey: resolveLocal, used: false, network: 'testnet' })
|
|
104
|
+
const resA = await verifyBbsPresentation(rpA, presA, opts())
|
|
105
|
+
const resB = await verifyBbsPresentation(rpB, presB, opts())
|
|
106
|
+
line(`RP A verify: valid=${resA.valid}`)
|
|
107
|
+
line(`RP B verify: valid=${resB.valid}`)
|
|
108
|
+
if (!resA.valid || !resB.valid) throw new Error('verification failed — demo aborted')
|
|
109
|
+
|
|
110
|
+
const replay = await verifyBbsPresentation(rpB, { ...presA, challengeId: rpB.id }, opts())
|
|
111
|
+
line(`RP B replaying A's proof under its own challenge: valid=${replay.valid} (must be false)`)
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// PART 3 — the collusion attempt: both RPs pool everything they received.
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
line()
|
|
117
|
+
line('== PART 3: RP A + RP B collude — the complete correlation surface ==')
|
|
118
|
+
const jsonA = JSON.stringify(presA)
|
|
119
|
+
const jsonB = JSON.stringify(presB)
|
|
120
|
+
|
|
121
|
+
for (const [name, needle] of [
|
|
122
|
+
['subject DID', 'demoHolderSubjectDid0000'],
|
|
123
|
+
['verification_id', hex(utf8('vrf_demo_0001'))],
|
|
124
|
+
['document_hash', hex(utf8('deadbeefdeadbeefdeadbeefdeadbeef'))],
|
|
125
|
+
]) {
|
|
126
|
+
const found = jsonA.includes(needle) || jsonB.includes(needle)
|
|
127
|
+
line(`per-holder ${name} present in either envelope: ${found ? 'YES — LINKABLE (FAIL)' : 'no'}`)
|
|
128
|
+
if (found) throw new Error('linkable identifier leaked')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const a = Buffer.from(presA.proof, 'hex')
|
|
132
|
+
const b = Buffer.from(presB.proof, 'hex')
|
|
133
|
+
let equalBytes = 0
|
|
134
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) if (a[i] === b[i]) equalBytes++
|
|
135
|
+
line(`proof bytes equal at the same offset: ${equalBytes}/${Math.min(a.length, b.length)} (random baseline ≈ ${(Math.min(a.length, b.length) / 256).toFixed(1)})`)
|
|
136
|
+
|
|
137
|
+
const presA2 = await present(rpA)
|
|
138
|
+
line(`regenerated proof for the SAME challenge identical to the first: ${presA2.proof === presA.proof ? 'YES (FAIL)' : 'no (randomized)'}`)
|
|
139
|
+
|
|
140
|
+
line('fields present in BOTH envelopes:')
|
|
141
|
+
for (const [k, v] of Object.entries(presA)) {
|
|
142
|
+
if (JSON.stringify(v) === JSON.stringify(presB[k])) line(` ${k} = ${JSON.stringify(v)} ← cohort-constant, shared by every holder of this (issuer, type, epoch)`)
|
|
143
|
+
}
|
|
144
|
+
const inA = Object.fromEntries(presA.disclosed.map((d) => [d.index, d.message]))
|
|
145
|
+
for (const d of presB.disclosed) {
|
|
146
|
+
if (inA[d.index]) line(` disclosed[${d.index}] (${KYC_MESSAGE_FIELDS[d.index]}) = "${Buffer.from(d.message, 'hex')}" ← disclosed by policy to both; a cohort value, not a per-user handle`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
line()
|
|
150
|
+
line('RESULT: both presentations verified; the pooled correlation surface contains only')
|
|
151
|
+
line('cohort-level constants and the claims each RP itself requested. No per-holder')
|
|
152
|
+
line('value appears in both envelopes.')
|
|
153
|
+
line()
|
|
154
|
+
line('HONESTY BOUNDARY — read before quoting this result:')
|
|
155
|
+
line(' This demonstrates unlinkability at the cryptographic PRESENTATION LAYER only.')
|
|
156
|
+
line(' It does NOT defend against network-level correlation (IP address, timing,')
|
|
157
|
+
line(' device fingerprints, cookies) or relying parties pooling out-of-band data')
|
|
158
|
+
line(' they collected themselves (email, phone). @solidus-network/bbs is testnet-grade;')
|
|
159
|
+
line(' external audit pending (NLnet NGI Zero, H2 2026 target).')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidus-network/auth",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "DID-based authentication for the Solidus Network protocol — Ed25519 challenge
|
|
3
|
+
"version": "0.6.2",
|
|
4
|
+
"description": "DID-based authentication and DID-less BBS+ selective-disclosure verification for the Solidus Network protocol — Ed25519 challenge/response, unlinkable presentation envelopes, and the relying-party issuer-key resolver.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -9,22 +9,54 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"import": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./envelope": {
|
|
14
|
+
"import": "./dist/envelope.js",
|
|
15
|
+
"types": "./dist/envelope.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./pairwise": {
|
|
18
|
+
"import": "./dist/pairwise.js",
|
|
19
|
+
"types": "./dist/pairwise.d.ts"
|
|
12
20
|
}
|
|
13
21
|
},
|
|
14
|
-
"files": [
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"demo",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
15
28
|
"dependencies": {
|
|
29
|
+
"@solidus-network/types": "0.6.2",
|
|
30
|
+
"@solidus-network/bbs": "0.6.2",
|
|
16
31
|
"@noble/ed25519": "^2.1.0",
|
|
17
|
-
"@noble/hashes": "^1.5.0"
|
|
32
|
+
"@noble/hashes": "^1.5.0",
|
|
33
|
+
"bs58": "^6.0.0"
|
|
18
34
|
},
|
|
19
|
-
"keywords": [
|
|
35
|
+
"keywords": [
|
|
36
|
+
"solidus",
|
|
37
|
+
"did",
|
|
38
|
+
"authentication",
|
|
39
|
+
"decentralized-identity",
|
|
40
|
+
"ed25519",
|
|
41
|
+
"challenge-response",
|
|
42
|
+
"signature",
|
|
43
|
+
"bbs",
|
|
44
|
+
"selective-disclosure",
|
|
45
|
+
"unlinkability",
|
|
46
|
+
"verifiable-presentation"
|
|
47
|
+
],
|
|
20
48
|
"author": "Solidus Network (https://solidus.network)",
|
|
21
49
|
"license": "Apache-2.0",
|
|
22
50
|
"homepage": "https://solidus.network",
|
|
23
|
-
"bugs": {
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/solidusnetwork/sdk/issues"
|
|
53
|
+
},
|
|
24
54
|
"repository": {
|
|
25
55
|
"type": "git",
|
|
26
56
|
"url": "git+https://github.com/solidusnetwork/sdk.git",
|
|
27
57
|
"directory": "auth"
|
|
28
58
|
},
|
|
29
|
-
"publishConfig": {
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
}
|
|
30
62
|
}
|