@uncefact/untp-utils 0.0.1
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/LICENSE +674 -0
- package/README.md +38 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -0
- package/build/multibase-digest/index.d.ts +2 -0
- package/build/multibase-digest/index.js +2 -0
- package/build/multibase-digest/index.js.map +1 -0
- package/build/multibase-digest/multibase-digest.d.ts +99 -0
- package/build/multibase-digest/multibase-digest.js +188 -0
- package/build/multibase-digest/multibase-digest.js.map +1 -0
- package/build/multibase-digest/multibase-digest.test.d.ts +1 -0
- package/build/multibase-digest/multibase-digest.test.js +227 -0
- package/build/multibase-digest/multibase-digest.test.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @uncefact/untp-utils
|
|
2
|
+
|
|
3
|
+
Shared utility primitives for UNTP packages and consumers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @uncefact/untp-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## MultibaseDigest
|
|
12
|
+
|
|
13
|
+
Encode, decode and verify multibase-encoded multihashes.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { MultibaseDigest } from '@uncefact/untp-utils';
|
|
17
|
+
|
|
18
|
+
// Hash some data, wrap as a multihash, encode as a multibase string.
|
|
19
|
+
const digest = await MultibaseDigest.fromData(new TextEncoder().encode('hello'), {
|
|
20
|
+
algorithm: 'sha2-256',
|
|
21
|
+
base: 'base58btc',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
digest.toString(); // e.g. "zQmYwAPJzv5..." (base58btc)
|
|
25
|
+
digest.toString('base64'); // e.g. "mEiBL..." (re-encoded, no rehash)
|
|
26
|
+
|
|
27
|
+
// Parse a multibase string. Algorithm and encoding are read from the string.
|
|
28
|
+
const parsed = MultibaseDigest.fromString(digest.toString());
|
|
29
|
+
parsed.algorithm; // "sha2-256"
|
|
30
|
+
parsed.base; // "base58btc"
|
|
31
|
+
|
|
32
|
+
// Verify against original data.
|
|
33
|
+
await parsed.verify(new TextEncoder().encode('hello')); // true | false
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Supported algorithms: `sha2-256`, `sha2-512`.
|
|
37
|
+
|
|
38
|
+
Supported multibase encodings: `base58btc`, `base64`.
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './multibase-digest/index.js';
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/multibase-digest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash algorithms accepted by {@link MultibaseDigest}. Recovered from the
|
|
3
|
+
* multihash prefix on decode, supplied by the caller on encode.
|
|
4
|
+
*/
|
|
5
|
+
export type HashAlgorithm = 'sha2-256' | 'sha2-512';
|
|
6
|
+
/**
|
|
7
|
+
* Multibase encodings accepted by {@link MultibaseDigest}. Recovered from the
|
|
8
|
+
* single-character prefix on a multibase string (`z` for base58btc, `m` for
|
|
9
|
+
* base64), supplied by the caller on encode.
|
|
10
|
+
*/
|
|
11
|
+
export type MultibaseEncoding = 'base58btc' | 'base64';
|
|
12
|
+
/**
|
|
13
|
+
* Algorithm and base selection for the encode-side {@link MultibaseDigest}
|
|
14
|
+
* constructors ({@link MultibaseDigest.fromData}, {@link MultibaseDigest.fromDigest}).
|
|
15
|
+
* Decode-side construction reads both from the input string and takes no options.
|
|
16
|
+
*/
|
|
17
|
+
export interface MultibaseDigestOptions {
|
|
18
|
+
algorithm: HashAlgorithm;
|
|
19
|
+
base: MultibaseEncoding;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Immutable value object representing a multibase-encoded multihash: a hash
|
|
23
|
+
* digest wrapped with its algorithm code (multihash) and paired with a chosen
|
|
24
|
+
* text encoding (multibase). Multihash and multibase are two separate
|
|
25
|
+
* specifications: multihash self-describes which hash algorithm produced the
|
|
26
|
+
* bytes; multibase self-describes which text encoding was used to render those
|
|
27
|
+
* bytes as a string. Instances are only obtainable through the static
|
|
28
|
+
* constructors, which validate inputs against the allow-lists.
|
|
29
|
+
*
|
|
30
|
+
* Two instances are equal when their underlying multihash bytes match. The
|
|
31
|
+
* chosen `base` is presentational and does not affect identity, so the same
|
|
32
|
+
* digest re-encoded under a different base compares equal.
|
|
33
|
+
*
|
|
34
|
+
* @see https://github.com/multiformats/multihash Multihash specification
|
|
35
|
+
* @see https://github.com/multiformats/multibase Multibase specification
|
|
36
|
+
*/
|
|
37
|
+
export declare class MultibaseDigest {
|
|
38
|
+
/** Hash algorithm used to produce {@link digest}. */
|
|
39
|
+
readonly algorithm: HashAlgorithm;
|
|
40
|
+
/** Multibase encoding used by {@link toString} when no override is supplied. */
|
|
41
|
+
readonly base: MultibaseEncoding;
|
|
42
|
+
/** Raw hash bytes (no multihash prefix). Length matches {@link algorithm}. */
|
|
43
|
+
readonly digest: Uint8Array;
|
|
44
|
+
/** Multihash bytes (varint code + varint length + {@link digest}). */
|
|
45
|
+
readonly multihash: Uint8Array;
|
|
46
|
+
private constructor();
|
|
47
|
+
/**
|
|
48
|
+
* Hashes `data` with the requested algorithm, wraps it as a multihash, and
|
|
49
|
+
* tags it with the requested multibase encoding for serialisation.
|
|
50
|
+
*
|
|
51
|
+
* @throws If `algorithm` or `base` is not in the allow-list.
|
|
52
|
+
*/
|
|
53
|
+
static fromData(data: Uint8Array, opts: MultibaseDigestOptions): Promise<MultibaseDigest>;
|
|
54
|
+
/**
|
|
55
|
+
* Wraps an already-computed raw `digest` (the bytes a hash function produces,
|
|
56
|
+
* no multihash prefix) and tags it with the requested multibase encoding. The
|
|
57
|
+
* caller asserts the algorithm; the byte length must match its expected
|
|
58
|
+
* digest size.
|
|
59
|
+
*
|
|
60
|
+
* @throws If `algorithm` or `base` is not in the allow-list, or if `digest.length`
|
|
61
|
+
* does not match the expected size for `algorithm`.
|
|
62
|
+
*/
|
|
63
|
+
static fromDigest(digest: Uint8Array, opts: MultibaseDigestOptions): MultibaseDigest;
|
|
64
|
+
/**
|
|
65
|
+
* Parses a multibase string into a {@link MultibaseDigest}. The algorithm and
|
|
66
|
+
* multibase encoding are both recovered from the string itself: the leading
|
|
67
|
+
* character names the multibase, and the multihash prefix bytes name the
|
|
68
|
+
* algorithm.
|
|
69
|
+
*
|
|
70
|
+
* Decode and multihash-parse errors are rethrown with `{ cause }` so the
|
|
71
|
+
* underlying multiformats error is preserved for debugging.
|
|
72
|
+
*
|
|
73
|
+
* @throws If `encoded` is empty, the multibase prefix is unknown, the body
|
|
74
|
+
* cannot be decoded, the multihash bytes are malformed, or the multihash
|
|
75
|
+
* algorithm code is not in the allow-list.
|
|
76
|
+
*/
|
|
77
|
+
static fromString(encoded: string): MultibaseDigest;
|
|
78
|
+
/**
|
|
79
|
+
* Returns the multibase-encoded multihash as a string. When called without
|
|
80
|
+
* arguments, uses {@link base}; pass a supported encoding to re-encode without
|
|
81
|
+
* rehashing.
|
|
82
|
+
*
|
|
83
|
+
* @throws If `base` is not in the allow-list.
|
|
84
|
+
*/
|
|
85
|
+
toString(base?: MultibaseEncoding): string;
|
|
86
|
+
/**
|
|
87
|
+
* Returns `true` when `other` has the same algorithm and identical multihash
|
|
88
|
+
* bytes. The base is presentational and does not participate in equality, so
|
|
89
|
+
* the same digest encoded under different bases compares equal.
|
|
90
|
+
*/
|
|
91
|
+
equals(other: MultibaseDigest): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Re-hashes `data` with this digest's own algorithm and compares against the
|
|
94
|
+
* stored digest. Returns `false` only on a genuine digest mismatch; throws if
|
|
95
|
+
* `data` cannot be hashed (e.g. invalid input type). Callers must not wrap
|
|
96
|
+
* this in `.catch(() => false)`, which would mask real failures as mismatches.
|
|
97
|
+
*/
|
|
98
|
+
verify(data: Uint8Array): Promise<boolean>;
|
|
99
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as Digest from 'multiformats/hashes/digest';
|
|
2
|
+
import { sha256, sha512 } from 'multiformats/hashes/sha2';
|
|
3
|
+
import { base58btc } from 'multiformats/bases/base58';
|
|
4
|
+
import { base64 } from 'multiformats/bases/base64';
|
|
5
|
+
const HASHERS = {
|
|
6
|
+
'sha2-256': sha256,
|
|
7
|
+
'sha2-512': sha512,
|
|
8
|
+
};
|
|
9
|
+
const HASH_CODE_TO_ALGORITHM = {
|
|
10
|
+
[sha256.code]: 'sha2-256',
|
|
11
|
+
[sha512.code]: 'sha2-512',
|
|
12
|
+
};
|
|
13
|
+
const DIGEST_LENGTHS = {
|
|
14
|
+
'sha2-256': 32,
|
|
15
|
+
'sha2-512': 64,
|
|
16
|
+
};
|
|
17
|
+
const BASES = {
|
|
18
|
+
base58btc,
|
|
19
|
+
base64,
|
|
20
|
+
};
|
|
21
|
+
const BASE_PREFIX_TO_ENCODING = {
|
|
22
|
+
[base58btc.prefix]: 'base58btc',
|
|
23
|
+
[base64.prefix]: 'base64',
|
|
24
|
+
};
|
|
25
|
+
function bytesEqual(a, b) {
|
|
26
|
+
if (a.length !== b.length)
|
|
27
|
+
return false;
|
|
28
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
29
|
+
if (a[i] !== b[i])
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function errorMessage(err) {
|
|
35
|
+
return err instanceof Error ? err.message : String(err);
|
|
36
|
+
}
|
|
37
|
+
function assertSupportedAlgorithm(algorithm) {
|
|
38
|
+
if (!HASHERS[algorithm]) {
|
|
39
|
+
throw new Error(`Unsupported hash algorithm: "${algorithm}"`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function assertSupportedBase(base) {
|
|
43
|
+
if (!BASES[base]) {
|
|
44
|
+
throw new Error(`Unsupported multibase encoding: "${base}"`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Immutable value object representing a multibase-encoded multihash: a hash
|
|
49
|
+
* digest wrapped with its algorithm code (multihash) and paired with a chosen
|
|
50
|
+
* text encoding (multibase). Multihash and multibase are two separate
|
|
51
|
+
* specifications: multihash self-describes which hash algorithm produced the
|
|
52
|
+
* bytes; multibase self-describes which text encoding was used to render those
|
|
53
|
+
* bytes as a string. Instances are only obtainable through the static
|
|
54
|
+
* constructors, which validate inputs against the allow-lists.
|
|
55
|
+
*
|
|
56
|
+
* Two instances are equal when their underlying multihash bytes match. The
|
|
57
|
+
* chosen `base` is presentational and does not affect identity, so the same
|
|
58
|
+
* digest re-encoded under a different base compares equal.
|
|
59
|
+
*
|
|
60
|
+
* @see https://github.com/multiformats/multihash Multihash specification
|
|
61
|
+
* @see https://github.com/multiformats/multibase Multibase specification
|
|
62
|
+
*/
|
|
63
|
+
export class MultibaseDigest {
|
|
64
|
+
/** Hash algorithm used to produce {@link digest}. */
|
|
65
|
+
algorithm;
|
|
66
|
+
/** Multibase encoding used by {@link toString} when no override is supplied. */
|
|
67
|
+
base;
|
|
68
|
+
/** Raw hash bytes (no multihash prefix). Length matches {@link algorithm}. */
|
|
69
|
+
digest;
|
|
70
|
+
/** Multihash bytes (varint code + varint length + {@link digest}). */
|
|
71
|
+
multihash;
|
|
72
|
+
constructor(algorithm, base, digest, multihash) {
|
|
73
|
+
this.algorithm = algorithm;
|
|
74
|
+
this.base = base;
|
|
75
|
+
this.digest = digest;
|
|
76
|
+
this.multihash = multihash;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Hashes `data` with the requested algorithm, wraps it as a multihash, and
|
|
80
|
+
* tags it with the requested multibase encoding for serialisation.
|
|
81
|
+
*
|
|
82
|
+
* @throws If `algorithm` or `base` is not in the allow-list.
|
|
83
|
+
*/
|
|
84
|
+
static async fromData(data, opts) {
|
|
85
|
+
assertSupportedAlgorithm(opts.algorithm);
|
|
86
|
+
assertSupportedBase(opts.base);
|
|
87
|
+
const hasher = HASHERS[opts.algorithm];
|
|
88
|
+
const mh = await hasher.digest(data);
|
|
89
|
+
return new MultibaseDigest(opts.algorithm, opts.base, mh.digest, mh.bytes);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Wraps an already-computed raw `digest` (the bytes a hash function produces,
|
|
93
|
+
* no multihash prefix) and tags it with the requested multibase encoding. The
|
|
94
|
+
* caller asserts the algorithm; the byte length must match its expected
|
|
95
|
+
* digest size.
|
|
96
|
+
*
|
|
97
|
+
* @throws If `algorithm` or `base` is not in the allow-list, or if `digest.length`
|
|
98
|
+
* does not match the expected size for `algorithm`.
|
|
99
|
+
*/
|
|
100
|
+
static fromDigest(digest, opts) {
|
|
101
|
+
assertSupportedAlgorithm(opts.algorithm);
|
|
102
|
+
assertSupportedBase(opts.base);
|
|
103
|
+
const expectedLength = DIGEST_LENGTHS[opts.algorithm];
|
|
104
|
+
if (digest.length !== expectedLength) {
|
|
105
|
+
throw new Error(`Digest length ${digest.length} does not match "${opts.algorithm}" (expected ${expectedLength})`);
|
|
106
|
+
}
|
|
107
|
+
const hasher = HASHERS[opts.algorithm];
|
|
108
|
+
const mh = Digest.create(hasher.code, digest);
|
|
109
|
+
return new MultibaseDigest(opts.algorithm, opts.base, mh.digest, mh.bytes);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parses a multibase string into a {@link MultibaseDigest}. The algorithm and
|
|
113
|
+
* multibase encoding are both recovered from the string itself: the leading
|
|
114
|
+
* character names the multibase, and the multihash prefix bytes name the
|
|
115
|
+
* algorithm.
|
|
116
|
+
*
|
|
117
|
+
* Decode and multihash-parse errors are rethrown with `{ cause }` so the
|
|
118
|
+
* underlying multiformats error is preserved for debugging.
|
|
119
|
+
*
|
|
120
|
+
* @throws If `encoded` is empty, the multibase prefix is unknown, the body
|
|
121
|
+
* cannot be decoded, the multihash bytes are malformed, or the multihash
|
|
122
|
+
* algorithm code is not in the allow-list.
|
|
123
|
+
*/
|
|
124
|
+
static fromString(encoded) {
|
|
125
|
+
if (typeof encoded !== 'string' || encoded.length === 0) {
|
|
126
|
+
throw new Error('Multibase string must be a non-empty string');
|
|
127
|
+
}
|
|
128
|
+
const prefix = encoded[0];
|
|
129
|
+
const base = BASE_PREFIX_TO_ENCODING[prefix];
|
|
130
|
+
if (!base) {
|
|
131
|
+
throw new Error(`Unsupported multibase prefix: "${prefix}"`);
|
|
132
|
+
}
|
|
133
|
+
const codec = BASES[base];
|
|
134
|
+
let mhBytes;
|
|
135
|
+
try {
|
|
136
|
+
mhBytes = codec.decoder.decode(encoded);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
throw new Error(`Failed to decode multibase string: ${errorMessage(err)}`, { cause: err });
|
|
140
|
+
}
|
|
141
|
+
let mh;
|
|
142
|
+
try {
|
|
143
|
+
mh = Digest.decode(mhBytes);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
throw new Error(`Failed to parse multihash: ${errorMessage(err)}`, { cause: err });
|
|
147
|
+
}
|
|
148
|
+
const algorithm = HASH_CODE_TO_ALGORITHM[mh.code];
|
|
149
|
+
if (!algorithm) {
|
|
150
|
+
throw new Error(`Unsupported multihash algorithm code: 0x${mh.code.toString(16)}`);
|
|
151
|
+
}
|
|
152
|
+
return new MultibaseDigest(algorithm, base, mh.digest, mh.bytes);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Returns the multibase-encoded multihash as a string. When called without
|
|
156
|
+
* arguments, uses {@link base}; pass a supported encoding to re-encode without
|
|
157
|
+
* rehashing.
|
|
158
|
+
*
|
|
159
|
+
* @throws If `base` is not in the allow-list.
|
|
160
|
+
*/
|
|
161
|
+
toString(base) {
|
|
162
|
+
const target = base ?? this.base;
|
|
163
|
+
assertSupportedBase(target);
|
|
164
|
+
return BASES[target].encoder.encode(this.multihash);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns `true` when `other` has the same algorithm and identical multihash
|
|
168
|
+
* bytes. The base is presentational and does not participate in equality, so
|
|
169
|
+
* the same digest encoded under different bases compares equal.
|
|
170
|
+
*/
|
|
171
|
+
equals(other) {
|
|
172
|
+
return this.algorithm === other.algorithm && bytesEqual(this.multihash, other.multihash);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Re-hashes `data` with this digest's own algorithm and compares against the
|
|
176
|
+
* stored digest. Returns `false` only on a genuine digest mismatch; throws if
|
|
177
|
+
* `data` cannot be hashed (e.g. invalid input type). Callers must not wrap
|
|
178
|
+
* this in `.catch(() => false)`, which would mask real failures as mismatches.
|
|
179
|
+
*/
|
|
180
|
+
async verify(data) {
|
|
181
|
+
const recomputed = await MultibaseDigest.fromData(data, {
|
|
182
|
+
algorithm: this.algorithm,
|
|
183
|
+
base: this.base,
|
|
184
|
+
});
|
|
185
|
+
return this.equals(recomputed);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=multibase-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multibase-digest.js","sourceRoot":"","sources":["../../src/multibase-digest/multibase-digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { base58btc } from 'multiformats/bases/base58';
|
|
2
|
+
import { MultibaseDigest } from './multibase-digest.js';
|
|
3
|
+
const encoder = new TextEncoder();
|
|
4
|
+
const helloBytes = encoder.encode('hello');
|
|
5
|
+
const worldBytes = encoder.encode('world');
|
|
6
|
+
const SHA256_HELLO_HEX = '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824';
|
|
7
|
+
const SHA256_EMPTY_HEX = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
|
|
8
|
+
function toHex(bytes) {
|
|
9
|
+
return Array.from(bytes)
|
|
10
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
11
|
+
.join('');
|
|
12
|
+
}
|
|
13
|
+
describe('MultibaseDigest', () => {
|
|
14
|
+
describe('fromData', () => {
|
|
15
|
+
it('produces the expected SHA-256 digest of "hello"', async () => {
|
|
16
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
17
|
+
algorithm: 'sha2-256',
|
|
18
|
+
base: 'base58btc',
|
|
19
|
+
});
|
|
20
|
+
expect(digest.algorithm).toBe('sha2-256');
|
|
21
|
+
expect(digest.base).toBe('base58btc');
|
|
22
|
+
expect(digest.digest).toHaveLength(32);
|
|
23
|
+
expect(toHex(digest.digest)).toBe(SHA256_HELLO_HEX);
|
|
24
|
+
});
|
|
25
|
+
it('produces the expected SHA-256 digest of empty input', async () => {
|
|
26
|
+
const digest = await MultibaseDigest.fromData(new Uint8Array(0), {
|
|
27
|
+
algorithm: 'sha2-256',
|
|
28
|
+
base: 'base58btc',
|
|
29
|
+
});
|
|
30
|
+
expect(toHex(digest.digest)).toBe(SHA256_EMPTY_HEX);
|
|
31
|
+
});
|
|
32
|
+
it('encodes as base58btc with a leading "z"', async () => {
|
|
33
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
34
|
+
algorithm: 'sha2-256',
|
|
35
|
+
base: 'base58btc',
|
|
36
|
+
});
|
|
37
|
+
expect(digest.toString().startsWith('z')).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('encodes as base64 with a leading "m"', async () => {
|
|
40
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
41
|
+
algorithm: 'sha2-256',
|
|
42
|
+
base: 'base64',
|
|
43
|
+
});
|
|
44
|
+
expect(digest.toString().startsWith('m')).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
it('produces sha2-512 digests of length 64', async () => {
|
|
47
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
48
|
+
algorithm: 'sha2-512',
|
|
49
|
+
base: 'base58btc',
|
|
50
|
+
});
|
|
51
|
+
expect(digest.algorithm).toBe('sha2-512');
|
|
52
|
+
expect(digest.digest).toHaveLength(64);
|
|
53
|
+
});
|
|
54
|
+
it('rejects unsupported algorithms', async () => {
|
|
55
|
+
await expect(MultibaseDigest.fromData(helloBytes, {
|
|
56
|
+
algorithm: 'md5',
|
|
57
|
+
base: 'base58btc',
|
|
58
|
+
})).rejects.toThrow('Unsupported hash algorithm');
|
|
59
|
+
});
|
|
60
|
+
it('rejects unsupported bases', async () => {
|
|
61
|
+
await expect(MultibaseDigest.fromData(helloBytes, {
|
|
62
|
+
algorithm: 'sha2-256',
|
|
63
|
+
base: 'base16',
|
|
64
|
+
})).rejects.toThrow('Unsupported multibase encoding');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('fromDigest', () => {
|
|
68
|
+
it('wraps a precomputed digest without rehashing', async () => {
|
|
69
|
+
const hashed = await MultibaseDigest.fromData(helloBytes, {
|
|
70
|
+
algorithm: 'sha2-256',
|
|
71
|
+
base: 'base58btc',
|
|
72
|
+
});
|
|
73
|
+
const wrapped = MultibaseDigest.fromDigest(hashed.digest, {
|
|
74
|
+
algorithm: 'sha2-256',
|
|
75
|
+
base: 'base58btc',
|
|
76
|
+
});
|
|
77
|
+
expect(wrapped.toString()).toBe(hashed.toString());
|
|
78
|
+
expect(wrapped.equals(hashed)).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
it('rejects unsupported algorithms', () => {
|
|
81
|
+
expect(() => MultibaseDigest.fromDigest(new Uint8Array(32), {
|
|
82
|
+
algorithm: 'md5',
|
|
83
|
+
base: 'base58btc',
|
|
84
|
+
})).toThrow('Unsupported hash algorithm');
|
|
85
|
+
});
|
|
86
|
+
it('rejects unsupported bases', () => {
|
|
87
|
+
expect(() => MultibaseDigest.fromDigest(new Uint8Array(32), {
|
|
88
|
+
algorithm: 'sha2-256',
|
|
89
|
+
base: 'base16',
|
|
90
|
+
})).toThrow('Unsupported multibase encoding');
|
|
91
|
+
});
|
|
92
|
+
it('rejects a digest whose length does not match the algorithm', () => {
|
|
93
|
+
// sha2-256 expects 32 bytes; a 16-byte digest is invalid.
|
|
94
|
+
expect(() => MultibaseDigest.fromDigest(new Uint8Array(16), {
|
|
95
|
+
algorithm: 'sha2-256',
|
|
96
|
+
base: 'base58btc',
|
|
97
|
+
})).toThrow('Digest length 16 does not match "sha2-256" (expected 32)');
|
|
98
|
+
// sha2-512 expects 64 bytes; a 32-byte digest is invalid.
|
|
99
|
+
expect(() => MultibaseDigest.fromDigest(new Uint8Array(32), {
|
|
100
|
+
algorithm: 'sha2-512',
|
|
101
|
+
base: 'base58btc',
|
|
102
|
+
})).toThrow('Digest length 32 does not match "sha2-512" (expected 64)');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('fromString', () => {
|
|
106
|
+
const supportedBases = ['base58btc', 'base64'];
|
|
107
|
+
const algorithms = ['sha2-256', 'sha2-512'];
|
|
108
|
+
it.each(supportedBases.flatMap((b) => algorithms.map((a) => [a, b])))('round-trips %s through %s', async (algorithm, base) => {
|
|
109
|
+
const original = await MultibaseDigest.fromData(helloBytes, { algorithm, base });
|
|
110
|
+
const encoded = original.toString();
|
|
111
|
+
const parsed = MultibaseDigest.fromString(encoded);
|
|
112
|
+
expect(parsed.algorithm).toBe(algorithm);
|
|
113
|
+
expect(parsed.base).toBe(base);
|
|
114
|
+
expect(parsed.equals(original)).toBe(true);
|
|
115
|
+
expect(parsed.toString()).toBe(encoded);
|
|
116
|
+
});
|
|
117
|
+
it('throws on an empty string', () => {
|
|
118
|
+
expect(() => MultibaseDigest.fromString('')).toThrow('non-empty');
|
|
119
|
+
});
|
|
120
|
+
it('throws on an unknown multibase prefix', () => {
|
|
121
|
+
// 'f' is the base16 prefix, which is not in our allow-list.
|
|
122
|
+
expect(() => MultibaseDigest.fromString('f1220')).toThrow('Unsupported multibase prefix');
|
|
123
|
+
});
|
|
124
|
+
it('throws with a decode error when the base58btc body contains non-alphabet characters', () => {
|
|
125
|
+
// 'z' selects base58btc; '0', 'O', 'I', 'l' are explicitly outside its alphabet.
|
|
126
|
+
expect(() => MultibaseDigest.fromString('z0OIl')).toThrow('Failed to decode multibase string');
|
|
127
|
+
});
|
|
128
|
+
it('throws on an unsupported multihash algorithm code', () => {
|
|
129
|
+
// sha1 = code 0x11, digest length 20. We don't support sha1.
|
|
130
|
+
const sha1Like = new Uint8Array(22);
|
|
131
|
+
sha1Like[0] = 0x11;
|
|
132
|
+
sha1Like[1] = 0x14;
|
|
133
|
+
const encoded = base58btc.encoder.encode(sha1Like);
|
|
134
|
+
expect(() => MultibaseDigest.fromString(encoded)).toThrow('Unsupported multihash algorithm code');
|
|
135
|
+
});
|
|
136
|
+
it('throws on malformed multihash bytes', () => {
|
|
137
|
+
// Claims sha2-256 (code 0x12) with 32-byte digest length (0x20) but has no data bytes.
|
|
138
|
+
const truncated = new Uint8Array([0x12, 0x20]);
|
|
139
|
+
const encoded = base58btc.encoder.encode(truncated);
|
|
140
|
+
expect(() => MultibaseDigest.fromString(encoded)).toThrow();
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('toString', () => {
|
|
144
|
+
it('re-encodes in a different base without rehashing', async () => {
|
|
145
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
146
|
+
algorithm: 'sha2-256',
|
|
147
|
+
base: 'base64',
|
|
148
|
+
});
|
|
149
|
+
const b58 = digest.toString('base58btc');
|
|
150
|
+
expect(b58.startsWith('z')).toBe(true);
|
|
151
|
+
const reparsed = MultibaseDigest.fromString(b58);
|
|
152
|
+
expect(reparsed.equals(digest)).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
it('rejects unsupported base requests', async () => {
|
|
155
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
156
|
+
algorithm: 'sha2-256',
|
|
157
|
+
base: 'base58btc',
|
|
158
|
+
});
|
|
159
|
+
expect(() => digest.toString('base16')).toThrow('Unsupported multibase encoding');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('equals', () => {
|
|
163
|
+
it('treats the same digest encoded in different bases as equal', async () => {
|
|
164
|
+
const a = await MultibaseDigest.fromData(helloBytes, {
|
|
165
|
+
algorithm: 'sha2-256',
|
|
166
|
+
base: 'base64',
|
|
167
|
+
});
|
|
168
|
+
const b = MultibaseDigest.fromString(a.toString('base58btc'));
|
|
169
|
+
expect(a.equals(b)).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
it('returns false for different data', async () => {
|
|
172
|
+
const a = await MultibaseDigest.fromData(helloBytes, {
|
|
173
|
+
algorithm: 'sha2-256',
|
|
174
|
+
base: 'base58btc',
|
|
175
|
+
});
|
|
176
|
+
const b = await MultibaseDigest.fromData(worldBytes, {
|
|
177
|
+
algorithm: 'sha2-256',
|
|
178
|
+
base: 'base58btc',
|
|
179
|
+
});
|
|
180
|
+
expect(a.equals(b)).toBe(false);
|
|
181
|
+
});
|
|
182
|
+
it('returns false for a single-byte difference at the same length', () => {
|
|
183
|
+
const base = new Uint8Array(32);
|
|
184
|
+
const variant = new Uint8Array(32);
|
|
185
|
+
variant[7] = 0x01;
|
|
186
|
+
const a = MultibaseDigest.fromDigest(base, { algorithm: 'sha2-256', base: 'base58btc' });
|
|
187
|
+
const b = MultibaseDigest.fromDigest(variant, { algorithm: 'sha2-256', base: 'base58btc' });
|
|
188
|
+
expect(a.equals(b)).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
it('returns false for different algorithms over the same data', async () => {
|
|
191
|
+
const a = await MultibaseDigest.fromData(helloBytes, {
|
|
192
|
+
algorithm: 'sha2-256',
|
|
193
|
+
base: 'base58btc',
|
|
194
|
+
});
|
|
195
|
+
const b = await MultibaseDigest.fromData(helloBytes, {
|
|
196
|
+
algorithm: 'sha2-512',
|
|
197
|
+
base: 'base58btc',
|
|
198
|
+
});
|
|
199
|
+
expect(a.equals(b)).toBe(false);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe('verify', () => {
|
|
203
|
+
it('returns true for matching data', async () => {
|
|
204
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
205
|
+
algorithm: 'sha2-256',
|
|
206
|
+
base: 'base58btc',
|
|
207
|
+
});
|
|
208
|
+
expect(await digest.verify(helloBytes)).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
it('returns false for non-matching data', async () => {
|
|
211
|
+
const digest = await MultibaseDigest.fromData(helloBytes, {
|
|
212
|
+
algorithm: 'sha2-256',
|
|
213
|
+
base: 'base58btc',
|
|
214
|
+
});
|
|
215
|
+
expect(await digest.verify(worldBytes)).toBe(false);
|
|
216
|
+
});
|
|
217
|
+
it("uses the digest's own algorithm, not the caller's", async () => {
|
|
218
|
+
const digest512 = await MultibaseDigest.fromData(helloBytes, {
|
|
219
|
+
algorithm: 'sha2-512',
|
|
220
|
+
base: 'base58btc',
|
|
221
|
+
});
|
|
222
|
+
// verify() must re-hash with sha2-512, not assume sha2-256.
|
|
223
|
+
expect(await digest512.verify(helloBytes)).toBe(true);
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=multibase-digest.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multibase-digest.test.js","sourceRoot":"","sources":["../../src/multibase-digest/multibase-digest.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@uncefact/untp-utils",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Shared utility primitives for UNTP packages and consumers.",
|
|
5
|
+
"main": "./build/index.js",
|
|
6
|
+
"types": "./build/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./build/index.d.ts",
|
|
10
|
+
"default": "./build/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./multibase-digest": {
|
|
13
|
+
"types": "./build/multibase-digest/index.d.ts",
|
|
14
|
+
"default": "./build/multibase-digest/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"typesVersions": {
|
|
18
|
+
"*": {
|
|
19
|
+
"multibase-digest": [
|
|
20
|
+
"./build/multibase-digest/index.d.ts"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"build"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"untp",
|
|
30
|
+
"multibase",
|
|
31
|
+
"multihash",
|
|
32
|
+
"digest"
|
|
33
|
+
],
|
|
34
|
+
"author": "",
|
|
35
|
+
"license": "ISC",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"multiformats": "^13.3.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/jest": "29.5.11",
|
|
41
|
+
"cross-env": "^7.0.3",
|
|
42
|
+
"jest": "29.7.0",
|
|
43
|
+
"ts-jest": "29.1.1",
|
|
44
|
+
"typescript": "^5.3.3"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc --build --clean && tsc",
|
|
48
|
+
"watch": "tsc -b --watch",
|
|
49
|
+
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
50
|
+
"test:coverage": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage"
|
|
51
|
+
}
|
|
52
|
+
}
|