k9guard 1.0.0

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/README.md ADDED
@@ -0,0 +1,235 @@
1
+ ![Banner](https://www.upload.ee/image/18782156/k9guard.png)
2
+
3
+ [Türkçe Dokümantasyon](docs/tr/README.md)
4
+
5
+ # K9Guard
6
+
7
+ A secure, lightweight, and flexible CAPTCHA module for TypeScript/JavaScript projects with cryptographic security and multi-language support.
8
+
9
+ ## Features
10
+
11
+ - **Cryptographically Secure**: NIST SP 800-90A compliant random generation
12
+ - **Multi-Language Support**: English and Turkish locales for riddles and logic questions
13
+ - **9 CAPTCHA Types**: Math, text, riddle, sequence, scramble, logic, reverse, mixed, and multi-step challenges
14
+ - **Security First**: SHA-256 salted hashing, nonce-based session management, and 5-minute expiry
15
+ - **Input Validation**: Length limits, type checking, and sanitization to prevent injection attacks
16
+ - **Custom Questions**: Support for your own questions with validation and sanitization
17
+ - **Zero Dependencies**: Lightweight with no external dependencies
18
+ - **Well Tested**: Comprehensive test coverage including edge cases and security scenarios
19
+ - **OWASP Compliant**: Follows OWASP Top 10 security guidelines
20
+ - **Privacy Compliant**: GDPR/KVKK compliant with no personal data storage
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install k9guard
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import K9Guard from "k9guard";
32
+
33
+ const captcha = new K9Guard({
34
+ type: 'math',
35
+ difficulty: 'medium',
36
+ locale: 'en'
37
+ });
38
+
39
+ // generate a challenge
40
+ const challenge = captcha.generate();
41
+ console.log(challenge.question); // "15 + 7"
42
+
43
+ // validate user answer
44
+ const isValid = captcha.validate(challenge, "22");
45
+ if (isValid) {
46
+ console.log("Access granted!");
47
+ } else {
48
+ console.log("Wrong answer!");
49
+ }
50
+ ```
51
+
52
+ ## Usage Examples
53
+
54
+ ### Math CAPTCHA
55
+
56
+ ```typescript
57
+ const captcha = new K9Guard({ type: 'math', difficulty: 'easy' });
58
+ const challenge = captcha.generate();
59
+ // Output: "5 + 3"
60
+ // Answer: "8"
61
+ ```
62
+
63
+ ### Text CAPTCHA
64
+
65
+ ```typescript
66
+ const captcha = new K9Guard({ type: 'text', difficulty: 'medium' });
67
+ const challenge = captcha.generate();
68
+ // Output: "aB2xY9"
69
+ // Answer: "aB2xY9"
70
+ ```
71
+
72
+ ### Riddle CAPTCHA
73
+
74
+ ```typescript
75
+ const captcha = new K9Guard({ type: 'riddle', difficulty: 'easy', locale: 'en' });
76
+ const challenge = captcha.generate();
77
+ // Output: "What has keys but can't open locks?"
78
+ // Answer: "piano"
79
+ ```
80
+
81
+ ### Sequence CAPTCHA
82
+
83
+ ```typescript
84
+ const captcha = new K9Guard({ type: 'sequence', difficulty: 'easy' });
85
+ const challenge = captcha.generate();
86
+ // Output: "2, 4, 6, ?"
87
+ // Answer: "8"
88
+ ```
89
+
90
+ ### Scramble CAPTCHA
91
+
92
+ ```typescript
93
+ const captcha = new K9Guard({ type: 'scramble', difficulty: 'easy' });
94
+ const challenge = captcha.generate();
95
+ // Output: "tac"
96
+ // Answer: "cat"
97
+ ```
98
+
99
+ ### Logic CAPTCHA
100
+
101
+ ```typescript
102
+ const captcha = new K9Guard({ type: 'logic', difficulty: 'easy', locale: 'en' });
103
+ const challenge = captcha.generate();
104
+ // Output: "Water is dry. True or False?"
105
+ // Answer: "false"
106
+ ```
107
+
108
+ ### Reverse CAPTCHA
109
+
110
+ ```typescript
111
+ const captcha = new K9Guard({ type: 'reverse', difficulty: 'easy' });
112
+ const challenge = captcha.generate();
113
+ // Output: "god"
114
+ // Answer: "dog"
115
+ ```
116
+
117
+ ### Mixed CAPTCHA
118
+
119
+ ```typescript
120
+ const captcha = new K9Guard({ type: 'mixed', difficulty: 'medium' });
121
+ const challenge = captcha.generate();
122
+ // Randomly picks one of the above types
123
+ ```
124
+
125
+ ### Multi-Step CAPTCHA
126
+
127
+ ```typescript
128
+ const captcha = new K9Guard({ type: 'multi', difficulty: 'easy' });
129
+ const challenge = captcha.generate();
130
+
131
+ if (challenge.steps) {
132
+ // user must solve both steps
133
+ const answers = challenge.steps.map(step => step.answer.toString());
134
+ const userInput = JSON.stringify(answers);
135
+ const isValid = captcha.validate(challenge, userInput);
136
+ }
137
+ ```
138
+
139
+ ### Custom Questions
140
+
141
+ ```typescript
142
+ const captcha = new K9Guard({
143
+ type: 'custom',
144
+ questions: [
145
+ { question: 'What is the capital of France?', answer: 'paris', difficulty: 'easy' },
146
+ { question: 'What is 2+2?', answer: '4', difficulty: 'easy' },
147
+ { question: 'What color is the sky?', answer: 'blue', difficulty: 'easy' }
148
+ ]
149
+ });
150
+
151
+ const challenge = captcha.generate();
152
+ const isValid = captcha.validate(challenge, "paris");
153
+ ```
154
+
155
+ ## API Reference
156
+
157
+ ### Constructor Options
158
+
159
+ #### Standard CAPTCHA Options
160
+
161
+ ```typescript
162
+ interface K9GuardOptions {
163
+ type: 'math' | 'text' | 'riddle' | 'sequence' | 'scramble' | 'logic' | 'reverse' | 'mixed' | 'multi';
164
+ difficulty: 'easy' | 'medium' | 'hard';
165
+ locale?: 'en' | 'tr'; // default: 'en'
166
+ }
167
+ ```
168
+
169
+ #### Custom CAPTCHA Options
170
+
171
+ ```typescript
172
+ interface K9GuardCustomOptions {
173
+ type: 'custom';
174
+ questions: CustomQuestion[];
175
+ }
176
+
177
+ interface CustomQuestion {
178
+ question: string; // 5-500 characters
179
+ answer: string; // 1-200 characters
180
+ difficulty: 'easy' | 'medium' | 'hard';
181
+ }
182
+ ```
183
+
184
+ ### Methods
185
+
186
+ #### `generate(): CaptchaChallenge`
187
+
188
+ Generates a new CAPTCHA challenge with unique nonce, expiry time, and hashed answer.
189
+
190
+ ```typescript
191
+ const challenge = captcha.generate();
192
+ console.log(challenge.question); // the question to show user
193
+ console.log(challenge.nonce); // unique session identifier
194
+ console.log(challenge.expiry); // timestamp when challenge expires
195
+ ```
196
+
197
+ #### `validate(challenge: CaptchaChallenge, userInput: string): boolean`
198
+
199
+ Validates user input against the challenge. Returns `true` if correct, `false` otherwise.
200
+
201
+ ```typescript
202
+ const isValid = captcha.validate(challenge, userAnswer);
203
+ ```
204
+
205
+ ## Testing
206
+
207
+ Run the included test suite:
208
+
209
+ ```bash
210
+ bun run src/test.ts
211
+ ```
212
+
213
+ Tests include:
214
+ - All CAPTCHA types with correct/incorrect/edge case inputs
215
+ - Custom question validation
216
+ - Locale switching
217
+ - Multi-step challenges
218
+ - Input sanitization
219
+ - Security validations
220
+
221
+ ## Contributing
222
+
223
+ We welcome contributions! Here's how you can help:
224
+
225
+ 1. **Fork the repository**
226
+ 2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
227
+ 3. **Add tests** for your changes
228
+ 4. **Run tests**: `bun run src/test.ts`
229
+ 5. **Commit your changes**: `git commit -m 'feat: add amazing feature'`
230
+ 6. **Push to branch**: `git push origin feature/amazing-feature`
231
+ 7. **Open a Pull Request**
232
+
233
+ ## License
234
+
235
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,235 @@
1
+ ![Banner](https://www.upload.ee/image/18782156/k9guard.png)
2
+
3
+ [English Documentation](../../README.md)
4
+
5
+ # K9Guard
6
+
7
+ TypeScript/JavaScript projeleri için kriptografik güvenlik ve çok dilli destek sunan güvenli, hafif ve esnek bir CAPTCHA modülü.
8
+
9
+ ## Özellikler
10
+
11
+ - **Kriptografik Güvenlik**: NIST SP 800-90A standardına uyumluluk sağlanmıştır
12
+ - **Çok Dilli Destek**: Bulmaca ve mantık soruları için İngilizce ve Türkçe dil desteği mevcuttur
13
+ - **9 CAPTCHA Türü**: Matematik, metin, bulmaca, dizi, karıştırma, mantık, ters çevirme, karma ve çok adımlı doğrulama yöntemleri
14
+ - **Güvenlik Odaklı**: SHA-256 tuzlu hash algoritması, nonce tabanlı oturum yönetimi ve 5 dakikalık geçerlilik süresi
15
+ - **Girdi Doğrulama**: Enjeksiyon saldırılarını önlemek için uzunluk sınırlamaları, tip kontrolü ve sanitizasyon
16
+ - **Özel Sorular**: Doğrulama ve sanitizasyon ile kendi sorularınızı tanımlama desteği
17
+ - **Sıfır Bağımlılık**: Harici bağımlılık gerektirmeyen hafif yapı
18
+ - **Kapsamlı Test Edilmiş**: Uç durumlar ve güvenlik senaryoları dahil olmak üzere geniş test kapsama alanı
19
+ - **OWASP Uyumlu**: OWASP Top 10 güvenlik yönergelerine uygun geliştirme
20
+ - **Gizlilik Uyumlu**: Kişisel veri saklamayan GDPR/KVKK uyumlu mimari
21
+
22
+ ## Kurulum
23
+
24
+ ```bash
25
+ npm install k9guard
26
+ ```
27
+
28
+ ## Hızlı Başlangıç
29
+
30
+ ```typescript
31
+ import K9Guard from "k9guard";
32
+
33
+ const captcha = new K9Guard({
34
+ type: 'math',
35
+ difficulty: 'medium',
36
+ locale: 'tr'
37
+ });
38
+
39
+ // doğrulama sorusu oluştur
40
+ const challenge = captcha.generate();
41
+ console.log(challenge.question); // "15 + 7"
42
+
43
+ // kullanıcı yanıtını doğrula
44
+ const isValid = captcha.validate(challenge, "22");
45
+ if (isValid) {
46
+ console.log("Erişim izni verildi!");
47
+ } else {
48
+ console.log("Yanlış cevap!");
49
+ }
50
+ ```
51
+
52
+ ## Kullanım Örnekleri
53
+
54
+ ### Matematik CAPTCHA
55
+
56
+ ```typescript
57
+ const captcha = new K9Guard({ type: 'math', difficulty: 'easy' });
58
+ const challenge = captcha.generate();
59
+ // Çıktı: "5 + 3"
60
+ // Cevap: "8"
61
+ ```
62
+
63
+ ### Metin CAPTCHA
64
+
65
+ ```typescript
66
+ const captcha = new K9Guard({ type: 'text', difficulty: 'medium' });
67
+ const challenge = captcha.generate();
68
+ // Çıktı: "aB2xY9"
69
+ // Cevap: "aB2xY9"
70
+ ```
71
+
72
+ ### Bulmaca CAPTCHA
73
+
74
+ ```typescript
75
+ const captcha = new K9Guard({ type: 'riddle', difficulty: 'easy', locale: 'tr' });
76
+ const challenge = captcha.generate();
77
+ // Çıktı: "Tuşları vardır ama kilit açamaz. Nedir?"
78
+ // Cevap: "piyano"
79
+ ```
80
+
81
+ ### Dizi CAPTCHA
82
+
83
+ ```typescript
84
+ const captcha = new K9Guard({ type: 'sequence', difficulty: 'easy' });
85
+ const challenge = captcha.generate();
86
+ // Çıktı: "2, 4, 6, ?"
87
+ // Cevap: "8"
88
+ ```
89
+
90
+ ### Karıştırma CAPTCHA
91
+
92
+ ```typescript
93
+ const captcha = new K9Guard({ type: 'scramble', difficulty: 'easy' });
94
+ const challenge = captcha.generate();
95
+ // Çıktı: "iked"
96
+ // Cevap: "kedi"
97
+ ```
98
+
99
+ ### Mantık CAPTCHA
100
+
101
+ ```typescript
102
+ const captcha = new K9Guard({ type: 'logic', difficulty: 'easy', locale: 'tr' });
103
+ const challenge = captcha.generate();
104
+ // Çıktı: "Su kuru bir maddedir. Doğru mu Yanlış mı?"
105
+ // Cevap: "yanlış"
106
+ ```
107
+
108
+ ### Ters Çevirme CAPTCHA
109
+
110
+ ```typescript
111
+ const captcha = new K9Guard({ type: 'reverse', difficulty: 'easy' });
112
+ const challenge = captcha.generate();
113
+ // Çıktı: "köpek"
114
+ // Cevap: "kepök"
115
+ ```
116
+
117
+ ### Karma CAPTCHA
118
+
119
+ ```typescript
120
+ const captcha = new K9Guard({ type: 'mixed', difficulty: 'medium' });
121
+ const challenge = captcha.generate();
122
+ // Yukarıdaki türlerden birini rastgele seçer
123
+ ```
124
+
125
+ ### Çok Adımlı CAPTCHA
126
+
127
+ ```typescript
128
+ const captcha = new K9Guard({ type: 'multi', difficulty: 'easy' });
129
+ const challenge = captcha.generate();
130
+
131
+ if (challenge.steps) {
132
+ // kullanıcı her iki adımı da çözmelidir
133
+ const answers = challenge.steps.map(step => step.answer.toString());
134
+ const userInput = JSON.stringify(answers);
135
+ const isValid = captcha.validate(challenge, userInput);
136
+ }
137
+ ```
138
+
139
+ ### Özel Sorular
140
+
141
+ ```typescript
142
+ const captcha = new K9Guard({
143
+ type: 'custom',
144
+ questions: [
145
+ { question: 'Türkiye\'nin başkenti neresidir?', answer: 'ankara', difficulty: 'easy' },
146
+ { question: '2+2 işleminin sonucu nedir?', answer: '4', difficulty: 'easy' },
147
+ { question: 'Gökyüzü ne renktir?', answer: 'mavi', difficulty: 'easy' }
148
+ ]
149
+ });
150
+
151
+ const challenge = captcha.generate();
152
+ const isValid = captcha.validate(challenge, "ankara");
153
+ ```
154
+
155
+ ## API Referansı
156
+
157
+ ### Yapıcı Metod Seçenekleri
158
+
159
+ #### Standart CAPTCHA Seçenekleri
160
+
161
+ ```typescript
162
+ interface K9GuardOptions {
163
+ type: 'math' | 'text' | 'riddle' | 'sequence' | 'scramble' | 'logic' | 'reverse' | 'mixed' | 'multi';
164
+ difficulty: 'easy' | 'medium' | 'hard';
165
+ locale?: 'en' | 'tr'; // varsayılan: 'en'
166
+ }
167
+ ```
168
+
169
+ #### Özel CAPTCHA Seçenekleri
170
+
171
+ ```typescript
172
+ interface K9GuardCustomOptions {
173
+ type: 'custom';
174
+ questions: CustomQuestion[];
175
+ }
176
+
177
+ interface CustomQuestion {
178
+ question: string; // 5-500 karakter arası
179
+ answer: string; // 1-200 karakter arası
180
+ difficulty: 'easy' | 'medium' | 'hard';
181
+ }
182
+ ```
183
+
184
+ ### Metotlar
185
+
186
+ #### `generate(): CaptchaChallenge`
187
+
188
+ Benzersiz nonce, geçerlilik süresi ve hash'lenmiş cevap içeren yeni bir CAPTCHA doğrulaması oluşturur.
189
+
190
+ ```typescript
191
+ const challenge = captcha.generate();
192
+ console.log(challenge.question); // kullanıcıya gösterilecek soru
193
+ console.log(challenge.nonce); // benzersiz oturum tanımlayıcısı
194
+ console.log(challenge.expiry); // doğrulamanın geçerlilik süresi sona erme zamanı
195
+ ```
196
+
197
+ #### `validate(challenge: CaptchaChallenge, userInput: string): boolean`
198
+
199
+ Kullanıcı girdisini doğrulama ile karşılaştırır. Doğruysa `true`, yanlışsa `false` değeri döndürür.
200
+
201
+ ```typescript
202
+ const isValid = captcha.validate(challenge, userAnswer);
203
+ ```
204
+
205
+ ## Test Etme
206
+
207
+ Dahil edilen test paketini çalıştırın:
208
+
209
+ ```bash
210
+ bun run src/test.ts
211
+ ```
212
+
213
+ Testler şunları içerir:
214
+ - Tüm CAPTCHA türleri için doğru/yanlış/uç durum girdileri
215
+ - Özel soru doğrulama senaryoları
216
+ - Dil değiştirme işlemleri
217
+ - Çok adımlı doğrulamalar
218
+ - Girdi sanitizasyonu
219
+ - Güvenlik doğrulamaları
220
+
221
+ ## Katkıda Bulunma
222
+
223
+ Katkılarınızı memnuniyetle karşılıyoruz! Nasıl yardımcı olabilirsiniz:
224
+
225
+ 1. **Depoyu fork edin**
226
+ 2. **Özellik dalı oluşturun**: `git checkout -b feature/harika-ozellik`
227
+ 3. **Değişiklikleriniz için testler ekleyin**
228
+ 4. **Testleri çalıştırın**: `bun run src/test.ts`
229
+ 5. **Değişikliklerinizi commit edin**: `git commit -m 'feat: harika özellik eklendi'`
230
+ 6. **Dalınıza push edin**: `git push origin feature/harika-ozellik`
231
+ 7. **Pull Request oluşturun**
232
+
233
+ ## Lisans
234
+
235
+ Bu proje MIT Lisansı altında lisanslanmıştır. Detaylar için [LICENSE](LICENSE) dosyasını inceleyebilirsiniz.
package/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { K9Guard as default } from './src/K9Guard';
2
+ export * from './src/types';
3
+ export { CustomQuestionValidator } from './src/validators/customQuestionValidator';
4
+ export { CustomQuestionGenerator } from './src/utils/customQuestionGenerator';
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "k9guard",
3
+ "version": "1.0.0",
4
+ "description": "A secure, lightweight, and flexible CAPTCHA module for TypeScript/JavaScript projects with cryptographic security and multi-language support",
5
+ "main": "index.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "captcha",
12
+ "security",
13
+ "cryptography",
14
+ "typescript",
15
+ "javascript",
16
+ "authentication",
17
+ "verification",
18
+ "bot-protection",
19
+ "spam-prevention",
20
+ "nist",
21
+ "owasp",
22
+ "gdpr",
23
+ "kvkk",
24
+ "sha256",
25
+ "multi-language",
26
+ "i18n",
27
+ "math-captcha",
28
+ "riddle-captcha",
29
+ "logic-captcha",
30
+ "k9crypt"
31
+ ],
32
+ "author": {
33
+ "name": "K9Crypt",
34
+ "url": "https://k9crypt.xyz/"
35
+ },
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/K9Crypt/k9guard.git"
40
+ },
41
+ "bugs": {
42
+ "url": "https://github.com/K9Crypt/k9guard/issues"
43
+ },
44
+ "homepage": "https://github.com/K9Crypt/k9guard#readme",
45
+ "engines": {
46
+ "node": ">=16.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/bun": "latest",
50
+ "@types/node": "^20.0.0",
51
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
52
+ "@typescript-eslint/parser": "^6.0.0",
53
+ "eslint": "^8.0.0",
54
+ "tsx": "^4.0.0",
55
+ "typescript": "^5.0.0"
56
+ },
57
+ "peerDependencies": {
58
+ "typescript": "^5"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public",
62
+ "registry": "https://registry.npmjs.org/"
63
+ }
64
+ }
package/src/K9Guard.ts ADDED
@@ -0,0 +1,83 @@
1
+ import type { K9GuardOptions, K9GuardCustomOptions, CaptchaChallenge, CustomQuestion } from './types';
2
+ import { CaptchaGenerator } from './core/captchaGenerator';
3
+ import { CaptchaValidator } from './core/captchaValidator';
4
+ import { CustomQuestionValidator } from './validators/customQuestionValidator';
5
+
6
+ export class K9Guard {
7
+ private options: K9GuardOptions | K9GuardCustomOptions;
8
+ private generator: CaptchaGenerator;
9
+
10
+ constructor(options: K9GuardOptions | K9GuardCustomOptions | { type: 'custom'; questions: CustomQuestion[] } = { type: 'math', difficulty: 'medium' }) {
11
+ const processedOptions = this.processOptions(options);
12
+ this.generator = new CaptchaGenerator(processedOptions);
13
+ this.options = processedOptions;
14
+ }
15
+
16
+ private processOptions(options: unknown): K9GuardOptions | K9GuardCustomOptions {
17
+ if (typeof options !== 'object' || options === null) {
18
+ return { type: 'math', difficulty: 'medium', locale: 'en' };
19
+ }
20
+
21
+ const opt = options as Record<string, unknown>;
22
+
23
+ if (opt.type === 'custom') {
24
+ if (!Array.isArray(opt.questions)) {
25
+ throw new Error('Custom type requires questions array');
26
+ }
27
+
28
+ const validation = CustomQuestionValidator.validate(opt.questions);
29
+ if (!validation.valid) {
30
+ throw new Error(`Invalid custom questions: ${validation.error}`);
31
+ }
32
+
33
+ return {
34
+ type: 'custom',
35
+ questions: CustomQuestionValidator.sanitize(opt.questions as CustomQuestion[])
36
+ } as K9GuardCustomOptions;
37
+ }
38
+
39
+ return {
40
+ type: opt.type || 'math',
41
+ difficulty: opt.difficulty || 'medium',
42
+ locale: opt.locale || 'en'
43
+ } as K9GuardOptions;
44
+ }
45
+
46
+ generate(): CaptchaChallenge {
47
+ return this.generator.generate();
48
+ }
49
+
50
+ validate(challenge: CaptchaChallenge, userInput: string): boolean {
51
+ if (!this.isValidChallenge(challenge)) {
52
+ return false;
53
+ }
54
+
55
+ if (typeof userInput !== 'string') {
56
+ return false;
57
+ }
58
+
59
+ const now = Date.now();
60
+ if (now > challenge.expiry) {
61
+ return false;
62
+ }
63
+
64
+ return CaptchaValidator.validate(challenge, userInput);
65
+ }
66
+
67
+ private isValidChallenge(challenge: unknown): boolean {
68
+ if (typeof challenge !== 'object' || challenge === null) {
69
+ return false;
70
+ }
71
+
72
+ const c = challenge as Record<string, unknown>;
73
+
74
+ return (
75
+ typeof c.type === 'string' &&
76
+ typeof c.question === 'string' &&
77
+ typeof c.nonce === 'string' &&
78
+ typeof c.expiry === 'number' &&
79
+ typeof c.hashedAnswer === 'string' &&
80
+ typeof c.salt === 'string'
81
+ );
82
+ }
83
+ }