@bsv/wallet-toolbox 1.6.36 → 1.6.38

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/wallet-toolbox",
3
- "version": "1.6.36",
3
+ "version": "1.6.38",
4
4
  "description": "BRC100 conforming wallet, wallet storage and wallet signer components",
5
5
  "main": "./out/src/index.js",
6
6
  "types": "./out/src/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@bsv/auth-express-middleware": "^1.2.3",
35
35
  "@bsv/payment-express-middleware": "^1.2.3",
36
- "@bsv/sdk": "^1.8.6",
36
+ "@bsv/sdk": "^1.8.10",
37
37
  "express": "^4.21.2",
38
38
  "idb": "^8.0.2",
39
39
  "knex": "^3.1.0",
@@ -0,0 +1,22 @@
1
+ import { Utils } from '@bsv/sdk'
2
+ import { validateBase64String } from '../validationHelpers'
3
+ describe('validationHelpers tests', () => {
4
+ jest.setTimeout(99999999)
5
+
6
+ test('0 validateBase64String', async () => {
7
+ const validB64 = 'SGVsbG8gV29ybGQh' // "Hello World!"
8
+
9
+ const s = validateBase64String(validB64, 'testParam', 1, 20)
10
+ expect(s).toBe(validB64)
11
+
12
+ {
13
+ const invalidB64 = 'SGVsbG8g29ybGQh'
14
+ expect(() => validateBase64String(invalidB64, 'testParam', 1, 20)).toThrow()
15
+ }
16
+
17
+ {
18
+ const invalidB64 = 'SGVsbG8gV29ybGQh='
19
+ expect(() => validateBase64String(invalidB64, 'testParam', 1, 20)).toThrow()
20
+ }
21
+ })
22
+ })
@@ -165,20 +165,67 @@ function validateOptionalBase64String(
165
165
  return validateBase64String(s, name, min, max)
166
166
  }
167
167
 
168
- function validateBase64String(s: string, name: string, min?: number, max?: number): string {
169
- // Remove any whitespace and check if the string length is valid for Base64
168
+ /**
169
+ * Validate a Base64 string (structure and decoded size).
170
+ *
171
+ * @param s - base64 string
172
+ * @param name - parameter name used in error messages
173
+ * @param min - optional minimum decoded byte length
174
+ * @param max - optional maximum decoded byte length
175
+ * @returns validated base64 string
176
+ * @throws WERR_INVALID_PARAMETER when invalid
177
+ */
178
+ export function validateBase64String(s: string, name: string, min?: number, max?: number): string {
170
179
  s = s.trim()
171
- const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
172
- const paddingMatch = /=+$/.exec(s)
173
- const paddingCount = paddingMatch ? paddingMatch[0].length : 0
180
+ if (s.length === 0) {
181
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
182
+ }
174
183
 
175
- if (paddingCount > 2 || (s.length % 4 !== 0 && paddingCount !== 0) || !base64Regex.test(s)) {
176
- throw new WERR_INVALID_PARAMETER(name, `balid base64 string`)
184
+ let paddingCount = 0
185
+ let validCharCount = 0
186
+
187
+ for (let i = 0; i < s.length; i++) {
188
+ const char = s.charCodeAt(i)
189
+ if (char >= 65 && char <= 90) continue // A-Z
190
+ if (char >= 97 && char <= 122) continue // a-z
191
+ if (char >= 48 && char <= 57) continue // 0-9
192
+ if (char === 43) continue // +
193
+ if (char === 47) continue // /
194
+ if (char === 61) {
195
+ // =
196
+ if (i < s.length - 2) {
197
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
198
+ }
199
+ paddingCount++
200
+ continue
201
+ }
202
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
177
203
  }
178
204
 
179
- const bytes = Utils.toArray(s, 'base64').length
180
- if (min !== undefined && bytes < min) throw new WERR_INVALID_PARAMETER(name, `at least ${min} length.`)
181
- if (max !== undefined && bytes > max) throw new WERR_INVALID_PARAMETER(name, `no more than ${max} length.`)
205
+ // Padding rules
206
+ if (paddingCount > 2) {
207
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
208
+ }
209
+ if (paddingCount > 0 && s.length % 4 !== 0) {
210
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
211
+ }
212
+
213
+ // Length must be multiple of 4 if no padding, or valid with padding
214
+ const mod = s.length % 4
215
+ if (mod !== 0 && mod !== 4 - paddingCount) {
216
+ throw new WERR_INVALID_PARAMETER(name, 'valid base64 string')
217
+ }
218
+
219
+ // Calculate decoded byte length: (valid chars * 6) / 8
220
+ const encodedLength = s.length - paddingCount
221
+ const bytes = Math.floor((encodedLength * 3) / 4)
222
+
223
+ if (min !== undefined && bytes < min) {
224
+ throw new WERR_INVALID_PARAMETER(name, `at least ${min} bytes`)
225
+ }
226
+ if (max !== undefined && bytes > max) {
227
+ throw new WERR_INVALID_PARAMETER(name, `no more than ${max} bytes`)
228
+ }
182
229
 
183
230
  return s
184
231
  }
@@ -513,6 +560,7 @@ export function validateOriginator(s?: string): string | undefined {
513
560
  for (const sp of sps) {
514
561
  validateStringLength(sp, 'originator part', 1, 63)
515
562
  }
563
+ return s
516
564
  }
517
565
 
518
566
  export function validateInternalizeActionArgs(args: InternalizeActionArgs): ValidInternalizeActionArgs {