From 6fe7e380cb3aa523ff969048a164f7a9d523c63b Mon Sep 17 00:00:00 2001 From: Morax Date: Thu, 31 Jul 2025 10:35:45 +0800 Subject: [PATCH] feat: Implement secure random generation for session IDs and card shuffling --- .claude/settings.local.json | 13 +++++++++++++ src/tarot/card-search.ts | 16 +++++++++++++++- src/tarot/session-manager.ts | 5 ++++- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..ec2360d --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Bash(ls:*)", + "Bash(npm outdated:*)", + "Bash(jq:*)", + "Bash(node:*)", + "Bash(npm run build:*)", + "Bash(npm test)" + ], + "deny": [] + } +} \ No newline at end of file diff --git a/src/tarot/card-search.ts b/src/tarot/card-search.ts index 27bf456..25d608c 100644 --- a/src/tarot/card-search.ts +++ b/src/tarot/card-search.ts @@ -1,4 +1,5 @@ import { TarotCard } from './types.js'; +import { getSecureRandom } from './utils.js'; export interface SearchOptions { keyword?: string; @@ -103,7 +104,8 @@ export class TarotCardSearch { filteredCards = searchResults.map(result => result.card); } - const shuffled = [...filteredCards].sort(() => Math.random() - 0.5); + // Use Fisher-Yates shuffle with secure random for true randomness + const shuffled = this.fisherYatesShuffle(filteredCards); return shuffled.slice(0, Math.min(count, shuffled.length)); } @@ -250,4 +252,16 @@ export class TarotCardSearch { .sort((a, b) => b.count - a.count) .slice(0, limit); } + + /** + * Fisher-Yates shuffle algorithm using cryptographically secure random + */ + private fisherYatesShuffle(array: readonly T[]): T[] { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(getSecureRandom() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled; + } } diff --git a/src/tarot/session-manager.ts b/src/tarot/session-manager.ts index e49ca00..09745a0 100644 --- a/src/tarot/session-manager.ts +++ b/src/tarot/session-manager.ts @@ -1,4 +1,5 @@ import { TarotSession, TarotReading } from "./types.js"; +import { getSecureRandom } from "./utils.js"; /** * Manages tarot reading sessions @@ -69,7 +70,9 @@ export class TarotSessionManager { * Generate a unique session ID */ private generateSessionId(): string { - return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + const timestamp = Date.now(); + const randomPart = Math.floor(getSecureRandom() * 1000000000).toString(36); + return `session_${timestamp}_${randomPart}`; } /**