OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet commits / 0d992ce

Add comprehensive test plan for Phase 2 security hardening
- 9 test categories covering all Phase 2 features - 50+ individual test cases with expected outcomes - Integration tests for complete workflows - Performance benchmarks - Security audit checklist - Regression tests for compatibility - Automated test scripts included Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
0d992ceb5c5aeeff0c1fc11b24ecce038ce1a3a4
by plankatron <fleeky@gmail.com> · 2026-01-27T19:57:59.000Z

Changed files (1) +1410 -0

.claude/PHASE2_TEST_PLAN.md +1410 -0
……@@ -0,0 +1,1410 @@
1# Phase 2 Security Hardening: Comprehensive Test Plan
2
3**Version**: 11436
4**Date**: 2026-01-27
5**Status**: Ready for Testing
6**Branch**: feature/codebase-clarity-security-validation
7
8---
9
10## Overview
11
12This document provides a comprehensive test plan for validating all Phase 2 security enhancements:
13- ✅ Phase 2.1: API Authentication
14- ✅ Phase 2.2: Mnemonic Encryption
15- ✅ Phase 2.3: Secure Device Pairing
16- ✅ Phase 2.4: Rate Limiting
17- ✅ Phase 2.5: CORS Restrictions
18- ✅ Phase 2.6: Input Validation
19
20---
21
22## Testing Environment Setup
23
24### 1. Start Testing Environment
25
26```bash
27cd /storage/projects/code/hypercore-kb/hyper-fleeky/hyper-wallet
28
29# Start test environment
30./scripts/pear-test.sh
31
32# Verify tmux session
33tmux list-windows -t pear-dev
34
35# Expected windows:
36# - hw-web: Web server on port 4004
37# - hw-cli: CLI testing
38# - hw-logs: Log monitoring
39```
40
41### 2. Clear Previous Data (Fresh Start)
42
43```bash
44# CAUTION: This deletes all wallet data!
45rm -rf ~/.hyper-wallet/
46rm -rf ~/.config/pear/app-storage/*
47
48# Verify clean slate
49ls ~/.hyper-wallet/ 2>&1 | grep "No such file" # Should see error
50```
51
52### 3. Access Web UI
53
54Open browser: http://localhost:4004
55
56---
57
58## Phase 2.1: API Authentication Tests
59
60### Test 1.1: Unauthenticated Request (FAIL)
61
62**Expected**: 401 Unauthorized
63
64```bash
65# Test without Bearer token
66curl -X GET http://localhost:4004/api/balance/bitcoin
67
68# Expected output:
69# {"error":"Unauthorized - Valid Bearer token required"}
70# HTTP 401
71```
72
73**✅ Pass Criteria**: 401 response with error message
74
75---
76
77### Test 1.2: Token Generation on Init (SUCCESS)
78
79**Steps**:
801. Open http://localhost:4004
812. Click "Create New Wallet"
823. Enter password (min 8 characters)
834. Confirm password
845. Click "Generate Wallet"
85
86**Expected**:
87- 24-word identity mnemonic displayed
88- 12-word wallet mnemonic displayed
89- API token displayed (64 hex characters)
90- Warning about saving mnemonics
91
92**✅ Pass Criteria**:
93- Token is 64 characters (32 bytes hex-encoded)
94- Token is saved to `~/.hyper-wallet/.api-token`
95- File mode is 0600 (read/write owner only)
96
97**Verification**:
98```bash
99ls -la ~/.hyper-wallet/.api-token
100# Expected: -rw------- (mode 600)
101
102cat ~/.hyper-wallet/.api-token
103# Expected: 64 hex characters
104```
105
106---
107
108### Test 1.3: Authenticated Request (SUCCESS)
109
110**Steps**:
1111. Copy API token from init screen
1122. Test API call with token:
113
114```bash
115TOKEN=$(cat ~/.hyper-wallet/.api-token)
116
117curl -X GET http://localhost:4004/api/balance/bitcoin \
118 -H "Authorization: Bearer $TOKEN"
119
120# Expected output:
121# {"balance":"0","chain":"bitcoin","network":"testnet"}
122```
123
124**✅ Pass Criteria**: 200 response with balance data
125
126---
127
128### Test 1.4: Invalid Token (FAIL)
129
130```bash
131curl -X GET http://localhost:4004/api/balance/bitcoin \
132 -H "Authorization: Bearer invalid_token_123"
133
134# Expected output:
135# {"error":"Unauthorized - Valid Bearer token required"}
136# HTTP 401
137```
138
139**✅ Pass Criteria**: 401 response
140
141---
142
143### Test 1.5: Token Persistence Across Server Restarts
144
145**Steps**:
1461. Note current token: `cat ~/.hyper-wallet/.api-token`
1472. Restart server (Ctrl+C in tmux, restart with `pear run pear://... web 4004`)
1483. Verify token unchanged: `cat ~/.hyper-wallet/.api-token`
1494. Test API with same token
150
151**✅ Pass Criteria**: Token remains valid after restart
152
153---
154
155## Phase 2.2: Mnemonic Encryption Tests
156
157### Test 2.1: Password-Based Encryption (SUCCESS)
158
159**Steps**:
1601. Create new wallet with password "TestPass123"
1612. Check mnemonic file:
162
163```bash
164cat ~/.hyper-wallet/.mnemonic
165
166# Expected: Base64-encoded encrypted data (NOT plaintext words)
167# Should see: "aBcDeFg..." (base64), NOT "word1 word2 word3..."
168```
169
170**✅ Pass Criteria**: File contains encrypted data (base64), not plaintext
171
172---
173
174### Test 2.2: Password Caching (SUCCESS)
175
176**Steps**:
1771. Initialize wallet with password
1782. Navigate to "Send" tab (no password prompt)
1793. Try to send transaction (no password prompt)
1804. Check balance (no password prompt)
181
182**Expected**: All operations work without re-entering password (cached in memory)
183
184**✅ Pass Criteria**: No password prompts after init until server restart
185
186---
187
188### Test 2.3: Password Required on Export (SUCCESS)
189
190**Steps**:
1911. Click "Export Identity Mnemonic"
1922. Enter password in prompt
1933. Click OK
194
195**Expected**: Mnemonic displayed if password correct
196
197**Verification**:
198```bash
199TOKEN=$(cat ~/.hyper-wallet/.api-token)
200
201# Correct password
202curl -X POST http://localhost:4004/api/export-identity \
203 -H "Authorization: Bearer $TOKEN" \
204 -H "Content-Type: application/json" \
205 -d '{"password":"TestPass123"}'
206
207# Expected: {"mnemonic":"word1 word2 ...","warning":"..."}
208
209# Wrong password
210curl -X POST http://localhost:4004/api/export-identity \
211 -H "Authorization: Bearer $TOKEN" \
212 -H "Content-Type: application/json" \
213 -d '{"password":"WrongPass"}'
214
215# Expected: {"error":"Invalid password"} (HTTP 401)
216```
217
218**✅ Pass Criteria**:
219- Correct password returns mnemonic
220- Wrong password returns 401 error
221
222---
223
224### Test 2.4: Password Validation (FAIL)
225
226**Steps**:
2271. Try to create wallet with password "short"
228
229**Expected**: Error "Password must be at least 8 characters"
230
231**✅ Pass Criteria**: Cannot create wallet with password < 8 chars
232
233---
234
235### Test 2.5: Password Cache Cleared on Restart
236
237**Steps**:
2381. Initialize wallet with password
2392. Restart server (Ctrl+C, start again)
2403. Try to access balance via Web UI
241
242**Expected**: Operations fail until password re-entered
243
244**Note**: Current implementation may auto-detect legacy plaintext. If encrypted, operations requiring mnemonic should fail.
245
246**✅ Pass Criteria**: Password not persisted across restarts
247
248---
249
250## Phase 2.3: Secure Device Pairing Tests
251
252### Test 3.1: Invite Code Generation with Signature (SUCCESS)
253
254**Steps**:
2551. Log in to wallet on Device A
2562. Click "Add Device"
2573. Receive invite code
258
259**Verification**:
260```bash
261TOKEN=$(cat ~/.hyper-wallet/.api-token)
262
263curl -X POST http://localhost:4004/api/device/add \
264 -H "Authorization: Bearer $TOKEN"
265
266# Expected output:
267# {
268# "sessionId": "abc123...",
269# "inviteCode": "base64_encoded_signed_invite",
270# "status": "waiting",
271# "message": "Share this invite code with your other device"
272# }
273```
274
275**Decode invite to verify signature**:
276```bash
277# Save invite code to variable
278INVITE="<paste_invite_code_here>"
279
280# Decode base64
281echo "$INVITE" | base64 -d | jq .
282
283# Expected fields:
284# - discoveryKey
285# - identityKey
286# - autobaseKey
287# - timestamp
288# - expiresAt (timestamp + 15 minutes)
289# - signature (hex string)
290```
291
292**✅ Pass Criteria**:
293- Invite code contains all required fields
294- Signature field present (64+ hex chars)
295- expiresAt = timestamp + 900000ms (15 minutes)
296
297---
298
299### Test 3.2: Invite Code Expiration (FAIL)
300
301**Steps**:
3021. Generate invite code
3032. Wait 16 minutes
3043. Try to join with expired code
305
306**Verification**:
307```bash
308# After 16 minutes
309curl -X POST http://localhost:4004/api/device/join \
310 -H "Authorization: Bearer $TOKEN" \
311 -H "Content-Type: application/json" \
312 -d '{
313 "inviteCode": "<expired_invite>",
314 "deviceName": "Test Device"
315 }'
316
317# Expected output:
318# {"error":"Invite code expired X minutes ago"}
319```
320
321**✅ Pass Criteria**: Error indicates expiration with elapsed time
322
323---
324
325### Test 3.3: Invite Code Signature Verification (FAIL)
326
327**Steps**:
3281. Generate valid invite code
3292. Modify signature (change last character)
3303. Try to join with tampered code
331
332**Verification**:
333```bash
334# Tamper with invite (manually edit base64 decoded JSON, change signature)
335# Re-encode to base64
336TAMPERED_INVITE="<tampered_base64>"
337
338curl -X POST http://localhost:4004/api/device/join \
339 -H "Authorization: Bearer $TOKEN" \
340 -H "Content-Type: application/json" \
341 -d "{
342 \"inviteCode\": \"$TAMPERED_INVITE\",
343 \"deviceName\": \"Hacker Device\"
344 }"
345
346# Expected output:
347# {"error":"Invalid invite signature - invite may be forged or corrupted"}
348```
349
350**✅ Pass Criteria**: Signature verification fails, error message clear
351
352---
353
354### Test 3.4: Valid Device Pairing (SUCCESS)
355
356**Prerequisites**: Second device or separate browser/incognito mode
357
358**Steps (Device A - Primary)**:
3591. Create invite code
3602. Copy invite code
361
362**Steps (Device B - Joining)**:
3631. Navigate to wallet (new session)
3642. Click "Join Existing Wallet"
3653. Paste invite code
3664. Enter device name: "Device B"
3675. Click "Join Wallet"
368
369**Expected**:
370- Success message
371- Both mnemonics received and saved
372- Device appears in device list on both devices
373
374**✅ Pass Criteria**:
375- Joining device receives identity mnemonic
376- Joining device receives wallet mnemonic
377- Both devices see each other in device list
378
379---
380
381## Phase 2.4: Rate Limiting Tests
382
383### Test 4.1: Transaction Rate Limit (FAIL after 10)
384
385**Limit**: 10 transactions per minute
386
387**Steps**:
388```bash
389TOKEN=$(cat ~/.hyper-wallet/.api-token)
390
391# Send 11 transactions rapidly
392for i in {1..11}; do
393 echo "Request $i..."
394 curl -X POST http://localhost:4004/api/send \
395 -H "Authorization: Bearer $TOKEN" \
396 -H "Content-Type: application/json" \
397 -d '{
398 "chain": "bitcoin",
399 "network": "testnet",
400 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
401 "amount": "1000"
402 }'
403 echo ""
404done
405
406# Expected:
407# Requests 1-10: Success (or fail for other reasons like insufficient balance)
408# Request 11: {"error":"Rate limit exceeded. Try again in X seconds."} (HTTP 429)
409```
410
411**Verify Rate Limit Headers**:
412```bash
413curl -I -X POST http://localhost:4004/api/send \
414 -H "Authorization: Bearer $TOKEN" \
415 -H "Content-Type: application/json"
416
417# Expected headers:
418# X-RateLimit-Limit: 10
419# X-RateLimit-Remaining: 9 (after first request)
420# X-RateLimit-Reset: 60
421```
422
423**✅ Pass Criteria**:
424- 11th request returns 429
425- Rate limit headers present
426- Error message includes retry time
427
428---
429
430### Test 4.2: Export Rate Limit (FAIL after 3)
431
432**Limit**: 3 exports per hour
433
434**Steps**:
435```bash
436TOKEN=$(cat ~/.hyper-wallet/.api-token)
437
438# Try to export 4 times
439for i in {1..4}; do
440 echo "Export attempt $i..."
441 curl -X POST http://localhost:4004/api/export-identity \
442 -H "Authorization: Bearer $TOKEN" \
443 -H "Content-Type: application/json" \
444 -d '{"password":"TestPass123"}'
445 echo ""
446 sleep 1
447done
448
449# Expected:
450# Attempts 1-3: Success (mnemonic returned)
451# Attempt 4: {"error":"Rate limit exceeded. Try again in X seconds."} (HTTP 429)
452```
453
454**✅ Pass Criteria**: 4th export attempt fails with 429
455
456---
457
458### Test 4.3: Device Pairing Rate Limit (FAIL after 5)
459
460**Limit**: 5 pairing attempts per 5 minutes
461
462**Steps**:
463```bash
464TOKEN=$(cat ~/.hyper-wallet/.api-token)
465
466# Try to create 6 invite codes
467for i in {1..6}; do
468 echo "Invite attempt $i..."
469 curl -X POST http://localhost:4004/api/device/add \
470 -H "Authorization: Bearer $TOKEN"
471 echo ""
472done
473
474# Expected:
475# Attempts 1-5: Success (invite codes returned)
476# Attempt 6: {"error":"Rate limit exceeded. Try again in X seconds."} (HTTP 429)
477```
478
479**✅ Pass Criteria**: 6th invite creation fails with 429
480
481---
482
483### Test 4.4: Rate Limit Reset After Window
484
485**Steps**:
4861. Hit rate limit (11 send requests)
4872. Wait 61 seconds
4883. Try 12th request
489
490**Expected**: 12th request succeeds (limit reset)
491
492**✅ Pass Criteria**: Rate limit resets after time window
493
494---
495
496### Test 4.5: Per-IP Rate Limiting
497
498**Prerequisites**: Two different IP addresses (or simulate via proxy)
499
500**Steps**:
5011. From IP A: Send 10 transactions (hit limit)
5022. From IP B: Send 1 transaction
503
504**Expected**: IP B request succeeds (separate limit)
505
506**✅ Pass Criteria**: Rate limits are per-IP, not global
507
508---
509
510## Phase 2.5: CORS Restriction Tests
511
512### Test 5.1: Allowed Origin (SUCCESS)
513
514**Steps**:
515```bash
516# Request from localhost (allowed origin)
517curl -X GET http://localhost:4004/api/status \
518 -H "Origin: http://localhost:4004"
519
520# Expected:
521# Access-Control-Allow-Origin: http://localhost:4004
522# HTTP 200
523```
524
525**✅ Pass Criteria**: Response includes matching Access-Control-Allow-Origin header
526
527---
528
529### Test 5.2: Blocked Origin (WARNING)
530
531**Steps**:
532```bash
533# Request from unauthorized origin
534curl -X GET http://localhost:4004/api/status \
535 -H "Origin: http://evil-site.com"
536
537# Expected in server logs:
538# ⚠️ CORS: Blocked origin: http://evil-site.com
539
540# Response still returns (fallback to default), but logs warning
541```
542
543**Verification**: Check server logs in tmux (pear-dev:hw-logs)
544
545**✅ Pass Criteria**: Warning logged for unauthorized origin
546
547---
548
549### Test 5.3: Preflight Request (OPTIONS)
550
551**Steps**:
552```bash
553curl -X OPTIONS http://localhost:4004/api/send \
554 -H "Origin: http://localhost:4004" \
555 -H "Access-Control-Request-Method: POST" \
556 -H "Access-Control-Request-Headers: Content-Type, Authorization"
557
558# Expected headers:
559# Access-Control-Allow-Origin: http://localhost:4004
560# Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT
561# Access-Control-Allow-Headers: Content-Type, Authorization
562# HTTP 204 (No Content)
563```
564
565**✅ Pass Criteria**: Preflight succeeds with correct headers
566
567---
568
569## Phase 2.6: Input Validation Tests
570
571### Test 6.1: Bitcoin Address Validation
572
573#### Test 6.1a: Valid P2PKH Testnet (SUCCESS)
574
575```bash
576TOKEN=$(cat ~/.hyper-wallet/.api-token)
577
578# Valid testnet address (starts with 'm' or 'n')
579curl -X POST http://localhost:4004/api/estimate-fee \
580 -H "Authorization: Bearer $TOKEN" \
581 -H "Content-Type: application/json" \
582 -d '{
583 "chain": "bitcoin",
584 "network": "testnet",
585 "to": "mqXz83H4LCxjf2ie8hYNsTRByvtfV43Pa7",
586 "amount": "10000"
587 }'
588
589# Expected: Fee estimate (or error about balance, but NOT address error)
590```
591
592**✅ Pass Criteria**: Address accepted (no validation error)
593
594---
595
596#### Test 6.1b: Invalid Checksum (FAIL)
597
598```bash
599# Change last character (breaks checksum)
600curl -X POST http://localhost:4004/api/send \
601 -H "Authorization: Bearer $TOKEN" \
602 -H "Content-Type: application/json" \
603 -d '{
604 "chain": "bitcoin",
605 "network": "testnet",
606 "to": "mqXz83H4LCxjf2ie8hYNsTRByvtfV43Pa6",
607 "amount": "10000"
608 }'
609
610# Expected:
611# {"error":"Invalid recipient address: Invalid Base58Check checksum"}
612# HTTP 400
613```
614
615**✅ Pass Criteria**: Checksum validation fails with clear error
616
617---
618
619#### Test 6.1c: Valid Bech32 Testnet (SUCCESS)
620
621```bash
622# Valid testnet bech32 (starts with 'tb1')
623curl -X POST http://localhost:4004/api/estimate-fee \
624 -H "Authorization: Bearer $TOKEN" \
625 -H "Content-Type: application/json" \
626 -d '{
627 "chain": "bitcoin",
628 "network": "testnet",
629 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
630 "amount": "10000"
631 }'
632
633# Expected: Fee estimate (address accepted)
634```
635
636**✅ Pass Criteria**: Bech32 address accepted
637
638---
639
640#### Test 6.1d: Mainnet Address on Testnet (FAIL)
641
642```bash
643# Mainnet address (starts with '1' or 'bc1') used on testnet
644curl -X POST http://localhost:4004/api/send \
645 -H "Authorization: Bearer $TOKEN" \
646 -H "Content-Type: application/json" \
647 -d '{
648 "chain": "bitcoin",
649 "network": "testnet",
650 "to": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
651 "amount": "10000"
652 }'
653
654# Expected:
655# {"error":"Invalid recipient address: Invalid network for address format (expected testnet)"}
656# HTTP 400
657```
658
659**✅ Pass Criteria**: Network mismatch detected
660
661---
662
663### Test 6.2: Ethereum Address Validation
664
665#### Test 6.2a: Valid EIP-55 Checksum (SUCCESS)
666
667```bash
668TOKEN=$(cat ~/.hyper-wallet/.api-token)
669
670# Valid checksummed address
671curl -X POST http://localhost:4004/api/estimate-fee \
672 -H "Authorization: Bearer $TOKEN" \
673 -H "Content-Type: application/json" \
674 -d '{
675 "chain": "ethereum",
676 "network": "sepolia",
677 "to": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
678 "amount": "1000000000000000000"
679 }'
680
681# Expected: Fee estimate (address accepted)
682```
683
684**✅ Pass Criteria**: EIP-55 checksum validated
685
686---
687
688#### Test 6.2b: Invalid EIP-55 Checksum (FAIL)
689
690```bash
691# Change case of one character (breaks EIP-55 checksum)
692curl -X POST http://localhost:4004/api/send \
693 -H "Authorization: Bearer $TOKEN" \
694 -H "Content-Type: application/json" \
695 -d '{
696 "chain": "ethereum",
697 "network": "sepolia",
698 "to": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1beAed",
699 "amount": "1000000000000000000"
700 }'
701
702# Expected:
703# {"error":"Invalid recipient address: Invalid EIP-55 checksum (case mismatch)"}
704# HTTP 400
705```
706
707**✅ Pass Criteria**: Checksum mismatch detected
708
709---
710
711#### Test 6.2c: All Lowercase (WARNING)
712
713```bash
714# All lowercase (no checksum, but valid)
715curl -X POST http://localhost:4004/api/estimate-fee \
716 -H "Authorization: Bearer $TOKEN" \
717 -H "Content-Type: application/json" \
718 -d '{
719 "chain": "ethereum",
720 "network": "sepolia",
721 "to": "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
722 "amount": "1000000000000000000"
723 }'
724
725# Expected: Fee estimate (address accepted with warning in logs)
726# Server log should show: ⚠️ Address validation warning: No EIP-55 checksum
727```
728
729**✅ Pass Criteria**: Accepted with warning logged
730
731---
732
733### Test 6.3: Amount Validation
734
735#### Test 6.3a: Positive Amount (SUCCESS)
736
737```bash
738TOKEN=$(cat ~/.hyper-wallet/.api-token)
739
740curl -X POST http://localhost:4004/api/estimate-fee \
741 -H "Authorization: Bearer $TOKEN" \
742 -H "Content-Type: application/json" \
743 -d '{
744 "chain": "bitcoin",
745 "network": "testnet",
746 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
747 "amount": "50000"
748 }'
749
750# Expected: Fee estimate
751```
752
753**✅ Pass Criteria**: Amount accepted
754
755---
756
757#### Test 6.3b: Zero Amount (FAIL)
758
759```bash
760curl -X POST http://localhost:4004/api/send \
761 -H "Authorization: Bearer $TOKEN" \
762 -H "Content-Type: application/json" \
763 -d '{
764 "chain": "bitcoin",
765 "network": "testnet",
766 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
767 "amount": "0"
768 }'
769
770# Expected:
771# {"error":"Invalid amount: Amount must be greater than zero"}
772# HTTP 400
773```
774
775**✅ Pass Criteria**: Zero amount rejected
776
777---
778
779#### Test 6.3c: Negative Amount (FAIL)
780
781```bash
782curl -X POST http://localhost:4004/api/send \
783 -H "Authorization: Bearer $TOKEN" \
784 -H "Content-Type: application/json" \
785 -d '{
786 "chain": "bitcoin",
787 "network": "testnet",
788 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
789 "amount": "-1000"
790 }'
791
792# Expected:
793# {"error":"Invalid amount: Amount cannot be negative"}
794# HTTP 400
795```
796
797**✅ Pass Criteria**: Negative amount rejected
798
799---
800
801#### Test 6.3d: Decimal Amount (FAIL)
802
803```bash
804curl -X POST http://localhost:4004/api/send \
805 -H "Authorization: Bearer $TOKEN" \
806 -H "Content-Type: application/json" \
807 -d '{
808 "chain": "bitcoin",
809 "network": "testnet",
810 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
811 "amount": "0.001"
812 }'
813
814# Expected:
815# {"error":"Invalid amount: Decimal values not supported (use smallest unit: satoshi/wei)"}
816# HTTP 400
817```
818
819**✅ Pass Criteria**: Decimal rejected (must use satoshi/wei)
820
821---
822
823#### Test 6.3e: Scientific Notation (FAIL)
824
825```bash
826curl -X POST http://localhost:4004/api/send \
827 -H "Authorization: Bearer $TOKEN" \
828 -H "Content-Type: application/json" \
829 -d '{
830 "chain": "bitcoin",
831 "network": "testnet",
832 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
833 "amount": "1e8"
834 }'
835
836# Expected:
837# {"error":"Invalid amount: Scientific notation not supported (use smallest unit: satoshi/wei)"}
838# HTTP 400
839```
840
841**✅ Pass Criteria**: Scientific notation rejected
842
843---
844
845#### Test 6.3f: Overflow Amount (FAIL)
846
847```bash
848# Amount exceeds 21M BTC (in satoshi)
849curl -X POST http://localhost:4004/api/send \
850 -H "Authorization: Bearer $TOKEN" \
851 -H "Content-Type: application/json" \
852 -d '{
853 "chain": "bitcoin",
854 "network": "testnet",
855 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
856 "amount": "9999999999999999999"
857 }'
858
859# Expected:
860# {"error":"Invalid amount: Amount exceeds maximum (21M BTC = 2,100,000,000,000,000 satoshi)"}
861# HTTP 400
862```
863
864**✅ Pass Criteria**: Overflow protection works
865
866---
867
868### Test 6.4: Contact Name Sanitization
869
870#### Test 6.4a: Valid Name (SUCCESS)
871
872```bash
873TOKEN=$(cat ~/.hyper-wallet/.api-token)
874
875curl -X POST http://localhost:4004/api/contacts \
876 -H "Authorization: Bearer $TOKEN" \
877 -H "Content-Type: application/json" \
878 -d '{
879 "name": "Alice Smith",
880 "address": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
881 "chain": "bitcoin",
882 "notes": "My friend"
883 }'
884
885# Expected: Contact created successfully
886```
887
888**✅ Pass Criteria**: Contact created
889
890---
891
892#### Test 6.4b: SQL Injection Attempt (SANITIZED)
893
894```bash
895curl -X POST http://localhost:4004/api/contacts \
896 -H "Authorization: Bearer $TOKEN" \
897 -H "Content-Type: application/json" \
898 -d '{
899 "name": "Alice'; DROP TABLE contacts; --",
900 "address": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
901 "chain": "bitcoin"
902 }'
903
904# Expected:
905# {"error":"Name contains invalid characters (allowed: letters, numbers, spaces, -_.'\''(),)"}
906# HTTP 400
907```
908
909**✅ Pass Criteria**: Special characters rejected (SQL injection blocked)
910
911---
912
913#### Test 6.4c: HTML Injection Attempt (SANITIZED)
914
915```bash
916curl -X POST http://localhost:4004/api/contacts \
917 -H "Authorization: Bearer $TOKEN" \
918 -H "Content-Type: application/json" \
919 -d '{
920 "name": "Alice",
921 "address": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
922 "chain": "bitcoin",
923 "notes": "<script>alert(\"XSS\")</script>"
924 }'
925
926# Expected:
927# {"error":"Notes contain invalid characters (< and > not allowed)"}
928# HTTP 400
929```
930
931**✅ Pass Criteria**: HTML tags blocked
932
933---
934
935#### Test 6.4d: Null Byte Injection (SANITIZED)
936
937```bash
938# Null bytes are automatically stripped by sanitizer
939curl -X POST http://localhost:4004/api/contacts \
940 -H "Authorization: Bearer $TOKEN" \
941 -H "Content-Type: application/json" \
942 -d $'{\n "name": "Alice\\x00Hidden",\n "address": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",\n "chain": "bitcoin"\n}'
943
944# Expected: Contact created with name "AliceHidden" (null byte removed)
945```
946
947**✅ Pass Criteria**: Null bytes stripped
948
949---
950
951### Test 6.5: Device Name Sanitization
952
953#### Test 6.5a: Valid Device Name (SUCCESS)
954
955```bash
956TOKEN=$(cat ~/.hyper-wallet/.api-token)
957
958curl -X POST http://localhost:4004/api/device/join \
959 -H "Authorization: Bearer $TOKEN" \
960 -H "Content-Type: application/json" \
961 -d '{
962 "inviteCode": "<valid_invite>",
963 "deviceName": "My-Laptop_2024"
964 }'
965
966# Expected: Device joined successfully
967```
968
969**✅ Pass Criteria**: Device name accepted
970
971---
972
973#### Test 6.5b: Special Characters (FAIL)
974
975```bash
976curl -X POST http://localhost:4004/api/device/join \
977 -H "Authorization: Bearer $TOKEN" \
978 -H "Content-Type: application/json" \
979 -d '{
980 "inviteCode": "<valid_invite>",
981 "deviceName": "My Laptop <3"
982 }'
983
984# Expected:
985# {"error":"Device name contains invalid characters (allowed: letters, numbers, spaces, -_)"}
986# HTTP 400
987```
988
989**✅ Pass Criteria**: Special characters rejected
990
991---
992
993### Test 6.6: Chain/Network Validation
994
995#### Test 6.6a: Valid Chain (SUCCESS)
996
997```bash
998TOKEN=$(cat ~/.hyper-wallet/.api-token)
999
1000curl -X GET http://localhost:4004/api/balance/bitcoin \
1001 -H "Authorization: Bearer $TOKEN"
1002
1003# Expected: Balance returned
1004```
1005
1006**✅ Pass Criteria**: Valid chain accepted
1007
1008---
1009
1010#### Test 6.6b: Invalid Chain (FAIL)
1011
1012```bash
1013curl -X GET http://localhost:4004/api/balance/dogecoin \
1014 -H "Authorization: Bearer $TOKEN"
1015
1016# Expected:
1017# {"error":"Invalid chain: dogecoin (supported: bitcoin, ethereum)"}
1018# HTTP 400
1019```
1020
1021**✅ Pass Criteria**: Unsupported chain rejected with list of supported chains
1022
1023---
1024
1025## Integration Tests
1026
1027### Test 7.1: Complete Transaction Flow
1028
1029**Scenario**: Send Bitcoin transaction with all security features
1030
1031**Prerequisites**:
1032- Wallet initialized with password
1033- Testnet Bitcoin funded (use faucet: https://testnet-faucet.mempool.co/)
1034
1035**Steps**:
10361. Get Bitcoin testnet address:
1037 ```bash
1038 curl -X GET http://localhost:4004/api/address/bitcoin \
1039 -H "Authorization: Bearer $(cat ~/.hyper-wallet/.api-token)"
1040 ```
10412. Fund address from faucet (0.001 tBTC)
10423. Wait for confirmation (~10 minutes)
10434. Check balance:
1044 ```bash
1045 curl -X GET http://localhost:4004/api/balance/bitcoin \
1046 -H "Authorization: Bearer $(cat ~/.hyper-wallet/.api-token)"
1047 ```
10485. Estimate fee:
1049 ```bash
1050 curl -X POST http://localhost:4004/api/estimate-fee \
1051 -H "Authorization: Bearer $(cat ~/.hyper-wallet/.api-token)" \
1052 -H "Content-Type: application/json" \
1053 -d '{
1054 "chain": "bitcoin",
1055 "network": "testnet",
1056 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
1057 "amount": "10000"
1058 }'
1059 ```
10606. Send transaction:
1061 ```bash
1062 curl -X POST http://localhost:4004/api/send \
1063 -H "Authorization: Bearer $(cat ~/.hyper-wallet/.api-token)" \
1064 -H "Content-Type: application/json" \
1065 -d '{
1066 "chain": "bitcoin",
1067 "network": "testnet",
1068 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
1069 "amount": "10000"
1070 }'
1071 ```
1072
1073**Expected**:
1074- Fee estimate returns reasonable fee (~1000-5000 satoshi)
1075- Send returns transaction hash
1076- Transaction appears in mempool (check https://mempool.space/testnet/)
1077
1078**Validation Points**:
1079- ✅ Authentication required (Bearer token)
1080- ✅ Address validated with checksum
1081- ✅ Amount validated (positive, within limits)
1082- ✅ Balance sufficiency checked (amount + fee)
1083- ✅ Rate limit enforced (try 11th transaction)
1084- ✅ CORS headers present
1085- ✅ Transaction logged on server
1086
1087**✅ Pass Criteria**: Transaction sent successfully with all validations
1088
1089---
1090
1091### Test 7.2: Multi-Device Sync
1092
1093**Prerequisites**: Two devices or two browser sessions
1094
1095**Steps (Device A)**:
10961. Initialize wallet on Device A
10972. Create contact "Bob" with address
10983. Create device invite
10994. Share invite with Device B
1100
1101**Steps (Device B)**:
11021. Join wallet with invite
11032. Verify contact "Bob" appears
11043. Create contact "Charlie"
1105
1106**Steps (Device A)**:
11071. Refresh device list
11082. Verify Device B appears
11093. Verify contact "Charlie" appears
1110
1111**Validation Points**:
1112- ✅ Invite signed and time-limited
1113- ✅ Mnemonics transferred securely
1114- ✅ Contacts sync across devices
1115- ✅ Device list shows both devices
1116- ✅ Autobase merge works (no conflicts)
1117
1118**✅ Pass Criteria**: Both devices see same data after sync
1119
1120---
1121
1122### Test 7.3: Password Recovery Scenario
1123
1124**Scenario**: User forgets password but has mnemonics
1125
1126**Steps**:
11271. Initialize wallet with password "OldPass123"
11282. Export identity mnemonic (with password)
11293. Export wallet mnemonic (with password)
11304. Save both mnemonics offline
11315. Delete wallet data:
1132 ```bash
1133 rm -rf ~/.hyper-wallet/
1134 ```
11356. Restore wallet:
1136 - Click "Restore Existing Wallet"
1137 - Enter NEW password "NewPass456"
1138 - Enter saved identity mnemonic
1139 - Enter saved wallet mnemonic
1140 - Click "Restore Wallet"
11417. Verify balance and contacts restored
1142
1143**Validation Points**:
1144- ✅ New password encrypts mnemonics
1145- ✅ Old password no longer works
1146- ✅ Balance intact
1147- ✅ Contacts intact
1148- ✅ Transaction history intact (Autobase persistence)
1149
1150**✅ Pass Criteria**: Wallet fully restored with new password
1151
1152---
1153
1154## Performance Tests
1155
1156### Test 8.1: Rate Limiter Performance
1157
1158**Goal**: Verify rate limiter doesn't significantly impact response time
1159
1160**Steps**:
1161```bash
1162TOKEN=$(cat ~/.hyper-wallet/.api-token)
1163
1164# Measure baseline (without rate limit hit)
1165time curl -X GET http://localhost:4004/api/status \
1166 -H "Authorization: Bearer $TOKEN"
1167
1168# Expected: < 100ms
1169```
1170
1171**✅ Pass Criteria**: Rate limiter overhead < 10ms
1172
1173---
1174
1175### Test 8.2: Address Validation Performance
1176
1177**Goal**: Verify checksum validation doesn't slow down transactions
1178
1179**Steps**:
1180```bash
1181# Time address validation
1182time for i in {1..100}; do
1183 curl -s -X POST http://localhost:4004/api/estimate-fee \
1184 -H "Authorization: Bearer $(cat ~/.hyper-wallet/.api-token)" \
1185 -H "Content-Type: application/json" \
1186 -d '{
1187 "chain": "bitcoin",
1188 "network": "testnet",
1189 "to": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
1190 "amount": "10000"
1191 }' > /dev/null
1192done
1193
1194# Expected: < 10 seconds for 100 requests (< 100ms per request)
1195```
1196
1197**✅ Pass Criteria**: < 100ms per validation
1198
1199---
1200
1201## Security Audit Checklist
1202
1203### Authentication
1204- [ ] All sensitive endpoints require Bearer token
1205- [ ] Invalid tokens return 401
1206- [ ] Token stored with mode 0600
1207- [ ] Token persists across restarts
1208- [ ] Token regeneration works
1209
1210### Encryption
1211- [ ] Mnemonics encrypted with AES-256-GCM
1212- [ ] Password min 8 characters enforced
1213- [ ] Scrypt key derivation used (N=16384)
1214- [ ] Salt and IV randomized per encryption
1215- [ ] Encrypted data not plaintext readable
1216- [ ] Wrong password returns 401 (no leak)
1217
1218### Device Pairing
1219- [ ] Invites signed with Ed25519
1220- [ ] Signature verified on join
1221- [ ] Invites expire after 15 minutes
1222- [ ] Expired invites rejected
1223- [ ] Tampered invites rejected
1224- [ ] Mnemonics only shared via secure channel
1225
1226### Rate Limiting
1227- [ ] Transaction limit enforced (10/min)
1228- [ ] Export limit enforced (3/hour)
1229- [ ] Pairing limit enforced (5 per 5min)
1230- [ ] Rate limit headers present
1231- [ ] 429 status on limit exceeded
1232- [ ] Limits are per-IP address
1233
1234### CORS
1235- [ ] Wildcard (*) removed
1236- [ ] Whitelist configured
1237- [ ] Unauthorized origins logged
1238- [ ] Preflight requests handled
1239- [ ] Credentials allowed for valid origins
1240
1241### Input Validation
1242- [ ] Bitcoin Base58Check validated
1243- [ ] Bitcoin Bech32 validated
1244- [ ] Ethereum EIP-55 validated
1245- [ ] Network mismatch detected
1246- [ ] Amount range checked
1247- [ ] Zero/negative amounts rejected
1248- [ ] Decimal amounts rejected
1249- [ ] Overflow amounts rejected
1250- [ ] Contact names sanitized
1251- [ ] Device names sanitized
1252- [ ] Notes sanitized (no HTML)
1253- [ ] Null bytes stripped
1254- [ ] Chain/network whitelist enforced
1255
1256---
1257
1258## Regression Tests
1259
1260### Test 9.1: Existing Wallet Compatibility
1261
1262**Goal**: Verify Phase 1 wallets still work
1263
1264**Prerequisites**: Backup of pre-Phase 2 wallet data
1265
1266**Steps**:
12671. Copy old wallet data to `~/.hyper-wallet/`
12682. Start new server (v11436)
12693. Access Web UI
1270
1271**Expected**: Legacy plaintext detection triggers, user can migrate
1272
1273**✅ Pass Criteria**: Old wallets still accessible with migration path
1274
1275---
1276
1277### Test 9.2: Transaction History Intact
1278
1279**Goal**: Verify old transactions not lost
1280
1281**Steps**:
12821. Restore pre-Phase 2 wallet
12832. Check transaction history API
12843. Verify all old transactions present
1285
1286**✅ Pass Criteria**: No data loss
1287
1288---
1289
1290## Test Results Summary Template
1291
1292```
1293# Phase 2 Test Results
1294Date: __________
1295Tester: __________
1296Version: 11436
1297
1298## Authentication (Phase 2.1)
1299- [ ] Test 1.1: Unauthenticated Request (FAIL) - PASS/FAIL
1300- [ ] Test 1.2: Token Generation on Init (SUCCESS) - PASS/FAIL
1301- [ ] Test 1.3: Authenticated Request (SUCCESS) - PASS/FAIL
1302- [ ] Test 1.4: Invalid Token (FAIL) - PASS/FAIL
1303- [ ] Test 1.5: Token Persistence - PASS/FAIL
1304
1305## Encryption (Phase 2.2)
1306- [ ] Test 2.1: Password-Based Encryption - PASS/FAIL
1307- [ ] Test 2.2: Password Caching - PASS/FAIL
1308- [ ] Test 2.3: Password Required on Export - PASS/FAIL
1309- [ ] Test 2.4: Password Validation - PASS/FAIL
1310- [ ] Test 2.5: Password Cache Cleared on Restart - PASS/FAIL
1311
1312## Device Pairing (Phase 2.3)
1313- [ ] Test 3.1: Invite Code with Signature - PASS/FAIL
1314- [ ] Test 3.2: Invite Expiration - PASS/FAIL
1315- [ ] Test 3.3: Signature Verification - PASS/FAIL
1316- [ ] Test 3.4: Valid Device Pairing - PASS/FAIL
1317
1318## Rate Limiting (Phase 2.4)
1319- [ ] Test 4.1: Transaction Rate Limit - PASS/FAIL
1320- [ ] Test 4.2: Export Rate Limit - PASS/FAIL
1321- [ ] Test 4.3: Device Pairing Rate Limit - PASS/FAIL
1322- [ ] Test 4.4: Rate Limit Reset - PASS/FAIL
1323- [ ] Test 4.5: Per-IP Rate Limiting - PASS/FAIL
1324
1325## CORS (Phase 2.5)
1326- [ ] Test 5.1: Allowed Origin - PASS/FAIL
1327- [ ] Test 5.2: Blocked Origin - PASS/FAIL
1328- [ ] Test 5.3: Preflight Request - PASS/FAIL
1329
1330## Input Validation (Phase 2.6)
1331- [ ] Test 6.1: Bitcoin Address Validation - PASS/FAIL
1332- [ ] Test 6.2: Ethereum Address Validation - PASS/FAIL
1333- [ ] Test 6.3: Amount Validation - PASS/FAIL
1334- [ ] Test 6.4: Contact Name Sanitization - PASS/FAIL
1335- [ ] Test 6.5: Device Name Sanitization - PASS/FAIL
1336- [ ] Test 6.6: Chain/Network Validation - PASS/FAIL
1337
1338## Integration Tests
1339- [ ] Test 7.1: Complete Transaction Flow - PASS/FAIL
1340- [ ] Test 7.2: Multi-Device Sync - PASS/FAIL
1341- [ ] Test 7.3: Password Recovery - PASS/FAIL
1342
1343## Performance Tests
1344- [ ] Test 8.1: Rate Limiter Performance - PASS/FAIL
1345- [ ] Test 8.2: Address Validation Performance - PASS/FAIL
1346
1347## Regression Tests
1348- [ ] Test 9.1: Existing Wallet Compatibility - PASS/FAIL
1349- [ ] Test 9.2: Transaction History Intact - PASS/FAIL
1350
1351## Critical Issues Found
13521.
13532.
13543.
1355
1356## Notes
1357```
1358
1359---
1360
1361## Quick Start for Testing
1362
1363```bash
1364# 1. Start test environment
1365cd /storage/projects/code/hypercore-kb/hyper-fleeky/hyper-wallet
1366./scripts/pear-test.sh
1367
1368# 2. Open browser
1369firefox http://localhost:4004 &
1370
1371# 3. Create wallet
1372# - Set password "TestPass123"
1373# - Save mnemonics and token
1374
1375# 4. Run automated tests
1376bash <<'EOF'
1377TOKEN=$(cat ~/.hyper-wallet/.api-token)
1378
1379# Test auth
1380echo "Testing authentication..."
1381curl -s http://localhost:4004/api/balance/bitcoin | grep -q "Unauthorized" && echo "✅ Auth required"
1382
1383# Test rate limit
1384echo "Testing rate limits..."
1385for i in {1..11}; do
1386 curl -s -X POST http://localhost:4004/api/send \
1387 -H "Authorization: Bearer $TOKEN" \
1388 -H "Content-Type: application/json" \
1389 -d '{"chain":"bitcoin","network":"testnet","to":"tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","amount":"1000"}' \
1390 | grep -q "Rate limit" && echo "✅ Rate limit works" && break
1391done
1392
1393# Test validation
1394echo "Testing address validation..."
1395curl -s -X POST http://localhost:4004/api/send \
1396 -H "Authorization: Bearer $TOKEN" \
1397 -H "Content-Type: application/json" \
1398 -d '{"chain":"bitcoin","network":"testnet","to":"invalid","amount":"1000"}' \
1399 | grep -q "Invalid recipient address" && echo "✅ Address validation works"
1400
1401echo "All basic tests complete!"
1402EOF
1403
1404# 5. Stop test environment
1405./scripts/pear-stop.sh
1406```
1407
1408---
1409
1410**END OF TEST PLAN**