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 +235 -0
- package/docs/tr/README.md +235 -0
- package/index.ts +4 -0
- package/package.json +64 -0
- package/src/K9Guard.ts +83 -0
- package/src/core/captchaGenerator.ts +233 -0
- package/src/core/captchaValidator.ts +117 -0
- package/src/locale/en.json +46 -0
- package/src/locale/tr.json +46 -0
- package/src/types/index.ts +72 -0
- package/src/utils/customQuestionGenerator.ts +40 -0
- package/src/utils/logicGenerator.ts +18 -0
- package/src/utils/random.ts +43 -0
- package/src/utils/reverseGenerator.ts +50 -0
- package/src/utils/riddleBank.ts +18 -0
- package/src/utils/scrambleGenerator.ts +37 -0
- package/src/utils/sequenceGenerator.ts +33 -0
- package/src/validators/customQuestionValidator.ts +88 -0
- package/tsconfig.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+

|
|
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
|
+

|
|
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
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
|
+
}
|