@oxyhq/services 5.17.8 → 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.
Files changed (91) hide show
  1. package/lib/commonjs/crypto/index.js +0 -23
  2. package/lib/commonjs/crypto/index.js.map +1 -1
  3. package/lib/commonjs/index.js +0 -15
  4. package/lib/commonjs/index.js.map +1 -1
  5. package/lib/commonjs/ui/components/Icon.js.map +1 -1
  6. package/lib/commonjs/ui/components/IconButton/utils.js.map +1 -1
  7. package/lib/commonjs/ui/components/TextField/Adornment/utils.js.map +1 -1
  8. package/lib/commonjs/ui/components/TextField/helpers.js.map +1 -1
  9. package/lib/commonjs/ui/components/TouchableRipple/utils.js.map +1 -1
  10. package/lib/commonjs/ui/components/Typography/AnimatedText.js.map +1 -1
  11. package/lib/commonjs/ui/context/OxyContext.js +23 -15
  12. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  13. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +63 -111
  14. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  15. package/lib/commonjs/ui/screens/OxyAuthScreen.js +0 -1
  16. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  17. package/lib/commonjs/ui/stores/authStore.js +52 -15
  18. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  19. package/lib/commonjs/ui/utils/avatarUtils.js +2 -32
  20. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  21. package/lib/module/crypto/index.js +4 -6
  22. package/lib/module/crypto/index.js.map +1 -1
  23. package/lib/module/index.js +6 -3
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/module/ui/components/Icon.js.map +1 -1
  26. package/lib/module/ui/components/IconButton/utils.js.map +1 -1
  27. package/lib/module/ui/components/TextField/Adornment/utils.js.map +1 -1
  28. package/lib/module/ui/components/TextField/helpers.js.map +1 -1
  29. package/lib/module/ui/components/TouchableRipple/utils.js.map +1 -1
  30. package/lib/module/ui/components/Typography/AnimatedText.js.map +1 -1
  31. package/lib/module/ui/context/OxyContext.js +23 -15
  32. package/lib/module/ui/context/OxyContext.js.map +1 -1
  33. package/lib/module/ui/context/hooks/useAuthOperations.js +63 -111
  34. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  35. package/lib/module/ui/screens/OxyAuthScreen.js +0 -1
  36. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  37. package/lib/module/ui/stores/authStore.js +52 -15
  38. package/lib/module/ui/stores/authStore.js.map +1 -1
  39. package/lib/module/ui/utils/avatarUtils.js +2 -32
  40. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  41. package/lib/typescript/crypto/index.d.ts +2 -5
  42. package/lib/typescript/crypto/index.d.ts.map +1 -1
  43. package/lib/typescript/crypto/types.d.ts +2 -2
  44. package/lib/typescript/index.d.ts +4 -2
  45. package/lib/typescript/index.d.ts.map +1 -1
  46. package/lib/typescript/ui/components/IconButton/utils.d.ts +1 -1
  47. package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts +1 -1
  48. package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
  49. package/lib/typescript/ui/components/TextField/helpers.d.ts +6 -6
  50. package/lib/typescript/ui/components/types.d.ts +0 -4
  51. package/lib/typescript/ui/components/types.d.ts.map +1 -1
  52. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  53. package/lib/typescript/ui/context/OxyContextBase.d.ts +2 -2
  54. package/lib/typescript/ui/context/OxyContextBase.d.ts.map +1 -1
  55. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +9 -5
  56. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  57. package/lib/typescript/ui/stores/authStore.d.ts +27 -4
  58. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  59. package/lib/typescript/ui/utils/avatarUtils.d.ts +0 -2
  60. package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
  61. package/package.json +2 -2
  62. package/src/crypto/index.ts +3 -11
  63. package/src/crypto/types.ts +2 -2
  64. package/src/index.ts +6 -11
  65. package/src/ui/components/Icon.tsx +1 -1
  66. package/src/ui/components/IconButton/utils.ts +1 -1
  67. package/src/ui/components/TextField/Adornment/utils.ts +2 -2
  68. package/src/ui/components/TextField/helpers.tsx +8 -8
  69. package/src/ui/components/TouchableRipple/utils.ts +2 -2
  70. package/src/ui/components/Typography/AnimatedText.tsx +2 -2
  71. package/src/ui/components/types.tsx +0 -6
  72. package/src/ui/context/OxyContext.tsx +23 -14
  73. package/src/ui/context/OxyContextBase.tsx +4 -4
  74. package/src/ui/context/hooks/useAuthOperations.ts +83 -134
  75. package/src/ui/screens/OxyAuthScreen.tsx +1 -1
  76. package/src/ui/stores/authStore.ts +57 -18
  77. package/src/ui/utils/avatarUtils.ts +4 -36
  78. package/lib/commonjs/crypto/keyManager.js +0 -356
  79. package/lib/commonjs/crypto/keyManager.js.map +0 -1
  80. package/lib/commonjs/crypto/signatureService.js +0 -269
  81. package/lib/commonjs/crypto/signatureService.js.map +0 -1
  82. package/lib/module/crypto/keyManager.js +0 -353
  83. package/lib/module/crypto/keyManager.js.map +0 -1
  84. package/lib/module/crypto/signatureService.js +0 -266
  85. package/lib/module/crypto/signatureService.js.map +0 -1
  86. package/lib/typescript/crypto/keyManager.d.ts +0 -80
  87. package/lib/typescript/crypto/keyManager.d.ts.map +0 -1
  88. package/lib/typescript/crypto/signatureService.d.ts +0 -77
  89. package/lib/typescript/crypto/signatureService.d.ts.map +0 -1
  90. package/src/crypto/keyManager.ts +0 -379
  91. package/src/crypto/signatureService.ts +0 -301
