@oxyhq/services 5.17.7 → 5.17.9
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/lib/commonjs/crypto/index.js +0 -23
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/index.js +0 -15
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/Icon.js.map +1 -1
- package/lib/commonjs/ui/components/IconButton/utils.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/helpers.js.map +1 -1
- package/lib/commonjs/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/commonjs/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +37 -589
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContextBase.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +60 -425
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +8 -112
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +2 -27
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +2 -27
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +2 -88
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +0 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +52 -15
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +2 -32
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/crypto/index.js +4 -6
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/index.js +6 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/Icon.js.map +1 -1
- package/lib/module/ui/components/IconButton/utils.js.map +1 -1
- package/lib/module/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/module/ui/components/TextField/helpers.js.map +1 -1
- package/lib/module/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/module/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +35 -588
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/OxyContextBase.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +60 -424
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +8 -112
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +2 -27
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +2 -27
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +2 -88
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +0 -1
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +52 -15
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +2 -32
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/typescript/crypto/index.d.ts +2 -5
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/types.d.ts +6 -2
- package/lib/typescript/crypto/types.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +4 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/IconButton/utils.d.ts +1 -1
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts +1 -1
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
- package/lib/typescript/ui/components/TextField/helpers.d.ts +6 -6
- package/lib/typescript/ui/components/types.d.ts +0 -4
- package/lib/typescript/ui/components/types.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContextBase.d.ts +2 -39
- package/lib/typescript/ui/context/OxyContextBase.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +10 -25
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts +1 -14
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +27 -4
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts +0 -2
- package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/crypto/index.ts +3 -11
- package/src/crypto/types.ts +6 -2
- package/src/index.ts +6 -11
- package/src/ui/components/Icon.tsx +1 -1
- package/src/ui/components/IconButton/utils.ts +1 -1
- package/src/ui/components/TextField/Adornment/utils.ts +2 -2
- package/src/ui/components/TextField/helpers.tsx +8 -8
- package/src/ui/components/TouchableRipple/utils.ts +2 -2
- package/src/ui/components/Typography/AnimatedText.tsx +2 -2
- package/src/ui/components/types.tsx +0 -6
- package/src/ui/context/OxyContext.tsx +33 -637
- package/src/ui/context/OxyContextBase.tsx +5 -23
- package/src/ui/context/hooks/useAuthOperations.ts +84 -460
- package/src/ui/hooks/mutations/useAccountMutations.ts +12 -110
- package/src/ui/hooks/queries/useAccountQueries.ts +3 -27
- package/src/ui/hooks/queries/useServicesQueries.ts +3 -27
- package/src/ui/hooks/useSessionSocket.ts +2 -106
- package/src/ui/screens/OxyAuthScreen.tsx +1 -1
- package/src/ui/stores/authStore.ts +57 -18
- package/src/ui/utils/avatarUtils.ts +4 -36
- package/lib/commonjs/crypto/keyManager.js +0 -511
- package/lib/commonjs/crypto/keyManager.js.map +0 -1
- package/lib/commonjs/crypto/signatureService.js +0 -269
- package/lib/commonjs/crypto/signatureService.js.map +0 -1
- package/lib/module/crypto/keyManager.js +0 -508
- package/lib/module/crypto/keyManager.js.map +0 -1
- package/lib/module/crypto/signatureService.js +0 -266
- package/lib/module/crypto/signatureService.js.map +0 -1
- package/lib/typescript/crypto/keyManager.d.ts +0 -97
- package/lib/typescript/crypto/keyManager.d.ts.map +0 -1
- package/lib/typescript/crypto/signatureService.d.ts +0 -77
- package/lib/typescript/crypto/signatureService.d.ts.map +0 -1
- package/src/crypto/keyManager.ts +0 -545
- package/src/crypto/signatureService.ts +0 -301
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Signature Service - ECDSA Digital Signatures
|
|
3
|
-
*
|
|
4
|
-
* Handles signing and verification of messages using ECDSA secp256k1.
|
|
5
|
-
* Used for authenticating requests and proving identity ownership.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { ec as EC } from 'elliptic';
|
|
9
|
-
import { KeyManager } from './keyManager';
|
|
10
|
-
|
|
11
|
-
// Lazy import for expo-crypto
|
|
12
|
-
let ExpoCrypto: typeof import('expo-crypto') | null = null;
|
|
13
|
-
|
|
14
|
-
const ec = new EC('secp256k1');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Check if we're in a React Native environment
|
|
18
|
-
*/
|
|
19
|
-
function isReactNative(): boolean {
|
|
20
|
-
return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Check if we're in a Node.js environment
|
|
25
|
-
*/
|
|
26
|
-
function isNodeJS(): boolean {
|
|
27
|
-
return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Initialize expo-crypto module
|
|
32
|
-
*/
|
|
33
|
-
async function initExpoCrypto(): Promise<typeof import('expo-crypto')> {
|
|
34
|
-
if (!ExpoCrypto) {
|
|
35
|
-
ExpoCrypto = await import('expo-crypto');
|
|
36
|
-
}
|
|
37
|
-
return ExpoCrypto;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Compute SHA-256 hash of a string
|
|
42
|
-
*/
|
|
43
|
-
async function sha256(message: string): Promise<string> {
|
|
44
|
-
// In React Native, always use expo-crypto
|
|
45
|
-
if (isReactNative() || !isNodeJS()) {
|
|
46
|
-
const Crypto = await initExpoCrypto();
|
|
47
|
-
return Crypto.digestStringAsync(
|
|
48
|
-
Crypto.CryptoDigestAlgorithm.SHA256,
|
|
49
|
-
message
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// In Node.js, use Node's crypto module
|
|
54
|
-
// Use Function constructor to prevent Metro bundler from statically analyzing this require
|
|
55
|
-
// This ensures the require is only evaluated in Node.js runtime, not during Metro bundling
|
|
56
|
-
try {
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
58
|
-
const getCrypto = new Function('return require("crypto")');
|
|
59
|
-
const crypto = getCrypto();
|
|
60
|
-
return crypto.createHash('sha256').update(message).digest('hex');
|
|
61
|
-
} catch (error) {
|
|
62
|
-
// Fallback to expo-crypto if Node crypto fails
|
|
63
|
-
const Crypto = await initExpoCrypto();
|
|
64
|
-
return Crypto.digestStringAsync(
|
|
65
|
-
Crypto.CryptoDigestAlgorithm.SHA256,
|
|
66
|
-
message
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface SignedMessage {
|
|
72
|
-
message: string;
|
|
73
|
-
signature: string;
|
|
74
|
-
publicKey: string;
|
|
75
|
-
timestamp: number;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface AuthChallenge {
|
|
79
|
-
challenge: string;
|
|
80
|
-
publicKey: string;
|
|
81
|
-
timestamp: number;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export class SignatureService {
|
|
85
|
-
/**
|
|
86
|
-
* Generate a random challenge string (for offline use)
|
|
87
|
-
* Uses expo-crypto in React Native, crypto.randomBytes in Node.js
|
|
88
|
-
*/
|
|
89
|
-
static async generateChallenge(): Promise<string> {
|
|
90
|
-
if (isReactNative() || !isNodeJS()) {
|
|
91
|
-
// Use expo-crypto for React Native (expo-random is deprecated)
|
|
92
|
-
const Crypto = await initExpoCrypto();
|
|
93
|
-
const randomBytes = await Crypto.getRandomBytesAsync(32);
|
|
94
|
-
return Array.from(randomBytes)
|
|
95
|
-
.map((b: number) => b.toString(16).padStart(2, '0'))
|
|
96
|
-
.join('');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Node.js fallback
|
|
100
|
-
try {
|
|
101
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
102
|
-
const getCrypto = new Function('return require("crypto")');
|
|
103
|
-
const crypto = getCrypto();
|
|
104
|
-
return crypto.randomBytes(32).toString('hex');
|
|
105
|
-
} catch (error) {
|
|
106
|
-
// Fallback to expo-crypto if Node crypto fails
|
|
107
|
-
const Crypto = await initExpoCrypto();
|
|
108
|
-
const randomBytes = await Crypto.getRandomBytesAsync(32);
|
|
109
|
-
return Array.from(randomBytes)
|
|
110
|
-
.map((b: number) => b.toString(16).padStart(2, '0'))
|
|
111
|
-
.join('');
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Hash a message using SHA-256
|
|
117
|
-
*/
|
|
118
|
-
static async hashMessage(message: string): Promise<string> {
|
|
119
|
-
return sha256(message);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Sign a message using the stored private key
|
|
124
|
-
* Returns the signature in DER format (hex encoded)
|
|
125
|
-
*/
|
|
126
|
-
static async sign(message: string): Promise<string> {
|
|
127
|
-
const keyPair = await KeyManager.getKeyPairObject();
|
|
128
|
-
if (!keyPair) {
|
|
129
|
-
throw new Error('No identity found. Please create or import an identity first.');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const messageHash = await sha256(message);
|
|
133
|
-
const signature = keyPair.sign(messageHash);
|
|
134
|
-
return signature.toDER('hex');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Sign a message with an explicit private key (without storing)
|
|
139
|
-
* Useful for one-time operations or testing
|
|
140
|
-
*/
|
|
141
|
-
static async signWithKey(message: string, privateKey: string): Promise<string> {
|
|
142
|
-
const keyPair = ec.keyFromPrivate(privateKey);
|
|
143
|
-
const messageHash = await sha256(message);
|
|
144
|
-
const signature = keyPair.sign(messageHash);
|
|
145
|
-
return signature.toDER('hex');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Verify a signature against a message and public key
|
|
150
|
-
*/
|
|
151
|
-
static async verify(message: string, signature: string, publicKey: string): Promise<boolean> {
|
|
152
|
-
try {
|
|
153
|
-
const key = ec.keyFromPublic(publicKey, 'hex');
|
|
154
|
-
const messageHash = await sha256(message);
|
|
155
|
-
return key.verify(messageHash, signature);
|
|
156
|
-
} catch {
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Synchronous verification (for Node.js backend)
|
|
163
|
-
* Uses crypto module directly for hashing
|
|
164
|
-
* Note: This method should only be used in Node.js environments
|
|
165
|
-
*/
|
|
166
|
-
static verifySync(message: string, signature: string, publicKey: string): boolean {
|
|
167
|
-
try {
|
|
168
|
-
if (!isNodeJS()) {
|
|
169
|
-
// In React Native, use async verify instead
|
|
170
|
-
throw new Error('verifySync should only be used in Node.js. Use verify() in React Native.');
|
|
171
|
-
}
|
|
172
|
-
// Use Function constructor to prevent Metro bundler from statically analyzing this require
|
|
173
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
174
|
-
const getCrypto = new Function('return require("crypto")');
|
|
175
|
-
const crypto = getCrypto();
|
|
176
|
-
const key = ec.keyFromPublic(publicKey, 'hex');
|
|
177
|
-
const messageHash = crypto.createHash('sha256').update(message).digest('hex');
|
|
178
|
-
return key.verify(messageHash, signature);
|
|
179
|
-
} catch {
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Create a signed message object with metadata
|
|
186
|
-
*/
|
|
187
|
-
static async createSignedMessage(message: string): Promise<SignedMessage> {
|
|
188
|
-
const publicKey = await KeyManager.getPublicKey();
|
|
189
|
-
if (!publicKey) {
|
|
190
|
-
throw new Error('No identity found. Please create or import an identity first.');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const timestamp = Date.now();
|
|
194
|
-
const messageWithTimestamp = `${message}:${timestamp}`;
|
|
195
|
-
const signature = await SignatureService.sign(messageWithTimestamp);
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
message,
|
|
199
|
-
signature,
|
|
200
|
-
publicKey,
|
|
201
|
-
timestamp,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Verify a signed message object
|
|
207
|
-
* Checks both signature validity and timestamp freshness
|
|
208
|
-
*/
|
|
209
|
-
static async verifySignedMessage(
|
|
210
|
-
signedMessage: SignedMessage,
|
|
211
|
-
maxAgeMs: number = 5 * 60 * 1000 // 5 minutes default
|
|
212
|
-
): Promise<boolean> {
|
|
213
|
-
const { message, signature, publicKey, timestamp } = signedMessage;
|
|
214
|
-
|
|
215
|
-
// Check timestamp freshness
|
|
216
|
-
const now = Date.now();
|
|
217
|
-
if (now - timestamp > maxAgeMs) {
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Verify signature
|
|
222
|
-
const messageWithTimestamp = `${message}:${timestamp}`;
|
|
223
|
-
return SignatureService.verify(messageWithTimestamp, signature, publicKey);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Create a signed authentication challenge response
|
|
228
|
-
* Used for challenge-response authentication
|
|
229
|
-
*/
|
|
230
|
-
static async signChallenge(challenge: string): Promise<AuthChallenge> {
|
|
231
|
-
const publicKey = await KeyManager.getPublicKey();
|
|
232
|
-
if (!publicKey) {
|
|
233
|
-
throw new Error('No identity found. Please create or import an identity first.');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const timestamp = Date.now();
|
|
237
|
-
const message = `auth:${publicKey}:${challenge}:${timestamp}`;
|
|
238
|
-
const signature = await SignatureService.sign(message);
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
challenge: signature,
|
|
242
|
-
publicKey,
|
|
243
|
-
timestamp,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Verify a challenge response
|
|
249
|
-
*/
|
|
250
|
-
static async verifyChallengeResponse(
|
|
251
|
-
originalChallenge: string,
|
|
252
|
-
response: AuthChallenge,
|
|
253
|
-
maxAgeMs: number = 5 * 60 * 1000
|
|
254
|
-
): Promise<boolean> {
|
|
255
|
-
const { challenge: signature, publicKey, timestamp } = response;
|
|
256
|
-
|
|
257
|
-
// Check timestamp freshness
|
|
258
|
-
const now = Date.now();
|
|
259
|
-
if (now - timestamp > maxAgeMs) {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const message = `auth:${publicKey}:${originalChallenge}:${timestamp}`;
|
|
264
|
-
return SignatureService.verify(message, signature, publicKey);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Sign arbitrary data for API requests
|
|
269
|
-
* Creates a canonical string representation and signs it
|
|
270
|
-
*/
|
|
271
|
-
static async signRequestData(data: Record<string, unknown>): Promise<{
|
|
272
|
-
signature: string;
|
|
273
|
-
publicKey: string;
|
|
274
|
-
timestamp: number;
|
|
275
|
-
}> {
|
|
276
|
-
const publicKey = await KeyManager.getPublicKey();
|
|
277
|
-
if (!publicKey) {
|
|
278
|
-
throw new Error('No identity found. Please create or import an identity first.');
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const timestamp = Date.now();
|
|
282
|
-
|
|
283
|
-
// Create canonical string representation
|
|
284
|
-
const sortedKeys = Object.keys(data).sort();
|
|
285
|
-
const canonicalParts = sortedKeys.map(key => `${key}:${JSON.stringify(data[key])}`);
|
|
286
|
-
const canonicalString = canonicalParts.join('|');
|
|
287
|
-
|
|
288
|
-
const message = `request:${publicKey}:${timestamp}:${canonicalString}`;
|
|
289
|
-
const signature = await SignatureService.sign(message);
|
|
290
|
-
|
|
291
|
-
return {
|
|
292
|
-
signature,
|
|
293
|
-
publicKey,
|
|
294
|
-
timestamp,
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export default SignatureService;
|
|
300
|
-
|
|
301
|
-
|