@totemsdk/identity 0.1.0 → 0.1.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 +21 -0
- package/README.md +306 -0
- package/dist/canonical.js +6 -2
- package/dist/claims.js +15 -9
- package/dist/constants.js +4 -1
- package/dist/document.js +12 -8
- package/dist/guards.js +12 -5
- package/dist/index.js +32 -10
- package/dist/manifest-binding.js +11 -7
- package/dist/resolver.js +6 -3
- package/dist/revocation.js +6 -3
- package/dist/rotation.js +6 -3
- package/dist/signing.js +16 -12
- package/dist/types.js +2 -1
- package/dist/verify.js +13 -10
- package/package.json +29 -6
- package/src/__tests__/identity.test.ts +0 -618
- package/src/canonical.ts +0 -27
- package/src/claims.ts +0 -108
- package/src/constants.ts +0 -1
- package/src/document.ts +0 -35
- package/src/guards.ts +0 -75
- package/src/index.ts +0 -55
- package/src/manifest-binding.ts +0 -163
- package/src/resolver.ts +0 -171
- package/src/revocation.ts +0 -25
- package/src/rotation.ts +0 -23
- package/src/signing.ts +0 -38
- package/src/types.ts +0 -147
- package/src/verify.ts +0 -90
package/src/types.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @totemsdk/identity — Type definitions
|
|
3
|
-
*
|
|
4
|
-
* Pure schema — no network, no DHT, no blockchain submission.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export type IdentityKind =
|
|
8
|
-
| 'person'
|
|
9
|
-
| 'device'
|
|
10
|
-
| 'agent'
|
|
11
|
-
| 'service'
|
|
12
|
-
| 'organization'
|
|
13
|
-
| 'sensor'
|
|
14
|
-
| 'robot'
|
|
15
|
-
| 'gateway';
|
|
16
|
-
|
|
17
|
-
export type IdentityStatus = 'active' | 'rotated' | 'revoked';
|
|
18
|
-
|
|
19
|
-
export interface TotemIdentityDocument {
|
|
20
|
-
id: string;
|
|
21
|
-
kind: IdentityKind;
|
|
22
|
-
version: number;
|
|
23
|
-
rootAddress: string;
|
|
24
|
-
controllerAddress: string;
|
|
25
|
-
createdAt: number;
|
|
26
|
-
metadata?: Record<string, unknown>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type IdentityClaimType =
|
|
30
|
-
| 'delegates_to'
|
|
31
|
-
| 'payment_recipient'
|
|
32
|
-
| 'service_endpoint'
|
|
33
|
-
| 'rotates_to'
|
|
34
|
-
| 'revokes';
|
|
35
|
-
|
|
36
|
-
export interface IdentityClaim {
|
|
37
|
-
id: string;
|
|
38
|
-
type: IdentityClaimType;
|
|
39
|
-
issuer: string;
|
|
40
|
-
subject: string;
|
|
41
|
-
object: string;
|
|
42
|
-
issuedAt: number;
|
|
43
|
-
expiresAt?: number;
|
|
44
|
-
payload: Record<string, unknown>;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface SignedIdentityClaim {
|
|
48
|
-
claim: IdentityClaim;
|
|
49
|
-
proof: {
|
|
50
|
-
address: string;
|
|
51
|
-
publicKey: string;
|
|
52
|
-
signature: string;
|
|
53
|
-
message?: string;
|
|
54
|
-
};
|
|
55
|
-
rootIdentityProof?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface IdentityVerifyResult {
|
|
59
|
-
valid: boolean;
|
|
60
|
-
reason?: string;
|
|
61
|
-
signerAddress?: string;
|
|
62
|
-
rootAddress?: string;
|
|
63
|
-
provenAddresses?: string[];
|
|
64
|
-
metadata?: Record<string, unknown>;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface IdentityProofVerifier {
|
|
68
|
-
type: string;
|
|
69
|
-
verify(proof: unknown): Promise<IdentityVerifyResult>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface IdentityGraph {
|
|
73
|
-
document: TotemIdentityDocument;
|
|
74
|
-
claims: SignedIdentityClaim[];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ResolvedIdentity {
|
|
78
|
-
document: TotemIdentityDocument;
|
|
79
|
-
status: IdentityStatus;
|
|
80
|
-
rootAddress: string;
|
|
81
|
-
controllerAddress: string;
|
|
82
|
-
controlledAddresses: string[];
|
|
83
|
-
authorizedAddresses: string[];
|
|
84
|
-
delegates: DelegationClaim[];
|
|
85
|
-
paymentRecipients: PaymentRecipientClaim[];
|
|
86
|
-
serviceEndpoints: ServiceEndpointClaim[];
|
|
87
|
-
rotationTarget?: string;
|
|
88
|
-
revokedAt?: number;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface IdentityResolutionResult {
|
|
92
|
-
resolved: ResolvedIdentity | null;
|
|
93
|
-
errors: string[];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface DelegationClaim {
|
|
97
|
-
claimId: string;
|
|
98
|
-
issuer: string;
|
|
99
|
-
subject: string;
|
|
100
|
-
delegatedAddress: string;
|
|
101
|
-
scopes: string[];
|
|
102
|
-
issuedAt: number;
|
|
103
|
-
expiresAt?: number;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface PaymentRecipientClaim {
|
|
107
|
-
claimId: string;
|
|
108
|
-
issuer: string;
|
|
109
|
-
address: string;
|
|
110
|
-
label?: string;
|
|
111
|
-
issuedAt: number;
|
|
112
|
-
expiresAt?: number;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export interface ServiceEndpointClaim {
|
|
116
|
-
claimId: string;
|
|
117
|
-
issuer: string;
|
|
118
|
-
endpointType: string;
|
|
119
|
-
uri: string;
|
|
120
|
-
issuedAt: number;
|
|
121
|
-
expiresAt?: number;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface RotationClaim {
|
|
125
|
-
claimId: string;
|
|
126
|
-
issuer: string;
|
|
127
|
-
subject: string;
|
|
128
|
-
newAddress: string;
|
|
129
|
-
issuedAt: number;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export interface RevocationClaim {
|
|
133
|
-
claimId: string;
|
|
134
|
-
issuer: string;
|
|
135
|
-
subject: string;
|
|
136
|
-
reason?: string;
|
|
137
|
-
issuedAt: number;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export interface ManifestIdentityBinding {
|
|
141
|
-
valid: boolean;
|
|
142
|
-
reason?: string;
|
|
143
|
-
manifestId: string;
|
|
144
|
-
identityId: string;
|
|
145
|
-
signerAddress: string;
|
|
146
|
-
resolvedStatus: IdentityStatus;
|
|
147
|
-
}
|
package/src/verify.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claim verification.
|
|
3
|
-
*
|
|
4
|
-
* verifyIdentityClaim recomputes the canonical claim digest from signed.claim
|
|
5
|
-
* using canonicalJson. It does NOT use proof.message as the source of truth —
|
|
6
|
-
* that field is optional debug/display metadata only.
|
|
7
|
-
*
|
|
8
|
-
* Security: proof.address is bound to proof.publicKey by re-deriving the
|
|
9
|
-
* expected address from the public key. Any mismatch fails verification,
|
|
10
|
-
* preventing signer-address spoofing.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { wotsVerifyDigest, hexToBytes, scriptFromWotsPk, scriptToAddress } from '@totemsdk/core';
|
|
14
|
-
import { claimDigest } from './signing.js';
|
|
15
|
-
import type { SignedIdentityClaim, IdentityVerifyResult } from './types.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Derive the Minima address from a 32-byte WOTS PKdigest (hex).
|
|
19
|
-
* Returns null if the public key cannot be decoded.
|
|
20
|
-
*/
|
|
21
|
-
function addressFromPkDigest(publicKeyHex: string): string | null {
|
|
22
|
-
try {
|
|
23
|
-
const pkDigest = hexToBytes(publicKeyHex);
|
|
24
|
-
const script = scriptFromWotsPk(pkDigest);
|
|
25
|
-
return scriptToAddress(script);
|
|
26
|
-
} catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function verifyIdentityClaim(signed: SignedIdentityClaim): IdentityVerifyResult {
|
|
32
|
-
const { claim, proof } = signed;
|
|
33
|
-
|
|
34
|
-
let sigBytes: Uint8Array;
|
|
35
|
-
let pkDigest: Uint8Array;
|
|
36
|
-
try {
|
|
37
|
-
sigBytes = hexToBytes(proof.signature);
|
|
38
|
-
pkDigest = hexToBytes(proof.publicKey);
|
|
39
|
-
} catch (e) {
|
|
40
|
-
return {
|
|
41
|
-
valid: false,
|
|
42
|
-
reason: `hex decode failed: ${String(e)}`,
|
|
43
|
-
signerAddress: proof.address,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Bind proof.address to proof.publicKey — derive expected address from the public key
|
|
48
|
-
// and verify it matches proof.address. This prevents signer-address spoofing.
|
|
49
|
-
const expectedAddress = addressFromPkDigest(proof.publicKey);
|
|
50
|
-
if (expectedAddress === null) {
|
|
51
|
-
return {
|
|
52
|
-
valid: false,
|
|
53
|
-
reason: 'could not derive address from proof.publicKey',
|
|
54
|
-
signerAddress: proof.address,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (expectedAddress !== proof.address) {
|
|
58
|
-
return {
|
|
59
|
-
valid: false,
|
|
60
|
-
reason: `proof.address '${proof.address}' does not match address derived from proof.publicKey '${expectedAddress}'`,
|
|
61
|
-
signerAddress: proof.address,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const digest = claimDigest(claim);
|
|
66
|
-
|
|
67
|
-
let sigValid: boolean;
|
|
68
|
-
try {
|
|
69
|
-
sigValid = wotsVerifyDigest(sigBytes, digest, pkDigest);
|
|
70
|
-
} catch (e) {
|
|
71
|
-
return {
|
|
72
|
-
valid: false,
|
|
73
|
-
reason: `WOTS verify threw: ${String(e)}`,
|
|
74
|
-
signerAddress: proof.address,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (!sigValid) {
|
|
79
|
-
return {
|
|
80
|
-
valid: false,
|
|
81
|
-
reason: 'WOTS signature invalid',
|
|
82
|
-
signerAddress: proof.address,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
valid: true,
|
|
88
|
-
signerAddress: proof.address,
|
|
89
|
-
};
|
|
90
|
-
}
|