@@ -1,80 +0,0 @@
1
- /**
2
- * Key Manager - ECDSA secp256k1 Key Generation and Storage
3
- *
4
- * Handles secure generation, storage, and retrieval of cryptographic keys.
5
- * Private keys are stored securely using expo-secure-store and never leave the device.
6
- */
7
- import type { ECKeyPair } from 'elliptic';
8
- export interface KeyPair {
9
- publicKey: string;
10
- privateKey: string;
11
- }
12
- export declare class KeyManager {
13
- /**
14
- * Generate a new ECDSA secp256k1 key pair
15
- * Returns the keys in hexadecimal format
16
- */
17
- static generateKeyPairSync(): KeyPair;
18
- /**
19
- * Generate a new key pair using secure random bytes
20
- */
21
- static generateKeyPair(): Promise<KeyPair>;
22
- /**
23
- * Generate and securely store a new key pair on the device
24
- * Returns only the public key (private key is stored securely)
25
- */
26
- static createIdentity(): Promise<string>;
27
- /**
28
- * Import an existing key pair (e.g., from backup file)
29
- */
30
- static importKeyPair(privateKey: string): Promise<string>;
31
- /**
32
- * Get the stored private key
33
- * WARNING: Only use this for signing operations within the app
34
- */
35
- static getPrivateKey(): Promise<string | null>;
36
- /**
37
- * Get the stored public key
38
- */
39
- static getPublicKey(): Promise<string | null>;
40
- /**
41
- * Check if an identity (key pair) exists on this device
42
- */
43
- static hasIdentity(): Promise<boolean>;
44
- /**
45
- * Delete the stored identity (both keys)
46
- * Use with EXTREME caution - this is irreversible without a backup file
47
- * This should ONLY be called when explicitly requested by the user
48
- * @param force - If true, skip confirmation checks (default: false)
49
- * @param userConfirmed - If true, user has explicitly confirmed deletion (default: false)
50
- */
51
- static deleteIdentity(force?: boolean, userConfirmed?: boolean): Promise<void>;
52
- /**
53
- * Verify identity integrity - checks if keys are valid and accessible
54
- */
55
- static verifyIdentityIntegrity(): Promise<boolean>;
56
- /**
57
- * Get the elliptic curve key object from the stored private key
58
- * Used internally for signing operations
59
- */
60
- static getKeyPairObject(): Promise<ECKeyPair | null>;
61
- /**
62
- * Derive public key from a private key (without storing)
63
- */
64
- static derivePublicKey(privateKey: string): string;
65
- /**
66
- * Validate that a string is a valid public key
67
- */
68
- static isValidPublicKey(publicKey: string): boolean;
69
- /**
70
- * Validate that a string is a valid private key
71
- */
72
- static isValidPrivateKey(privateKey: string): boolean;
73
- /**
74
- * Get a shortened version of the public key for display
75
- * Format: first 8 chars...last 8 chars
76
- */
77
- static shortenPublicKey(publicKey: string): string;
78
- }
79
- export default KeyManager;
80
- //# sourceMappingURL=keyManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"keyManager.d.ts","sourceRoot":"","sources":["../../../src/crypto/keyManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAsG1C,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;IAErB;;;OAGG;IACH,MAAM,CAAC,mBAAmB,IAAI,OAAO;IAQrC;;OAEG;WACU,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWhD;;;OAGG;WACU,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAgB9C;;OAEG;WACU,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB/D;;;OAGG;WACU,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiBpD;;OAEG;WACU,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBnD;;OAEG;WACU,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB5C;;;;;;OAMG;WACU,cAAc,CACzB,KAAK,GAAE,OAAe,EACtB,aAAa,GAAE,OAAe,GAC7B,OAAO,CAAC,IAAI,CAAC;IAqBhB;;OAEG;WACU,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC;IA2CxD;;;OAGG;WACU,gBAAgB,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAS1D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAKlD;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IASnD;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAWrD;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAInD;AAED,eAAe,UAAU,CAAC"}
@@ -1,77 +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
- export interface SignedMessage {
8
- message: string;
9
- signature: string;
10
- publicKey: string;
11
- timestamp: number;
12
- }
13
- export interface AuthChallenge {
14
- challenge: string;
15
- publicKey: string;
16
- timestamp: number;
17
- }
18
- export declare class SignatureService {
19
- /**
20
- * Generate a random challenge string (for offline use)
21
- * Uses expo-crypto in React Native, crypto.randomBytes in Node.js
22
- */
23
- static generateChallenge(): Promise<string>;
24
- /**
25
- * Hash a message using SHA-256
26
- */
27
- static hashMessage(message: string): Promise<string>;
28
- /**
29
- * Sign a message using the stored private key
30
- * Returns the signature in DER format (hex encoded)
31
- */
32
- static sign(message: string): Promise<string>;
33
- /**
34
- * Sign a message with an explicit private key (without storing)
35
- * Useful for one-time operations or testing
36
- */
37
- static signWithKey(message: string, privateKey: string): Promise<string>;
38
- /**
39
- * Verify a signature against a message and public key
40
- */
41
- static verify(message: string, signature: string, publicKey: string): Promise<boolean>;
42
- /**
43
- * Synchronous verification (for Node.js backend)
44
- * Uses crypto module directly for hashing
45
- * Note: This method should only be used in Node.js environments
46
- */
47
- static verifySync(message: string, signature: string, publicKey: string): boolean;
48
- /**
49
- * Create a signed message object with metadata
50
- */
51
- static createSignedMessage(message: string): Promise<SignedMessage>;
52
- /**
53
- * Verify a signed message object
54
- * Checks both signature validity and timestamp freshness
55
- */
56
- static verifySignedMessage(signedMessage: SignedMessage, maxAgeMs?: number): Promise<boolean>;
57
- /**
58
- * Create a signed authentication challenge response
59
- * Used for challenge-response authentication
60
- */
61
- static signChallenge(challenge: string): Promise<AuthChallenge>;
62
- /**
63
- * Verify a challenge response
64
- */
65
- static verifyChallengeResponse(originalChallenge: string, response: AuthChallenge, maxAgeMs?: number): Promise<boolean>;
66
- /**
67
- * Sign arbitrary data for API requests
68
- * Creates a canonical string representation and signs it
69
- */
70
- static signRequestData(data: Record<string, unknown>): Promise<{
71
- signature: string;
72
- publicKey: string;
73
- timestamp: number;
74
- }>;
75
- }
76
- export default SignatureService;
77
- //# sourceMappingURL=signatureService.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"signatureService.d.ts","sourceRoot":"","sources":["../../../src/crypto/signatureService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiEH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,gBAAgB;IAC3B;;;OAGG;WACU,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IA0BjD;;OAEG;WACU,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI1D;;;OAGG;WACU,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWnD;;;OAGG;WACU,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO9E;;OAEG;WACU,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5F;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAkBjF;;OAEG;WACU,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkBzE;;;OAGG;WACU,mBAAmB,CAC9B,aAAa,EAAE,aAAa,EAC5B,QAAQ,GAAE,MAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC;IAcnB;;;OAGG;WACU,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAiBrE;;OAEG;WACU,uBAAuB,CAClC,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,aAAa,EACvB,QAAQ,GAAE,MAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC;IAanB;;;OAGG;WACU,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QACnE,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CAsBH;AAED,eAAe,gBAAgB,CAAC"}
@@ -1,379 +0,0 @@
1
- /**
2
- * Key Manager - ECDSA secp256k1 Key Generation and Storage
3
- *
4
- * Handles secure generation, storage, and retrieval of cryptographic keys.
5
- * Private keys are stored securely using expo-secure-store and never leave the device.
6
- */
7
-
8
- import { ec as EC } from 'elliptic';
9
- import type { ECKeyPair } from 'elliptic';
10
- import { Platform } from 'react-native';
11
-
12
- // Lazy imports for React Native specific modules
13
- let SecureStore: typeof import('expo-secure-store') | null = null;
14
- let ExpoCrypto: typeof import('expo-crypto') | null = null;
15
-
16
- const ec = new EC('secp256k1');
17
-
18
- const STORAGE_KEYS = {
19
- PRIVATE_KEY: 'oxy_identity_private_key',
20
- PUBLIC_KEY: 'oxy_identity_public_key',
21
- } as const;
22
-
23
- /**
24
- * Initialize React Native specific modules
25
- * This allows the module to work in both Node.js and React Native environments
26
- */
27
- async function initSecureStore(): Promise<typeof import('expo-secure-store')> {
28
- if (!SecureStore) {
29
- try {
30
- SecureStore = await import('expo-secure-store');
31
- } catch (error) {
32
- const errorMessage = error instanceof Error ? error.message : String(error);
33
- throw new Error(`Failed to load expo-secure-store: ${errorMessage}. Make sure expo-secure-store is installed and properly configured.`);
34
- }
35
- }
36
- if (!SecureStore) {
37
- throw new Error('expo-secure-store module is not available');
38
- }
39
- return SecureStore;
40
- }
41
-
42
- /**
43
- * Check if we're in a React Native environment
44
- */
45
- function isReactNative(): boolean {
46
- return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
47
- }
48
-
49
- /**
50
- * Check if we're in a Node.js environment
51
- */
52
- function isNodeJS(): boolean {
53
- return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
54
- }
55
-
56
- /**
57
- * Check if we're on web platform
58
- * Identity storage is only available on native platforms (iOS/Android)
59
- */
60
- function isWebPlatform(): boolean {
61
- try {
62
- return Platform.OS === 'web';
63
- } catch {
64
- // Fallback if Platform is not available
65
- return typeof window !== 'undefined' && typeof navigator !== 'undefined' && navigator.product !== 'ReactNative';
66
- }
67
- }
68
-
69
- async function initExpoCrypto(): Promise<typeof import('expo-crypto')> {
70
- if (!ExpoCrypto) {
71
- ExpoCrypto = await import('expo-crypto');
72
- }
73
- return ExpoCrypto;
74
- }
75
-
76
- /**
77
- * Convert Uint8Array to hexadecimal string
78
- * Works in both Node.js and React Native
79
- */
80
- function uint8ArrayToHex(bytes: Uint8Array): string {
81
- return Array.from(bytes)
82
- .map(b => b.toString(16).padStart(2, '0'))
83
- .join('');
84
- }
85
-
86
- /**
87
- * Generate cryptographically secure random bytes
88
- */
89
- async function getSecureRandomBytes(length: number): Promise<Uint8Array> {
90
- // In React Native, always use expo-crypto
91
- if (isReactNative() || !isNodeJS()) {
92
- const Crypto = await initExpoCrypto();
93
- return Crypto.getRandomBytes(length);
94
- }
95
-
96
- // In Node.js, use Node's crypto module
97
- // Use Function constructor to prevent Metro bundler from statically analyzing this require
98
- // This ensures the require is only evaluated in Node.js runtime, not during Metro bundling
99
- try {
100
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
101
- const getCrypto = new Function('return require("crypto")');
102
- const crypto = getCrypto();
103
- return new Uint8Array(crypto.randomBytes(length));
104
- } catch (error) {
105
- // Fallback to expo-crypto if Node crypto fails
106
- const Crypto = await initExpoCrypto();
107
- return Crypto.getRandomBytes(length);
108
- }
109
- }
110
-
111
- export interface KeyPair {
112
- publicKey: string;
113
- privateKey: string;
114
- }
115
-
116
- export class KeyManager {
117
-
118
- /**
119
- * Generate a new ECDSA secp256k1 key pair
120
- * Returns the keys in hexadecimal format
121
- */
122
- static generateKeyPairSync(): KeyPair {
123
- const keyPair = ec.genKeyPair();
124
- return {
125
- privateKey: keyPair.getPrivate('hex'),
126
- publicKey: keyPair.getPublic('hex'),
127
- };
128
- }
129
-
130
- /**
131
- * Generate a new key pair using secure random bytes
132
- */
133
- static async generateKeyPair(): Promise<KeyPair> {
134
- const randomBytes = await getSecureRandomBytes(32);
135
- const privateKeyHex = uint8ArrayToHex(randomBytes);
136
- const keyPair = ec.keyFromPrivate(privateKeyHex);
137
-
138
- return {
139
- privateKey: keyPair.getPrivate('hex'),
140
- publicKey: keyPair.getPublic('hex'),
141
- };
142
- }
143
-
144
- /**
145
- * Generate and securely store a new key pair on the device
146
- * Returns only the public key (private key is stored securely)
147
- */
148
- static async createIdentity(): Promise<string> {
149
- if (isWebPlatform()) {
150
- throw new Error('Identity creation is only available on native platforms (iOS/Android). Please use the native app to create your identity.');
151
- }
152
- const store = await initSecureStore();
153
- const { privateKey, publicKey } = await KeyManager.generateKeyPair();
154
-
155
- await store.setItemAsync(STORAGE_KEYS.PRIVATE_KEY, privateKey, {
156
- keychainAccessible: store.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
157
- });
158
-
159
- await store.setItemAsync(STORAGE_KEYS.PUBLIC_KEY, publicKey);
160
-
161
- return publicKey;
162
- }
163
-
164
- /**
165
- * Import an existing key pair (e.g., from backup file)
166
- */
167
- static async importKeyPair(privateKey: string): Promise<string> {
168
- if (isWebPlatform()) {
169
- throw new Error('Identity import is only available on native platforms (iOS/Android). Please use the native app to import your identity.');
170
- }
171
- const store = await initSecureStore();
172
-
173
- const keyPair = ec.keyFromPrivate(privateKey);
174
- const publicKey = keyPair.getPublic('hex');
175
-
176
- await store.setItemAsync(STORAGE_KEYS.PRIVATE_KEY, privateKey, {
177
- keychainAccessible: store.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
178
- });
179
- await store.setItemAsync(STORAGE_KEYS.PUBLIC_KEY, publicKey);
180
-
181
- return publicKey;
182
- }
183
-
184
- /**
185
- * Get the stored private key
186
- * WARNING: Only use this for signing operations within the app
187
- */
188
- static async getPrivateKey(): Promise<string | null> {
189
- if (isWebPlatform()) {
190
- return null; // Identity storage is only available on native platforms
191
- }
192
- try {
193
- const store = await initSecureStore();
194
- return await store.getItemAsync(STORAGE_KEYS.PRIVATE_KEY);
195
- } catch (error) {
196
- // If secure store is not available, return null (no identity)
197
- // This allows the app to continue functioning even if secure store fails to load
198
- if (__DEV__) {
199
- console.warn('[KeyManager] Failed to access secure store:', error);
200
- }
201
- return null;
202
- }
203
- }
204
-
205
- /**
206
- * Get the stored public key
207
- */
208
- static async getPublicKey(): Promise<string | null> {
209
- if (isWebPlatform()) {
210
- return null; // Identity storage is only available on native platforms
211
- }
212
-
213
- try {
214
- const store = await initSecureStore();
215
- return await store.getItemAsync(STORAGE_KEYS.PUBLIC_KEY);
216
- } catch (error) {
217
- if (__DEV__) {
218
- console.warn('[KeyManager] Failed to access secure store:', error);
219
- }
220
- return null;
221
- }
222
- }
223
-
224
- /**
225
- * Check if an identity (key pair) exists on this device
226
- */
227
- static async hasIdentity(): Promise<boolean> {
228
- if (isWebPlatform()) {
229
- return false; // Identity storage is only available on native platforms
230
- }
231
-
232
- try {
233
- const privateKey = await KeyManager.getPrivateKey();
234
- return privateKey !== null;
235
- } catch (error) {
236
- if (__DEV__) {
237
- console.warn('[KeyManager] Failed to check identity:', error);
238
- }
239
- return false;
240
- }
241
- }
242
-
243
- /**
244
- * Delete the stored identity (both keys)
245
- * Use with EXTREME caution - this is irreversible without a backup file
246
- * This should ONLY be called when explicitly requested by the user
247
- * @param force - If true, skip confirmation checks (default: false)
248
- * @param userConfirmed - If true, user has explicitly confirmed deletion (default: false)
249
- */
250
- static async deleteIdentity(
251
- force: boolean = false,
252
- userConfirmed: boolean = false
253
- ): Promise<void> {
254
- if (isWebPlatform()) {
255
- return; // Identity storage is only available on native platforms, nothing to delete
256
- }
257
- // CRITICAL SAFEGUARD: Require explicit user confirmation unless force is true
258
- if (!force && !userConfirmed) {
259
- throw new Error('Identity deletion requires explicit user confirmation. This is a safety measure to prevent accidental data loss.');
260
- }
261
-
262
- if (!force) {
263
- const hasIdentity = await KeyManager.hasIdentity();
264
- if (!hasIdentity) {
265
- return; // Nothing to delete
266
- }
267
- }
268
-
269
- const store = await initSecureStore();
270
- await store.deleteItemAsync(STORAGE_KEYS.PRIVATE_KEY);
271
- await store.deleteItemAsync(STORAGE_KEYS.PUBLIC_KEY);
272
- }
273
-
274
- /**
275
- * Verify identity integrity - checks if keys are valid and accessible
276
- */
277
- static async verifyIdentityIntegrity(): Promise<boolean> {
278
- if (isWebPlatform()) {
279
- return false; // Identity storage is only available on native platforms
280
- }
281
- try {
282
- const privateKey = await KeyManager.getPrivateKey();
283
- const publicKey = await KeyManager.getPublicKey();
284
-
285
- if (!privateKey || !publicKey) {
286
- return false;
287
- }
288
-
289
- // Validate private key format
290
- if (!KeyManager.isValidPrivateKey(privateKey)) {
291
- return false;
292
- }
293
-
294
- // Validate public key format
295
- if (!KeyManager.isValidPublicKey(publicKey)) {
296
- return false;
297
- }
298
-
299
- // Verify public key can be derived from private key
300
- const derivedPublicKey = KeyManager.derivePublicKey(privateKey);
301
- if (derivedPublicKey !== publicKey) {
302
- return false; // Keys don't match
303
- }
304
-
305
- // Verify we can create a key pair object (tests elliptic curve operations)
306
- const keyPair = await KeyManager.getKeyPairObject();
307
- if (!keyPair) {
308
- return false;
309
- }
310
-
311
- return true;
312
- } catch (error) {
313
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
314
- console.error('[KeyManager] Identity integrity check failed:', error);
315
- }
316
- return false;
317
- }
318
- }
319
-
320
- /**
321
- * Get the elliptic curve key object from the stored private key
322
- * Used internally for signing operations
323
- */
324
- static async getKeyPairObject(): Promise<ECKeyPair | null> {
325
- if (isWebPlatform()) {
326
- return null; // Identity storage is only available on native platforms
327
- }
328
- const privateKey = await KeyManager.getPrivateKey();
329
- if (!privateKey) return null;
330
- return ec.keyFromPrivate(privateKey);
331
- }
332
-
333
- /**
334
- * Derive public key from a private key (without storing)
335
- */
336
- static derivePublicKey(privateKey: string): string {
337
- const keyPair = ec.keyFromPrivate(privateKey);
338
- return keyPair.getPublic('hex');
339
- }
340
-
341
- /**
342
- * Validate that a string is a valid public key
343
- */
344
- static isValidPublicKey(publicKey: string): boolean {
345
- try {
346
- ec.keyFromPublic(publicKey, 'hex');
347
- return true;
348
- } catch {
349
- return false;
350
- }
351
- }
352
-
353
- /**
354
- * Validate that a string is a valid private key
355
- */
356
- static isValidPrivateKey(privateKey: string): boolean {
357
- try {
358
- const keyPair = ec.keyFromPrivate(privateKey);
359
- // Verify it can derive a public key
360
- keyPair.getPublic('hex');
361
- return true;
362
- } catch {
363
- return false;
364
- }
365
- }
366
-
367
- /**
368
- * Get a shortened version of the public key for display
369
- * Format: first 8 chars...last 8 chars
370
- */
371
- static shortenPublicKey(publicKey: string): string {
372
- if (publicKey.length <= 20) return publicKey;
373
- return `${publicKey.slice(0, 8)}...${publicKey.slice(-8)}`;
374
- }
375
- }
376
-
377
- export default KeyManager;
378
-
379
-