Skip to content

Commit c5b039a

Browse files
authored
feat: enforce max digest length (#360)
Adds an option to enforce a maximum digest length for identity hashes.
1 parent 2e79f32 commit c5b039a

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

packages/blockstore-core/src/identity.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,32 @@ import type { CID } from 'multiformats/cid'
77
// https://github.com/multiformats/multicodec/blob/d06fc6194710e8909bac64273c43f16b56ca4c34/table.csv#L2
88
const IDENTITY_CODEC = 0x00
99

10+
class IdentityDigestTooLongError extends Error {
11+
static name = 'IdentityDigestTooLongError'
12+
name = 'IdentityDigestTooLongError'
13+
}
14+
15+
export interface IdentityBlockstoreInit {
16+
maxDigestLength?: number
17+
}
18+
1019
export class IdentityBlockstore extends BaseBlockstore {
1120
private readonly child?: Blockstore
21+
private readonly maxDigestLength?: number
1222

13-
constructor (child?: Blockstore) {
23+
constructor (child?: Blockstore, init?: IdentityBlockstoreInit) {
1424
super()
1525

1626
this.child = child
27+
this.maxDigestLength = init?.maxDigestLength
1728
}
1829

1930
put (key: CID, block: Uint8Array | AwaitIterable<Uint8Array>, options?: AbortOptions): Await<CID> {
2031
if (key.multihash.code === IDENTITY_CODEC) {
32+
if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
33+
throw new IdentityDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
34+
}
35+
2136
options?.signal?.throwIfAborted()
2237
return key
2338
}
@@ -32,6 +47,10 @@ export class IdentityBlockstore extends BaseBlockstore {
3247

3348
* get (key: CID, options?: AbortOptions): AwaitGenerator<Uint8Array> {
3449
if (key.multihash.code === IDENTITY_CODEC) {
50+
if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
51+
throw new IdentityDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
52+
}
53+
3554
options?.signal?.throwIfAborted()
3655
yield key.multihash.digest
3756
return
@@ -47,6 +66,10 @@ export class IdentityBlockstore extends BaseBlockstore {
4766

4867
has (key: CID, options?: AbortOptions): Await<boolean> {
4968
if (key.multihash.code === IDENTITY_CODEC) {
69+
if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
70+
throw new IdentityDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
71+
}
72+
5073
options?.signal?.throwIfAborted()
5174
return true
5275
}
@@ -61,6 +84,10 @@ export class IdentityBlockstore extends BaseBlockstore {
6184

6285
delete (key: CID, options?: AbortOptions): Await<void> {
6386
if (key.code === IDENTITY_CODEC) {
87+
if (this.maxDigestLength != null && key.multihash.digest.byteLength > this.maxDigestLength) {
88+
throw new IdentityDigestTooLongError(`Identity digest too long - ${key.multihash.digest.byteLength} > this.maxDigestLength`)
89+
}
90+
6491
options?.signal?.throwIfAborted()
6592
return
6693
}

packages/blockstore-core/test/identity.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,27 @@ describe('identity', () => {
127127
expect(result).to.have.lengthOf(1)
128128
expect(result[0].cid.toString()).to.equal(cid.toString())
129129
})
130+
131+
it('should enforce a maximum digest size', async () => {
132+
blockstore = new IdentityBlockstore(child, {
133+
maxDigestLength: 5
134+
})
135+
136+
const tooLong = Uint8Array.from([0, 1, 2, 3, 4, 5])
137+
const ok = Uint8Array.from([0, 1, 2, 3, 4])
138+
const buf = Uint8Array.from([])
139+
140+
expect(blockstore.get(CID.createV1(raw.code, identity.digest(ok)))).to.be.ok()
141+
expect(blockstore.put(CID.createV1(raw.code, identity.digest(ok)), buf)).to.be.ok()
142+
expect(blockstore.has(CID.createV1(raw.code, identity.digest(ok)))).to.be.ok()
143+
144+
expect(() => all(blockstore.get(CID.createV1(raw.code, identity.digest(tooLong))))).to.throw()
145+
.with.property('name', 'IdentityDigestTooLongError')
146+
147+
expect(() => blockstore.put(CID.createV1(raw.code, identity.digest(tooLong)), buf)).to.throw()
148+
.with.property('name', 'IdentityDigestTooLongError')
149+
150+
expect(() => blockstore.has(CID.createV1(raw.code, identity.digest(tooLong)))).to.throw()
151+
.with.property('name', 'IdentityDigestTooLongError')
152+
})
130153
})

0 commit comments

Comments
 (0)