@blazium/ton-connect-mobile 1.2.5 → 1.2.6

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.
@@ -1,238 +1,62 @@
1
- /**
2
- * Cryptographic utilities for TonConnect
3
- * Uses tweetnacl for signature verification
4
- */
5
-
6
- // Type declarations for runtime globals
7
- declare const console: {
8
- warn(...args: unknown[]): void;
9
- error(...args: unknown[]): void;
10
- };
11
-
12
- declare const crypto: {
13
- getRandomValues(array: Uint8Array): Uint8Array;
14
- } | undefined;
15
-
16
- declare const require: {
17
- (id: string): any;
18
- };
19
-
20
- // eslint-disable-next-line @typescript-eslint/no-var-requires
21
- const nacl = require('tweetnacl');
22
- import { ConnectionResponsePayload } from '../types';
23
-
24
- /**
25
- * Decode base64 string to Uint8Array
26
- */
27
- function decodeBase64(base64: string): Uint8Array {
28
- // Remove padding and convert URL-safe to standard base64
29
- const cleanBase64 = base64.replace(/-/g, '+').replace(/_/g, '/');
30
- const padded = cleanBase64 + '='.repeat((4 - (cleanBase64.length % 4)) % 4);
31
-
32
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
33
- const bytes: number[] = [];
34
- let buffer = 0;
35
- let bitsCollected = 0;
36
-
37
- for (let i = 0; i < padded.length; i++) {
38
- const ch = padded[i];
39
- if (ch === '=') break;
40
-
41
- const index = chars.indexOf(ch);
42
- if (index === -1) continue;
43
-
44
- buffer = (buffer << 6) | index;
45
- bitsCollected += 6;
46
-
47
- if (bitsCollected >= 8) {
48
- bitsCollected -= 8;
49
- bytes.push((buffer >> bitsCollected) & 0xff);
50
- buffer &= (1 << bitsCollected) - 1;
51
- }
52
- }
53
-
54
- return new Uint8Array(bytes);
55
- }
56
-
57
- /**
58
- * TextEncoder type declaration
59
- */
60
- declare const TextEncoder: {
61
- new (): {
62
- encode(input: string): Uint8Array;
63
- };
64
- } | undefined;
65
-
66
- /**
67
- * Get TextEncoder with fallback
68
- */
69
- function getTextEncoder(): { encode(input: string): Uint8Array } {
70
- if (typeof TextEncoder !== 'undefined') {
71
- return new TextEncoder();
72
- }
73
- // Fallback implementation for older React Native
74
- throw new Error('TextEncoder is not available. Please use React Native 0.59+ or add a polyfill.');
75
- }
76
-
77
- /**
78
- * Verify connection proof signature
79
- * The proof is signed by the wallet to verify authenticity
80
- */
81
- export function verifyConnectionProof(
82
- response: ConnectionResponsePayload,
83
- manifestUrl: string
84
- ): boolean {
85
- // HIGH FIX: Log warning if proof is missing but allow for compatibility
86
- if (!response.proof) {
87
- console.warn('TON Connect: Connection proof missing - wallet may not support proof verification');
88
- // Allow connection for compatibility, but log warning
89
- return true;
90
- }
91
-
92
- try {
93
- const { timestamp, domain, signature } = response.proof;
94
-
95
- // Validate proof structure
96
- if (typeof timestamp !== 'number' || !domain || typeof domain.lengthBytes !== 'number' || typeof domain.value !== 'string' || typeof signature !== 'string') {
97
- return false;
98
- }
99
-
100
- // Build the message that was signed
101
- // Format: <timestamp>.<domain_length>.<domain_value>.<address>.<publicKey>
102
- const domainLength = domain.lengthBytes;
103
- const message = `${timestamp}.${domainLength}.${domain.value}.${response.address}.${response.publicKey}`;
104
-
105
- // Convert public key from hex to Uint8Array
106
- const publicKeyBytes = hexToBytes(response.publicKey);
107
- if (publicKeyBytes.length !== 32) {
108
- return false;
109
- }
110
-
111
- // Convert signature from base64 to Uint8Array
112
- const signatureBytes = decodeBase64(signature);
113
- if (signatureBytes.length !== 64) {
114
- return false;
115
- }
116
-
117
- // Verify signature using nacl
118
- const encoder = getTextEncoder();
119
- const messageBytes = encoder.encode(message);
120
- return nacl.sign.detached.verify(messageBytes, signatureBytes, publicKeyBytes);
121
- } catch (error) {
122
- // If verification fails, return false
123
- console.error('TON Connect: Proof verification error:', error);
124
- return false;
125
- }
126
- }
127
-
128
- /**
129
- * Verify transaction signature
130
- *
131
- * WARNING: This function only performs basic format validation.
132
- * Full signature verification requires parsing the BOC (Bag of Cells) and
133
- * verifying the signature against the transaction hash, which requires
134
- * TON library integration (@ton/core or @ton/crypto).
135
- *
136
- * For production use, transaction signatures should be verified server-side
137
- * using proper TON libraries.
138
- *
139
- * @returns false - Always returns false to be safe until proper implementation
140
- */
141
- export function verifyTransactionSignature(
142
- boc: string,
143
- signature: string,
144
- publicKey: string
145
- ): boolean {
146
- // CRITICAL FIX: This function does not actually verify signatures
147
- // It only checks format. For security, we return false until proper implementation.
148
-
149
- try {
150
- // Basic format validation
151
- if (!boc || typeof boc !== 'string' || boc.length === 0) {
152
- return false;
153
- }
154
- if (!signature || typeof signature !== 'string' || signature.length === 0) {
155
- return false;
156
- }
157
- if (!publicKey || typeof publicKey !== 'string' || publicKey.length === 0) {
158
- return false;
159
- }
160
-
161
- // Convert public key from hex to Uint8Array
162
- const publicKeyBytes = hexToBytes(publicKey);
163
- if (publicKeyBytes.length !== 32) {
164
- return false;
165
- }
166
-
167
- // Convert signature from base64 to Uint8Array
168
- const signatureBytes = decodeBase64(signature);
169
- if (signatureBytes.length !== 64) {
170
- return false;
171
- }
172
-
173
- // Convert BOC from base64 to Uint8Array
174
- const bocBytes = decodeBase64(boc);
175
- if (bocBytes.length === 0) {
176
- return false;
177
- }
178
-
179
- // CRITICAL: Return false - actual signature verification requires TON library
180
- // TODO: Integrate @ton/core or @ton/crypto for proper BOC parsing and signature verification
181
- console.warn('TON Connect: Transaction signature verification not fully implemented. Signature format is valid but not cryptographically verified. Verify server-side using @ton/core.');
182
- return false; // Fail-safe: reject until properly implemented
183
- } catch (error) {
184
- console.error('TON Connect: Transaction signature verification error:', error);
185
- return false;
186
- }
187
- }
188
-
189
- /**
190
- * Convert hex string to Uint8Array
191
- */
192
- function hexToBytes(hex: string): Uint8Array {
193
- // Remove 0x prefix if present
194
- const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
195
-
196
- // Handle odd-length hex strings
197
- const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex;
198
-
199
- const bytes = new Uint8Array(paddedHex.length / 2);
200
- for (let i = 0; i < paddedHex.length; i += 2) {
201
- bytes[i / 2] = parseInt(paddedHex.substr(i, 2), 16);
202
- }
203
- return bytes;
204
- }
205
-
206
- /**
207
- * Generate cryptographically secure random bytes
208
- */
209
- function getSecureRandomBytes(length: number): Uint8Array {
210
- const bytes = new Uint8Array(length);
211
-
212
- // Try to use crypto.getRandomValues (available in React Native with polyfill)
213
- // eslint-disable-next-line no-undef
214
- if (typeof globalThis !== 'undefined' && (globalThis as any).crypto && (globalThis as any).crypto.getRandomValues) {
215
- (globalThis as any).crypto.getRandomValues(bytes);
216
- return bytes;
217
- }
218
-
219
- // HIGH FIX: Throw error instead of using insecure Math.random()
220
- throw new Error(
221
- 'Cryptographically secure random number generation not available. ' +
222
- 'Please install react-native-get-random-values or use React Native 0.59+'
223
- );
224
- }
225
-
226
- /**
227
- * Generate random session ID
228
- */
229
- export function generateSessionId(): string {
230
- // HIGH FIX: Use secure random bytes
231
- const bytes = getSecureRandomBytes(32);
232
-
233
- // Convert to hex string
234
- return Array.from(bytes)
235
- .map((b) => b.toString(16).padStart(2, '0'))
236
- .join('');
237
- }
238
-
1
+ /**
2
+ * Cryptographic utilities for TonConnect
3
+ * Legacy module primary crypto is now in session.ts
4
+ * This module provides helper functions that may be used externally
5
+ */
6
+
7
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
8
+ const nacl = require('tweetnacl');
9
+
10
+ /**
11
+ * Convert hex string to Uint8Array
12
+ */
13
+ export function hexToBytes(hex: string): Uint8Array {
14
+ const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
15
+ const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex;
16
+ const bytes = new Uint8Array(paddedHex.length / 2);
17
+ for (let i = 0; i < paddedHex.length; i += 2) {
18
+ bytes[i / 2] = parseInt(paddedHex.substr(i, 2), 16);
19
+ }
20
+ return bytes;
21
+ }
22
+
23
+ /**
24
+ * Generate cryptographically secure random bytes
25
+ */
26
+ function getSecureRandomBytes(length: number): Uint8Array {
27
+ const bytes = new Uint8Array(length);
28
+ // eslint-disable-next-line no-undef
29
+ if (typeof globalThis !== 'undefined' && (globalThis as any).crypto && (globalThis as any).crypto.getRandomValues) {
30
+ (globalThis as any).crypto.getRandomValues(bytes);
31
+ return bytes;
32
+ }
33
+ throw new Error(
34
+ 'Cryptographically secure random number generation not available. ' +
35
+ 'Please install react-native-get-random-values or use React Native 0.59+'
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Generate random session ID
41
+ */
42
+ export function generateSessionId(): string {
43
+ const bytes = getSecureRandomBytes(32);
44
+ return Array.from(bytes)
45
+ .map((b) => b.toString(16).padStart(2, '0'))
46
+ .join('');
47
+ }
48
+
49
+ /**
50
+ * Verify Ed25519 signature
51
+ */
52
+ export function verifySignature(
53
+ message: Uint8Array,
54
+ signature: Uint8Array,
55
+ publicKey: Uint8Array
56
+ ): boolean {
57
+ try {
58
+ return nacl.sign.detached.verify(message, signature, publicKey);
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
package/src/core/index.ts CHANGED
@@ -1,7 +1,17 @@
1
- /**
2
- * Core protocol exports
3
- */
4
-
5
- export * from './protocol';
6
- export * from './crypto';
7
-
1
+ /**
2
+ * Core module exports
3
+ */
4
+
5
+ export { SessionCrypto } from './session';
6
+ export { BridgeGateway } from './bridge';
7
+ export {
8
+ buildConnectUniversalLink,
9
+ buildReturnUniversalLink,
10
+ buildSendTransactionRpcRequest,
11
+ buildDisconnectRpcRequest,
12
+ parseConnectResponse,
13
+ parseRpcResponse,
14
+ extractWalletInfoFromEvent,
15
+ validateTransactionRequest,
16
+ } from './protocol';
17
+ export { SUPPORTED_WALLETS, getWalletByName, getDefaultWallet, getWalletsForPlatform } from './wallets';