technocore-sdk 0.1.0
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/CHANGELOG.md +42 -0
- package/LICENSE +176 -0
- package/README.md +165 -0
- package/SECURITY.md +46 -0
- package/dist/agent/index.d.ts +112 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +225 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/client/index.d.ts +29 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +41 -0
- package/dist/client/index.js.map +1 -0
- package/dist/contributions/index.d.ts +41 -0
- package/dist/contributions/index.d.ts.map +1 -0
- package/dist/contributions/index.js +48 -0
- package/dist/contributions/index.js.map +1 -0
- package/dist/crypto/canonicalize.d.ts +31 -0
- package/dist/crypto/canonicalize.d.ts.map +1 -0
- package/dist/crypto/canonicalize.js +36 -0
- package/dist/crypto/canonicalize.js.map +1 -0
- package/dist/crypto/did.d.ts +39 -0
- package/dist/crypto/did.d.ts.map +1 -0
- package/dist/crypto/did.js +82 -0
- package/dist/crypto/did.js.map +1 -0
- package/dist/crypto/encode.d.ts +34 -0
- package/dist/crypto/encode.d.ts.map +1 -0
- package/dist/crypto/encode.js +98 -0
- package/dist/crypto/encode.js.map +1 -0
- package/dist/crypto/fingerprint.d.ts +43 -0
- package/dist/crypto/fingerprint.d.ts.map +1 -0
- package/dist/crypto/fingerprint.js +61 -0
- package/dist/crypto/fingerprint.js.map +1 -0
- package/dist/crypto/nonce.d.ts +44 -0
- package/dist/crypto/nonce.d.ts.map +1 -0
- package/dist/crypto/nonce.js +69 -0
- package/dist/crypto/nonce.js.map +1 -0
- package/dist/crypto/sign.d.ts +52 -0
- package/dist/crypto/sign.d.ts.map +1 -0
- package/dist/crypto/sign.js +78 -0
- package/dist/crypto/sign.js.map +1 -0
- package/dist/crypto/sweep.d.ts +24 -0
- package/dist/crypto/sweep.d.ts.map +1 -0
- package/dist/crypto/sweep.js +40 -0
- package/dist/crypto/sweep.js.map +1 -0
- package/dist/crypto/verify.d.ts +27 -0
- package/dist/crypto/verify.d.ts.map +1 -0
- package/dist/crypto/verify.js +118 -0
- package/dist/crypto/verify.js.map +1 -0
- package/dist/errors/index.d.ts +86 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +131 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/identity/index.d.ts +100 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +143 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/notes/index.d.ts +108 -0
- package/dist/notes/index.d.ts.map +1 -0
- package/dist/notes/index.js +251 -0
- package/dist/notes/index.js.map +1 -0
- package/dist/rooms/index.d.ts +138 -0
- package/dist/rooms/index.d.ts.map +1 -0
- package/dist/rooms/index.js +325 -0
- package/dist/rooms/index.js.map +1 -0
- package/dist/streaming/index.d.ts +72 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +125 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/transport/http.d.ts +51 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +132 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/types/index.d.ts +148 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +56 -0
- package/dist/types/index.js.map +1 -0
- package/dist/verification/index.d.ts +40 -0
- package/dist/verification/index.d.ts.map +1 -0
- package/dist/verification/index.js +69 -0
- package/dist/verification/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Encoding Utilities
|
|
3
|
+
*
|
|
4
|
+
* Base64url and base58btc encoding for signatures and DIDs.
|
|
5
|
+
* Uses @scure/base for base58btc (audited, zero-dependency).
|
|
6
|
+
*/
|
|
7
|
+
import { base58 } from '@scure/base';
|
|
8
|
+
// ─── Base64url ──────────────────────────────────────────────────────────────
|
|
9
|
+
const B64URL_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
10
|
+
/**
|
|
11
|
+
* Encode bytes to base64url (no padding).
|
|
12
|
+
* This is the canonical encoding — the last character is determined by the encoder,
|
|
13
|
+
* and is the only one the server accepts.
|
|
14
|
+
*/
|
|
15
|
+
export function base64urlEncode(bytes) {
|
|
16
|
+
let result = '';
|
|
17
|
+
const len = bytes.length;
|
|
18
|
+
let i = 0;
|
|
19
|
+
for (; i + 2 < len; i += 3) {
|
|
20
|
+
const b0 = bytes[i];
|
|
21
|
+
const b1 = bytes[i + 1];
|
|
22
|
+
const b2 = bytes[i + 2];
|
|
23
|
+
result += B64URL_CHARS[(b0 >> 2)];
|
|
24
|
+
result += B64URL_CHARS[((b0 & 0x03) << 4) | (b1 >> 4)];
|
|
25
|
+
result += B64URL_CHARS[((b1 & 0x0f) << 2) | (b2 >> 6)];
|
|
26
|
+
result += B64URL_CHARS[b2 & 0x3f];
|
|
27
|
+
}
|
|
28
|
+
// Handle remaining bytes
|
|
29
|
+
if (i < len) {
|
|
30
|
+
const b0 = bytes[i];
|
|
31
|
+
result += B64URL_CHARS[b0 >> 2];
|
|
32
|
+
if (i + 1 < len) {
|
|
33
|
+
const b1 = bytes[i + 1];
|
|
34
|
+
result += B64URL_CHARS[((b0 & 0x03) << 4) | (b1 >> 4)];
|
|
35
|
+
result += B64URL_CHARS[(b1 & 0x0f) << 2];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
result += B64URL_CHARS[(b0 & 0x03) << 4];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Decode base64url string to bytes (no padding expected).
|
|
45
|
+
*/
|
|
46
|
+
export function base64urlDecode(str) {
|
|
47
|
+
// Build reverse lookup
|
|
48
|
+
const lookup = new Uint8Array(128);
|
|
49
|
+
for (let i = 0; i < B64URL_CHARS.length; i++) {
|
|
50
|
+
lookup[B64URL_CHARS.charCodeAt(i)] = i;
|
|
51
|
+
}
|
|
52
|
+
const len = str.length;
|
|
53
|
+
const outputLen = Math.floor((len * 3) / 4);
|
|
54
|
+
const bytes = new Uint8Array(outputLen);
|
|
55
|
+
let j = 0;
|
|
56
|
+
for (let i = 0; i < len; i += 4) {
|
|
57
|
+
const c0 = lookup[str.charCodeAt(i)];
|
|
58
|
+
const c1 = lookup[str.charCodeAt(i + 1)];
|
|
59
|
+
const c2 = i + 2 < len ? lookup[str.charCodeAt(i + 2)] : 0;
|
|
60
|
+
const c3 = i + 3 < len ? lookup[str.charCodeAt(i + 3)] : 0;
|
|
61
|
+
bytes[j++] = (c0 << 2) | (c1 >> 4);
|
|
62
|
+
if (i + 2 < len)
|
|
63
|
+
bytes[j++] = ((c1 & 0x0f) << 4) | (c2 >> 2);
|
|
64
|
+
if (i + 3 < len)
|
|
65
|
+
bytes[j++] = ((c2 & 0x03) << 6) | c3;
|
|
66
|
+
}
|
|
67
|
+
return bytes.slice(0, j);
|
|
68
|
+
}
|
|
69
|
+
// ─── Base58btc ──────────────────────────────────────────────────────────────
|
|
70
|
+
/**
|
|
71
|
+
* Encode bytes to base58btc (Bitcoin alphabet).
|
|
72
|
+
* Used for the multibase portion of did:key identifiers.
|
|
73
|
+
*/
|
|
74
|
+
export function base58btcEncode(bytes) {
|
|
75
|
+
return base58.encode(bytes);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Decode base58btc string to bytes.
|
|
79
|
+
*/
|
|
80
|
+
export function base58btcDecode(str) {
|
|
81
|
+
return base58.decode(str);
|
|
82
|
+
}
|
|
83
|
+
// ─── UTF-8 ──────────────────────────────────────────────────────────────────
|
|
84
|
+
const textEncoder = new TextEncoder();
|
|
85
|
+
const textDecoder = new TextDecoder();
|
|
86
|
+
/**
|
|
87
|
+
* Encode string to UTF-8 bytes.
|
|
88
|
+
*/
|
|
89
|
+
export function utf8Encode(str) {
|
|
90
|
+
return textEncoder.encode(str);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Decode UTF-8 bytes to string.
|
|
94
|
+
*/
|
|
95
|
+
export function utf8Decode(bytes) {
|
|
96
|
+
return textDecoder.decode(bytes);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=encode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode.js","sourceRoot":"","sources":["../../src/crypto/encode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — DID Fingerprint
|
|
3
|
+
*
|
|
4
|
+
* Convention (not a server feature):
|
|
5
|
+
* Fingerprint = first 16 lowercase hex characters of SHA-256 of the full did:key string.
|
|
6
|
+
*
|
|
7
|
+
* Used for publishing identity notes:
|
|
8
|
+
* /kv/did-{shard}/{remaining}
|
|
9
|
+
* where shard = first 2 chars, remaining = next 14 chars.
|
|
10
|
+
*
|
|
11
|
+
* Readers try the sharded path first, then legacy /kv/did/{fingerprint}.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Compute the DID fingerprint: first 16 hex chars of SHA-256(did:key string).
|
|
15
|
+
*
|
|
16
|
+
* @param did - The full did:key string (e.g., "did:key:z6Mk...")
|
|
17
|
+
* @returns 16-character lowercase hex string
|
|
18
|
+
*/
|
|
19
|
+
export declare function didFingerprint(did: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Get the sharded note path for a DID.
|
|
22
|
+
*
|
|
23
|
+
* @param did - The full did:key string
|
|
24
|
+
* @returns { shard, key, namespace, path } where:
|
|
25
|
+
* - shard: first 2 hex chars
|
|
26
|
+
* - key: remaining 14 hex chars
|
|
27
|
+
* - namespace: `did-${shard}`
|
|
28
|
+
* - path: `/kv/did-${shard}/${key}`
|
|
29
|
+
*/
|
|
30
|
+
export declare function didNotePath(did: string): {
|
|
31
|
+
shard: string;
|
|
32
|
+
key: string;
|
|
33
|
+
namespace: string;
|
|
34
|
+
path: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Get the legacy (unsharded) note path for a DID.
|
|
38
|
+
*
|
|
39
|
+
* @param did - The full did:key string
|
|
40
|
+
* @returns Legacy path `/kv/did/${fingerprint}`
|
|
41
|
+
*/
|
|
42
|
+
export declare function didLegacyNotePath(did: string): string;
|
|
43
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/crypto/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — DID Fingerprint
|
|
3
|
+
*
|
|
4
|
+
* Convention (not a server feature):
|
|
5
|
+
* Fingerprint = first 16 lowercase hex characters of SHA-256 of the full did:key string.
|
|
6
|
+
*
|
|
7
|
+
* Used for publishing identity notes:
|
|
8
|
+
* /kv/did-{shard}/{remaining}
|
|
9
|
+
* where shard = first 2 chars, remaining = next 14 chars.
|
|
10
|
+
*
|
|
11
|
+
* Readers try the sharded path first, then legacy /kv/did/{fingerprint}.
|
|
12
|
+
*/
|
|
13
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
14
|
+
import { utf8Encode } from './encode.js';
|
|
15
|
+
/**
|
|
16
|
+
* Compute the DID fingerprint: first 16 hex chars of SHA-256(did:key string).
|
|
17
|
+
*
|
|
18
|
+
* @param did - The full did:key string (e.g., "did:key:z6Mk...")
|
|
19
|
+
* @returns 16-character lowercase hex string
|
|
20
|
+
*/
|
|
21
|
+
export function didFingerprint(did) {
|
|
22
|
+
const hash = sha256(utf8Encode(did));
|
|
23
|
+
// Convert first 8 bytes (16 hex chars) to lowercase hex
|
|
24
|
+
let hex = '';
|
|
25
|
+
for (let i = 0; i < 8; i++) {
|
|
26
|
+
hex += (hash[i] >>> 4).toString(16);
|
|
27
|
+
hex += (hash[i] & 0x0f).toString(16);
|
|
28
|
+
}
|
|
29
|
+
return hex;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the sharded note path for a DID.
|
|
33
|
+
*
|
|
34
|
+
* @param did - The full did:key string
|
|
35
|
+
* @returns { shard, key, namespace, path } where:
|
|
36
|
+
* - shard: first 2 hex chars
|
|
37
|
+
* - key: remaining 14 hex chars
|
|
38
|
+
* - namespace: `did-${shard}`
|
|
39
|
+
* - path: `/kv/did-${shard}/${key}`
|
|
40
|
+
*/
|
|
41
|
+
export function didNotePath(did) {
|
|
42
|
+
const fp = didFingerprint(did);
|
|
43
|
+
const shard = fp.slice(0, 2);
|
|
44
|
+
const key = fp.slice(2);
|
|
45
|
+
return {
|
|
46
|
+
shard,
|
|
47
|
+
key,
|
|
48
|
+
namespace: `did-${shard}`,
|
|
49
|
+
path: `/kv/did-${shard}/${key}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the legacy (unsharded) note path for a DID.
|
|
54
|
+
*
|
|
55
|
+
* @param did - The full did:key string
|
|
56
|
+
* @returns Legacy path `/kv/did/${fingerprint}`
|
|
57
|
+
*/
|
|
58
|
+
export function didLegacyNotePath(did) {
|
|
59
|
+
return `/kv/did/${didFingerprint(did)}`;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/crypto/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,wDAAwD;IACxD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IAMrC,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO;QACL,KAAK;QACL,GAAG;QACH,SAAS,EAAE,OAAO,KAAK,EAAE;QACzB,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,EAAE;KAChC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,WAAW,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Nonce Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages strictly increasing nonces per (identity, room) pair.
|
|
5
|
+
*
|
|
6
|
+
* Requirements from the protocol:
|
|
7
|
+
* - Nonce must be 1–19 digits
|
|
8
|
+
* - Must be strictly greater than the last nonce that key used in that room
|
|
9
|
+
* - A millisecond clock works, but concurrent sends must not collide
|
|
10
|
+
*
|
|
11
|
+
* Strategy: monotonic counter based on Date.now(), with an atomic increment
|
|
12
|
+
* that prevents concurrent collision. Promise.all([send(), send(), send()])
|
|
13
|
+
* will produce distinct monotonic nonces.
|
|
14
|
+
*/
|
|
15
|
+
export declare class NonceManager {
|
|
16
|
+
#private;
|
|
17
|
+
/**
|
|
18
|
+
* Get the next nonce for a given identity and room.
|
|
19
|
+
* Thread-safe within a single JS event loop (synchronous increment).
|
|
20
|
+
*
|
|
21
|
+
* @param did - The DID of the signing identity
|
|
22
|
+
* @param room - The room name
|
|
23
|
+
* @returns Nonce string (1–19 digits, strictly increasing)
|
|
24
|
+
*/
|
|
25
|
+
next(did: string, room: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Set the last known nonce for a (did, room) pair.
|
|
28
|
+
* Use this when recovering state from a server response or external source.
|
|
29
|
+
*
|
|
30
|
+
* @param did - The DID
|
|
31
|
+
* @param room - The room name
|
|
32
|
+
* @param nonce - The last known nonce value
|
|
33
|
+
*/
|
|
34
|
+
setLastNonce(did: string, room: string, nonce: bigint | number | string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get the last issued nonce for a (did, room) pair, or undefined if none.
|
|
37
|
+
*/
|
|
38
|
+
getLastNonce(did: string, room: string): bigint | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Clear all tracked nonces.
|
|
41
|
+
*/
|
|
42
|
+
clear(): void;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=nonce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.d.ts","sourceRoot":"","sources":["../../src/crypto/nonce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,qBAAa,YAAY;;IAOvB;;;;;;;OAOG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAavC;;;;;;;OAOG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAU9E;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Nonce Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages strictly increasing nonces per (identity, room) pair.
|
|
5
|
+
*
|
|
6
|
+
* Requirements from the protocol:
|
|
7
|
+
* - Nonce must be 1–19 digits
|
|
8
|
+
* - Must be strictly greater than the last nonce that key used in that room
|
|
9
|
+
* - A millisecond clock works, but concurrent sends must not collide
|
|
10
|
+
*
|
|
11
|
+
* Strategy: monotonic counter based on Date.now(), with an atomic increment
|
|
12
|
+
* that prevents concurrent collision. Promise.all([send(), send(), send()])
|
|
13
|
+
* will produce distinct monotonic nonces.
|
|
14
|
+
*/
|
|
15
|
+
export class NonceManager {
|
|
16
|
+
/**
|
|
17
|
+
* Map of "did|room" → last issued nonce (as bigint for safe 19-digit handling).
|
|
18
|
+
* Using bigint because nonces can be up to 19 digits (past 2^53).
|
|
19
|
+
*/
|
|
20
|
+
#lastNonce = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Get the next nonce for a given identity and room.
|
|
23
|
+
* Thread-safe within a single JS event loop (synchronous increment).
|
|
24
|
+
*
|
|
25
|
+
* @param did - The DID of the signing identity
|
|
26
|
+
* @param room - The room name
|
|
27
|
+
* @returns Nonce string (1–19 digits, strictly increasing)
|
|
28
|
+
*/
|
|
29
|
+
next(did, room) {
|
|
30
|
+
const key = `${did}|${room}`;
|
|
31
|
+
const now = BigInt(Date.now());
|
|
32
|
+
const last = this.#lastNonce.get(key) ?? 0n;
|
|
33
|
+
// Take the max of (current time in ms, last nonce + 1)
|
|
34
|
+
// This ensures monotonicity even under sub-millisecond concurrency
|
|
35
|
+
const nonce = now > last ? now : last + 1n;
|
|
36
|
+
this.#lastNonce.set(key, nonce);
|
|
37
|
+
return nonce.toString();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Set the last known nonce for a (did, room) pair.
|
|
41
|
+
* Use this when recovering state from a server response or external source.
|
|
42
|
+
*
|
|
43
|
+
* @param did - The DID
|
|
44
|
+
* @param room - The room name
|
|
45
|
+
* @param nonce - The last known nonce value
|
|
46
|
+
*/
|
|
47
|
+
setLastNonce(did, room, nonce) {
|
|
48
|
+
const key = `${did}|${room}`;
|
|
49
|
+
const n = typeof nonce === 'bigint' ? nonce : BigInt(nonce);
|
|
50
|
+
const current = this.#lastNonce.get(key) ?? 0n;
|
|
51
|
+
// Only advance, never regress
|
|
52
|
+
if (n > current) {
|
|
53
|
+
this.#lastNonce.set(key, n);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the last issued nonce for a (did, room) pair, or undefined if none.
|
|
58
|
+
*/
|
|
59
|
+
getLastNonce(did, room) {
|
|
60
|
+
return this.#lastNonce.get(`${did}|${room}`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Clear all tracked nonces.
|
|
64
|
+
*/
|
|
65
|
+
clear() {
|
|
66
|
+
this.#lastNonce.clear();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=nonce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce.js","sourceRoot":"","sources":["../../src/crypto/nonce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,OAAO,YAAY;IACvB;;;OAGG;IACM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEhD;;;;;;;OAOG;IACH,IAAI,CAAC,GAAW,EAAE,IAAY;QAC5B,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAE5C,uDAAuD;QACvD,mEAAmE;QACnE,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEhC,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,YAAY,CAAC,GAAW,EAAE,IAAY,EAAE,KAA+B;QACrE,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC/C,8BAA8B;QAC9B,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC;YAChB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,GAAW,EAAE,IAAY;QACpC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Ed25519 Signing
|
|
3
|
+
*
|
|
4
|
+
* Uses @noble/ed25519 (audited by Cure53, zero dependencies).
|
|
5
|
+
*
|
|
6
|
+
* The signing pipeline:
|
|
7
|
+
* 1. Apply single-line sweep to text
|
|
8
|
+
* 2. Build canonical string: <room>|<nonce>|<sweptText>
|
|
9
|
+
* 3. Encode as UTF-8 bytes
|
|
10
|
+
* 4. Sign with Ed25519 private key → 64-byte signature
|
|
11
|
+
* 5. Encode signature as base64url (86 chars, canonical last char)
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Result of signing a Technocore message.
|
|
15
|
+
*/
|
|
16
|
+
export interface SignResult {
|
|
17
|
+
/** The text after single-line sweep (what gets stored). */
|
|
18
|
+
readonly sweptText: string;
|
|
19
|
+
/** Base64url-encoded signature (86 chars, canonical). */
|
|
20
|
+
readonly sig: string;
|
|
21
|
+
/** The nonce used (as string, 1–19 digits). */
|
|
22
|
+
readonly nonce: string;
|
|
23
|
+
/** The raw canonical payload that was signed (for debugging/verification). */
|
|
24
|
+
readonly canonicalPayload: Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sign a Technocore room message.
|
|
28
|
+
*
|
|
29
|
+
* @param privateKey - 32-byte Ed25519 private key (seed)
|
|
30
|
+
* @param room - Room name
|
|
31
|
+
* @param nonce - Nonce string (1–19 digits, must be > last nonce for this key+room)
|
|
32
|
+
* @param text - Raw message text (sweep will be applied)
|
|
33
|
+
* @returns SignResult with swept text, signature, nonce, and canonical payload
|
|
34
|
+
*/
|
|
35
|
+
export declare function signMessage(privateKey: Uint8Array, room: string, nonce: string, text: string): Promise<SignResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Sign a Technocore note write.
|
|
38
|
+
*
|
|
39
|
+
* @param privateKey - 32-byte Ed25519 private key (seed)
|
|
40
|
+
* @param namespace - Note namespace (e.g., "room-owners")
|
|
41
|
+
* @param key - Note key
|
|
42
|
+
* @param nonce - Nonce string
|
|
43
|
+
* @param value - Note value
|
|
44
|
+
* @returns Base64url-encoded signature
|
|
45
|
+
*/
|
|
46
|
+
export declare function signNote(privateKey: Uint8Array, namespace: string, key: string, nonce: string, value: string): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Raw Ed25519 sign — sign arbitrary bytes.
|
|
49
|
+
* Lower-level API for custom signing needs.
|
|
50
|
+
*/
|
|
51
|
+
export declare function rawSign(privateKey: Uint8Array, message: Uint8Array): Promise<Uint8Array>;
|
|
52
|
+
//# sourceMappingURL=sign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../src/crypto/sign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,gBAAgB,EAAE,UAAU,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,CAAC,CAqBrB;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAErB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Ed25519 Signing
|
|
3
|
+
*
|
|
4
|
+
* Uses @noble/ed25519 (audited by Cure53, zero dependencies).
|
|
5
|
+
*
|
|
6
|
+
* The signing pipeline:
|
|
7
|
+
* 1. Apply single-line sweep to text
|
|
8
|
+
* 2. Build canonical string: <room>|<nonce>|<sweptText>
|
|
9
|
+
* 3. Encode as UTF-8 bytes
|
|
10
|
+
* 4. Sign with Ed25519 private key → 64-byte signature
|
|
11
|
+
* 5. Encode signature as base64url (86 chars, canonical last char)
|
|
12
|
+
*/
|
|
13
|
+
import * as ed from '@noble/ed25519';
|
|
14
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
15
|
+
import { base64urlEncode } from './encode.js';
|
|
16
|
+
import { sweep } from './sweep.js';
|
|
17
|
+
import { canonicalMessagePayload, canonicalNotePayload } from './canonicalize.js';
|
|
18
|
+
import { SIG_PATTERN } from '../types/index.js';
|
|
19
|
+
import { TechnocoreSignatureError } from '../errors/index.js';
|
|
20
|
+
// Configure noble/ed25519 to use @noble/hashes for SHA-512
|
|
21
|
+
// This is required in environments without Web Crypto (some Node versions, edge runtimes)
|
|
22
|
+
ed.etc.sha512Sync = (...m) => {
|
|
23
|
+
const h = sha512.create();
|
|
24
|
+
for (const msg of m)
|
|
25
|
+
h.update(msg);
|
|
26
|
+
return h.digest();
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Sign a Technocore room message.
|
|
30
|
+
*
|
|
31
|
+
* @param privateKey - 32-byte Ed25519 private key (seed)
|
|
32
|
+
* @param room - Room name
|
|
33
|
+
* @param nonce - Nonce string (1–19 digits, must be > last nonce for this key+room)
|
|
34
|
+
* @param text - Raw message text (sweep will be applied)
|
|
35
|
+
* @returns SignResult with swept text, signature, nonce, and canonical payload
|
|
36
|
+
*/
|
|
37
|
+
export async function signMessage(privateKey, room, nonce, text) {
|
|
38
|
+
// Step 1: Apply single-line sweep
|
|
39
|
+
const sweptText = sweep(text);
|
|
40
|
+
// Step 2-3: Build canonical payload as UTF-8
|
|
41
|
+
const payload = canonicalMessagePayload(room, nonce, sweptText);
|
|
42
|
+
// Step 4: Sign with Ed25519
|
|
43
|
+
const sigBytes = await ed.signAsync(payload, privateKey);
|
|
44
|
+
// Step 5: Encode as base64url
|
|
45
|
+
const sig = base64urlEncode(sigBytes);
|
|
46
|
+
// Validate the canonical form
|
|
47
|
+
if (!SIG_PATTERN.test(sig)) {
|
|
48
|
+
throw new TechnocoreSignatureError(`Generated signature is not canonical: ${sig} (last char must be A, Q, g, or w)`);
|
|
49
|
+
}
|
|
50
|
+
return { sweptText, sig, nonce, canonicalPayload: payload };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sign a Technocore note write.
|
|
54
|
+
*
|
|
55
|
+
* @param privateKey - 32-byte Ed25519 private key (seed)
|
|
56
|
+
* @param namespace - Note namespace (e.g., "room-owners")
|
|
57
|
+
* @param key - Note key
|
|
58
|
+
* @param nonce - Nonce string
|
|
59
|
+
* @param value - Note value
|
|
60
|
+
* @returns Base64url-encoded signature
|
|
61
|
+
*/
|
|
62
|
+
export async function signNote(privateKey, namespace, key, nonce, value) {
|
|
63
|
+
const payload = canonicalNotePayload(namespace, key, nonce, value);
|
|
64
|
+
const sigBytes = await ed.signAsync(payload, privateKey);
|
|
65
|
+
const sig = base64urlEncode(sigBytes);
|
|
66
|
+
if (!SIG_PATTERN.test(sig)) {
|
|
67
|
+
throw new TechnocoreSignatureError(`Generated note signature is not canonical: ${sig}`);
|
|
68
|
+
}
|
|
69
|
+
return sig;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Raw Ed25519 sign — sign arbitrary bytes.
|
|
73
|
+
* Lower-level API for custom signing needs.
|
|
74
|
+
*/
|
|
75
|
+
export async function rawSign(privateKey, message) {
|
|
76
|
+
return ed.signAsync(message, privateKey);
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=sign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.js","sourceRoot":"","sources":["../../src/crypto/sign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,2DAA2D;AAC3D,0FAA0F;AAC1F,EAAE,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,CAAe,EAAE,EAAE;IACzC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,CAAC;QAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC;AAgBF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAsB,EACtB,IAAY,EACZ,KAAa,EACb,IAAY;IAEZ,kCAAkC;IAClC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAE9B,6CAA6C;IAC7C,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAEhE,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEzD,8BAA8B;IAC9B,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEtC,8BAA8B;IAC9B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,wBAAwB,CAChC,yCAAyC,GAAG,oCAAoC,CACjF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAsB,EACtB,SAAiB,EACjB,GAAW,EACX,KAAa,EACb,KAAa;IAEb,MAAM,OAAO,GAAG,oBAAoB,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEtC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,wBAAwB,CAChC,8CAA8C,GAAG,EAAE,CACpD,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAsB,EACtB,OAAmB;IAEnB,OAAO,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Single-Line Sweep
|
|
3
|
+
*
|
|
4
|
+
* The server replaces every character in Unicode general categories
|
|
5
|
+
* Cc, Cf, Cs, Co, Zl, and Zp with a space before storage, then trims the ends.
|
|
6
|
+
*
|
|
7
|
+
* This is NOT Unicode normalization (NFC/NFD). The server never normalizes —
|
|
8
|
+
* it stores the code points you send. NFC and NFD of one word are two different
|
|
9
|
+
* messages.
|
|
10
|
+
*
|
|
11
|
+
* Sign the text AFTER the sweep — the bytes that get stored — so the record
|
|
12
|
+
* can be re-verified later.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Apply the Technocore single-line sweep to text.
|
|
16
|
+
*
|
|
17
|
+
* Replaces all characters in Unicode categories Cc, Cf, Cs, Co, Zl, Zp
|
|
18
|
+
* with a space, then trims both ends.
|
|
19
|
+
*
|
|
20
|
+
* @param text - Raw input text
|
|
21
|
+
* @returns Swept text (single-line, ready for signing)
|
|
22
|
+
*/
|
|
23
|
+
export declare function sweep(text: string): string;
|
|
24
|
+
//# sourceMappingURL=sweep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweep.d.ts","sourceRoot":"","sources":["../../src/crypto/sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiBH;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Single-Line Sweep
|
|
3
|
+
*
|
|
4
|
+
* The server replaces every character in Unicode general categories
|
|
5
|
+
* Cc, Cf, Cs, Co, Zl, and Zp with a space before storage, then trims the ends.
|
|
6
|
+
*
|
|
7
|
+
* This is NOT Unicode normalization (NFC/NFD). The server never normalizes —
|
|
8
|
+
* it stores the code points you send. NFC and NFD of one word are two different
|
|
9
|
+
* messages.
|
|
10
|
+
*
|
|
11
|
+
* Sign the text AFTER the sweep — the bytes that get stored — so the record
|
|
12
|
+
* can be re-verified later.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Regex matching characters the server replaces with space.
|
|
16
|
+
*
|
|
17
|
+
* Categories:
|
|
18
|
+
* - Cc: C0/C1 controls (U+0000–U+001F, U+007F–U+009F) — includes \n, \r, \t
|
|
19
|
+
* - Cf: Format characters (zero-width joiners, bidi overrides, Unicode tag block)
|
|
20
|
+
* - Cs: Lone surrogates (U+D800–U+DFFF)
|
|
21
|
+
* - Co: Private use (U+E000–U+F8FF, U+F0000–U+FFFFD, U+100000–U+10FFFD)
|
|
22
|
+
* - Zl: Line separator (U+2028)
|
|
23
|
+
* - Zp: Paragraph separator (U+2029)
|
|
24
|
+
*
|
|
25
|
+
* Uses Unicode property escapes (ES2018+).
|
|
26
|
+
*/
|
|
27
|
+
const SWEEP_PATTERN = /[\p{Cc}\p{Cf}\p{Cs}\p{Co}\p{Zl}\p{Zp}]/gu;
|
|
28
|
+
/**
|
|
29
|
+
* Apply the Technocore single-line sweep to text.
|
|
30
|
+
*
|
|
31
|
+
* Replaces all characters in Unicode categories Cc, Cf, Cs, Co, Zl, Zp
|
|
32
|
+
* with a space, then trims both ends.
|
|
33
|
+
*
|
|
34
|
+
* @param text - Raw input text
|
|
35
|
+
* @returns Swept text (single-line, ready for signing)
|
|
36
|
+
*/
|
|
37
|
+
export function sweep(text) {
|
|
38
|
+
return text.replace(SWEEP_PATTERN, ' ').trim();
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/crypto/sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,aAAa,GAAG,0CAA0C,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technocore SDK — Ed25519 Verification
|
|
3
|
+
*
|
|
4
|
+
* Verifies signed Technocore messages offline — no network access required
|
|
5
|
+
* when the message contains enough information (room, nonce, text, sig, DID).
|
|
6
|
+
*
|
|
7
|
+
* Distinguishes:
|
|
8
|
+
* - syntactically valid DID
|
|
9
|
+
* - valid signature format
|
|
10
|
+
* - cryptographically valid signature
|
|
11
|
+
* These are different concepts. Never say "verified" when only the DID format is valid.
|
|
12
|
+
*/
|
|
13
|
+
import type { TechnocoreMessage, VerificationResult } from '../types/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Verify a signed Technocore message.
|
|
16
|
+
*
|
|
17
|
+
* @param room - The room the message belongs to
|
|
18
|
+
* @param message - The message object (must have `from`, `nonce`, `sig`, `text`)
|
|
19
|
+
* @returns Structured VerificationResult — never throws for invalid messages
|
|
20
|
+
*/
|
|
21
|
+
export declare function verifyMessage(room: string, message: TechnocoreMessage): Promise<VerificationResult>;
|
|
22
|
+
/**
|
|
23
|
+
* Raw Ed25519 verify — verify arbitrary bytes against a signature and public key.
|
|
24
|
+
* Lower-level API.
|
|
25
|
+
*/
|
|
26
|
+
export declare function rawVerify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): Promise<boolean>;
|
|
27
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/crypto/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA+F7B;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAElB"}
|