@ainize/core 0.2.3 → 0.3.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/dist/config-schema.js +1 -1
- package/dist/identity.d.ts +46 -3
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +68 -15
- package/dist/identity.js.map +1 -1
- package/package.json +4 -3
package/dist/config-schema.js
CHANGED
|
@@ -125,7 +125,7 @@ export const nodeConfigSchema = z.object({
|
|
|
125
125
|
*/
|
|
126
126
|
operatorPasswordHash: z.string().optional(),
|
|
127
127
|
/**
|
|
128
|
-
* Addresses that may sign in as this node's operator
|
|
128
|
+
* Addresses that may sign in as this node's operator, besides the node's own key.
|
|
129
129
|
*
|
|
130
130
|
* The node's OWN address is always allowed and is not listed here — whoever holds the node's key already owns
|
|
131
131
|
* everything the node published, so requiring them to also type a password protects nothing. This list is for
|
package/dist/identity.d.ts
CHANGED
|
@@ -7,9 +7,52 @@ export declare function createIdentity(): Identity;
|
|
|
7
7
|
export declare function identityFromPrivateKey(privHex: string): Identity;
|
|
8
8
|
export declare function signMessage(message: string, privHex: string): string;
|
|
9
9
|
export declare function verifyMessage(message: string, signature: string, address: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* ─── HUMANS SIGN EIP-191, KEYS SIGN AIN ───────────────────────────────────────────────────────────────────
|
|
12
|
+
*
|
|
13
|
+
* `verifyMessage` above is the product's universal scheme and it is deliberately NOT widened. It verifies
|
|
14
|
+
* teach headers, delegations, publish claims, x402 payment proofs, p2p headers and every local-ledger record —
|
|
15
|
+
* all of them produced by a key this product generated, several of them firing per minute. Making that one
|
|
16
|
+
* function accept a second signature shape would widen every one of those surfaces at once.
|
|
17
|
+
*
|
|
18
|
+
* What a browser wallet gives us is different in kind: a PERSON, present, approving one thing, with a prompt
|
|
19
|
+
* in front of them. That happens a handful of times — sign-in, claiming a node, approving a device — so it
|
|
20
|
+
* gets its own verifier and its own call sites.
|
|
21
|
+
*
|
|
22
|
+
* The two schemes differ twice over, and both differences are fatal to interop:
|
|
23
|
+
*
|
|
24
|
+
* AIN keccak256(keccak256( varint(26) ‖ 'AINetwork Signed Message:\n' ‖ varint(str.length) ‖ bytes ))
|
|
25
|
+
* wire: 0x ‖ hash(32) ‖ r(32) ‖ s(32) ‖ v(1) — the digest travels WITH the signature
|
|
26
|
+
* EIP-191 keccak256( '\x19Ethereum Signed Message:\n' ‖ byteLength ‖ bytes )
|
|
27
|
+
* wire: 0x ‖ r(32) ‖ s(32) ‖ v(1) — 65 bytes, no embedded digest
|
|
28
|
+
*
|
|
29
|
+
* Note the length: AIN counts UTF-16 code units (JS `.length`), EIP-191 counts UTF-8 bytes. For "한글" that is
|
|
30
|
+
* 2 against 6, so a Korean message hashes differently even before the prefix is considered.
|
|
31
|
+
*
|
|
32
|
+
* The ADDRESS is the same in both worlds — same curve, same keccak-of-pubkey derivation — which is the whole
|
|
33
|
+
* reason this works: a MetaMask account names exactly one AIN address. Measured, not assumed: the same private
|
|
34
|
+
* key yields 0x00ADEc28… under both `privateToAddress` and Ethereum's rules.
|
|
35
|
+
*/
|
|
36
|
+
/** The EIP-191 personal-message digest MetaMask signs. Byte length, not string length. */
|
|
37
|
+
export declare function hashEip191(message: string): Buffer;
|
|
38
|
+
/**
|
|
39
|
+
* Did `address` sign `message` with a browser wallet (MetaMask and every EIP-1193 wallet)?
|
|
40
|
+
*
|
|
41
|
+
* Rejects anything that is not a bare 65-byte signature, so an AIN signature — which carries its own 32-byte
|
|
42
|
+
* digest in front and is therefore 97 bytes — cannot be smuggled in here and silently verified under the wrong
|
|
43
|
+
* rules. `v` is accepted as 27/28 (what wallets send) or 0/1 (what some libraries send).
|
|
44
|
+
*/
|
|
45
|
+
export declare function verifyEip191(message: string, signature: string, address: string): boolean;
|
|
46
|
+
/** Which scheme produced a signature. `ain` is a key this product generated; `eip191` is a person's wallet. */
|
|
47
|
+
export type AuthScheme = 'ain' | 'eip191';
|
|
48
|
+
/**
|
|
49
|
+
* Verify a signature under a NAMED scheme.
|
|
50
|
+
*
|
|
51
|
+
* The scheme is always stated by the caller and never guessed from the signature's shape. A verifier that
|
|
52
|
+
* tried both would accept whichever passed, which means an attacker picks the scheme — and the two have
|
|
53
|
+
* different security properties at the call site (a wallet prompt a human saw, versus a key acting on its own).
|
|
54
|
+
*/
|
|
55
|
+
export declare function verifyAuth(scheme: AuthScheme, message: string, signature: string, address: string): boolean;
|
|
10
56
|
export declare function isAddress(value: string): boolean;
|
|
11
57
|
export declare function checksum(address: string): string;
|
|
12
|
-
/** Operator password hashing (scrypt) for the web console login. */
|
|
13
|
-
export declare function hashPassword(password: string): string;
|
|
14
|
-
export declare function verifyPassword(password: string, stored: string): boolean;
|
|
15
58
|
//# sourceMappingURL=identity.d.ts.map
|
package/dist/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,IAAI,QAAQ,CAKzC;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAKhE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAM1F;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,IAAI,QAAQ,CAKzC;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAKhE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAM1F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAezF;AAED,+GAA+G;AAC/G,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3G;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMhD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
package/dist/identity.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* so a node's signature over a ledger record is verifiable by any peer with only the address.
|
|
5
5
|
*/
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
|
-
import { randomBytes
|
|
7
|
+
import { randomBytes } from 'node:crypto';
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
9
9
|
// ain-util is CommonJS
|
|
10
10
|
const ainUtil = require('@ainblockchain/ain-util');
|
|
@@ -31,6 +31,73 @@ export function verifyMessage(message, signature, address) {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* ─── HUMANS SIGN EIP-191, KEYS SIGN AIN ───────────────────────────────────────────────────────────────────
|
|
36
|
+
*
|
|
37
|
+
* `verifyMessage` above is the product's universal scheme and it is deliberately NOT widened. It verifies
|
|
38
|
+
* teach headers, delegations, publish claims, x402 payment proofs, p2p headers and every local-ledger record —
|
|
39
|
+
* all of them produced by a key this product generated, several of them firing per minute. Making that one
|
|
40
|
+
* function accept a second signature shape would widen every one of those surfaces at once.
|
|
41
|
+
*
|
|
42
|
+
* What a browser wallet gives us is different in kind: a PERSON, present, approving one thing, with a prompt
|
|
43
|
+
* in front of them. That happens a handful of times — sign-in, claiming a node, approving a device — so it
|
|
44
|
+
* gets its own verifier and its own call sites.
|
|
45
|
+
*
|
|
46
|
+
* The two schemes differ twice over, and both differences are fatal to interop:
|
|
47
|
+
*
|
|
48
|
+
* AIN keccak256(keccak256( varint(26) ‖ 'AINetwork Signed Message:\n' ‖ varint(str.length) ‖ bytes ))
|
|
49
|
+
* wire: 0x ‖ hash(32) ‖ r(32) ‖ s(32) ‖ v(1) — the digest travels WITH the signature
|
|
50
|
+
* EIP-191 keccak256( '\x19Ethereum Signed Message:\n' ‖ byteLength ‖ bytes )
|
|
51
|
+
* wire: 0x ‖ r(32) ‖ s(32) ‖ v(1) — 65 bytes, no embedded digest
|
|
52
|
+
*
|
|
53
|
+
* Note the length: AIN counts UTF-16 code units (JS `.length`), EIP-191 counts UTF-8 bytes. For "한글" that is
|
|
54
|
+
* 2 against 6, so a Korean message hashes differently even before the prefix is considered.
|
|
55
|
+
*
|
|
56
|
+
* The ADDRESS is the same in both worlds — same curve, same keccak-of-pubkey derivation — which is the whole
|
|
57
|
+
* reason this works: a MetaMask account names exactly one AIN address. Measured, not assumed: the same private
|
|
58
|
+
* key yields 0x00ADEc28… under both `privateToAddress` and Ethereum's rules.
|
|
59
|
+
*/
|
|
60
|
+
/** The EIP-191 personal-message digest MetaMask signs. Byte length, not string length. */
|
|
61
|
+
export function hashEip191(message) {
|
|
62
|
+
const bytes = Buffer.from(message, 'utf8');
|
|
63
|
+
return ainUtil.keccak(Buffer.concat([Buffer.from(`\x19Ethereum Signed Message:\n${bytes.length}`, 'utf8'), bytes]));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Did `address` sign `message` with a browser wallet (MetaMask and every EIP-1193 wallet)?
|
|
67
|
+
*
|
|
68
|
+
* Rejects anything that is not a bare 65-byte signature, so an AIN signature — which carries its own 32-byte
|
|
69
|
+
* digest in front and is therefore 97 bytes — cannot be smuggled in here and silently verified under the wrong
|
|
70
|
+
* rules. `v` is accepted as 27/28 (what wallets send) or 0/1 (what some libraries send).
|
|
71
|
+
*/
|
|
72
|
+
export function verifyEip191(message, signature, address) {
|
|
73
|
+
try {
|
|
74
|
+
const raw = Buffer.from(signature.replace(/^0x/, ''), 'hex');
|
|
75
|
+
if (raw.length !== 65)
|
|
76
|
+
return false;
|
|
77
|
+
const r = raw.subarray(0, 32);
|
|
78
|
+
const s = raw.subarray(32, 64);
|
|
79
|
+
const vRaw = raw[64];
|
|
80
|
+
const v = vRaw >= 27 ? vRaw : vRaw + 27;
|
|
81
|
+
if (v !== 27 && v !== 28)
|
|
82
|
+
return false;
|
|
83
|
+
const pub = ainUtil.ecRecoverPub(hashEip191(message), r, s, v);
|
|
84
|
+
const recovered = ainUtil.toChecksumAddress(ainUtil.bufferToHex(ainUtil.pubToAddress(pub.subarray(1))));
|
|
85
|
+
return recovered.toLowerCase() === address.toLowerCase();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Verify a signature under a NAMED scheme.
|
|
93
|
+
*
|
|
94
|
+
* The scheme is always stated by the caller and never guessed from the signature's shape. A verifier that
|
|
95
|
+
* tried both would accept whichever passed, which means an attacker picks the scheme — and the two have
|
|
96
|
+
* different security properties at the call site (a wallet prompt a human saw, versus a key acting on its own).
|
|
97
|
+
*/
|
|
98
|
+
export function verifyAuth(scheme, message, signature, address) {
|
|
99
|
+
return scheme === 'eip191' ? verifyEip191(message, signature, address) : verifyMessage(message, signature, address);
|
|
100
|
+
}
|
|
34
101
|
export function isAddress(value) {
|
|
35
102
|
try {
|
|
36
103
|
return ainUtil.isValidAddress(value);
|
|
@@ -42,18 +109,4 @@ export function isAddress(value) {
|
|
|
42
109
|
export function checksum(address) {
|
|
43
110
|
return ainUtil.toChecksumAddress(address);
|
|
44
111
|
}
|
|
45
|
-
/** Operator password hashing (scrypt) for the web console login. */
|
|
46
|
-
export function hashPassword(password) {
|
|
47
|
-
const salt = randomBytes(16);
|
|
48
|
-
const key = scryptSync(password, salt, 32);
|
|
49
|
-
return `scrypt$${salt.toString('hex')}$${key.toString('hex')}`;
|
|
50
|
-
}
|
|
51
|
-
export function verifyPassword(password, stored) {
|
|
52
|
-
const [alg, saltHex, keyHex] = stored.split('$');
|
|
53
|
-
if (alg !== 'scrypt' || !saltHex || !keyHex)
|
|
54
|
-
return false;
|
|
55
|
-
const key = scryptSync(password, Buffer.from(saltHex, 'hex'), 32);
|
|
56
|
-
const expected = Buffer.from(keyHex, 'hex');
|
|
57
|
-
return key.length === expected.length && timingSafeEqual(key, expected);
|
|
58
|
-
}
|
|
59
112
|
//# sourceMappingURL=identity.js.map
|
package/dist/identity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainize/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Ainize core
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Ainize core — knowledge-patch schemas, lineage, verification and ledger (AIN) bindings shared by @ainize/node and @ainize/cli",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -42,8 +42,9 @@
|
|
|
42
42
|
"zod": "^4.5.4"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
+
"@noble/secp256k1": "^2.3.0",
|
|
45
46
|
"@types/node": "^24.10.0",
|
|
46
47
|
"tsx": "^4.23.13",
|
|
47
48
|
"typescript": "^5.9.3"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|