@tatil/crypto 0.0.1 → 0.0.2
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 +141 -15
- package/index.js +114 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,37 +1,163 @@
|
|
|
1
1
|
# @tatil/crypto
|
|
2
2
|
|
|
3
|
-
Tatilsepeti
|
|
3
|
+
Tatilsepeti projeleri için şifreleme ve deşifreme işlemlerini içeren paket.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Özellikler
|
|
6
|
+
|
|
7
|
+
### API-Based Encryption/Decryption (Client-Side)
|
|
8
|
+
- Reservation ID şifreleme/deşifreleme
|
|
9
|
+
- API endpoint üzerinden işlem yapar
|
|
10
|
+
- Client-side kullanım için uygun
|
|
11
|
+
|
|
12
|
+
### Local AES-256 Encryption (Server-Side)
|
|
13
|
+
- AES-256-CBC algoritması
|
|
14
|
+
- Gzip compression ile veri sıkıştırma
|
|
15
|
+
- URL-safe base64 encoding
|
|
16
|
+
- Server-side sadece (Node.js crypto module)
|
|
17
|
+
|
|
18
|
+
## Kurulum
|
|
6
19
|
|
|
7
20
|
```bash
|
|
8
21
|
yarn add @tatil/crypto
|
|
9
22
|
```
|
|
10
23
|
|
|
11
|
-
##
|
|
24
|
+
## Kullanım
|
|
25
|
+
|
|
26
|
+
### API-Based Encryption (Client-Side)
|
|
12
27
|
|
|
13
28
|
```javascript
|
|
14
29
|
import { encryption, decryption } from '@tatil/crypto';
|
|
15
30
|
|
|
16
|
-
//
|
|
31
|
+
// Reservation ID şifreleme
|
|
17
32
|
const encryptedId = await encryption(12345);
|
|
18
33
|
|
|
19
|
-
//
|
|
20
|
-
const decryptedId = await decryption('
|
|
34
|
+
// Reservation ID deşifreleme
|
|
35
|
+
const decryptedId = await decryption('encrypted_string_here');
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Local AES-256 Encryption (Server-Side)
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { encrypt, decrypt } from '@tatil/crypto';
|
|
42
|
+
|
|
43
|
+
// Veri şifreleme
|
|
44
|
+
const data = { userId: 123, email: 'user@example.com' };
|
|
45
|
+
const encrypted = await encrypt(data);
|
|
46
|
+
// Sonuç: "base64_encoded_string"
|
|
47
|
+
|
|
48
|
+
// Veri deşifreleme
|
|
49
|
+
const decrypted = await decrypt(encrypted);
|
|
50
|
+
// Sonuç: { userId: 123, email: 'user@example.com' }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Environment Variables
|
|
54
|
+
|
|
55
|
+
```env
|
|
56
|
+
CRYPTO_SECRET_KEY=your_32_byte_secret_key_here
|
|
21
57
|
```
|
|
22
58
|
|
|
23
|
-
|
|
59
|
+
**Önemli:** `encrypt` ve `decrypt` fonksiyonları için `CRYPTO_SECRET_KEY` environment variable'si gereklidir.
|
|
60
|
+
|
|
61
|
+
## API Reference
|
|
62
|
+
|
|
63
|
+
### encryption(value)
|
|
64
|
+
Reservation ID'yi şifreler (API tabanlı)
|
|
65
|
+
|
|
66
|
+
- **Parametreler:** `value` (string|number) - Şifrelenecek değer
|
|
67
|
+
- **Dönüş:** Promise<string> - Şifrelenmiş değer
|
|
68
|
+
- **Kullanım:** Client-side
|
|
69
|
+
|
|
70
|
+
### decryption(value)
|
|
71
|
+
Şifrelenmiş Reservation ID'yi çözer (API tabanlı)
|
|
72
|
+
|
|
73
|
+
- **Parametreler:** `value` (string|number) - Çözülecek şifreli değer
|
|
74
|
+
- **Dönüş:** Promise<number> - Çözülmüş sayısal değer
|
|
75
|
+
- **Kullanım:** Client-side
|
|
76
|
+
|
|
77
|
+
### encrypt(data, secretKey?)
|
|
78
|
+
Veriyi AES-256-CBC ile şifreler (Yerel)
|
|
79
|
+
|
|
80
|
+
- **Parametreler:**
|
|
81
|
+
- `data` (Object|string) - Şifrelenecek veri
|
|
82
|
+
- `secretKey` (string, optional) - Gizli anahtar (default: process.env.CRYPTO_SECRET_KEY)
|
|
83
|
+
- **Dönüş:** Promise<string> - Base64 encoded şifreli veri
|
|
84
|
+
- **Kullanım:** Server-side only
|
|
85
|
+
|
|
86
|
+
### decrypt(encryptedData, secretKey?)
|
|
87
|
+
Şifrelenmiş veriyi çözer (Yerel)
|
|
88
|
+
|
|
89
|
+
- **Parametreler:**
|
|
90
|
+
- `encryptedData` (string) - Şifreli veri (base64)
|
|
91
|
+
- `secretKey` (string, optional) - Gizli anahtar (default: process.env.CRYPTO_SECRET_KEY)
|
|
92
|
+
- **Dönüş:** Promise<Object|string> - Çözülmüş veri
|
|
93
|
+
- **Kullanım:** Server-side only
|
|
24
94
|
|
|
25
|
-
|
|
95
|
+
## Bağımlılıklar
|
|
26
96
|
|
|
27
|
-
|
|
97
|
+
- `@tatil/client-api`: API-based işlemler için
|
|
98
|
+
- `crypto` (Node.js built-in): AES-256 şifreleme için
|
|
99
|
+
- `zlib` (Node.js built-in): Gzip compression için
|
|
100
|
+
|
|
101
|
+
## Örnek Kullanım Senaryoları
|
|
102
|
+
|
|
103
|
+
### 1. Reservation ID Şifreleme (URL'de güvenli taşıma)
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
// Client-side
|
|
107
|
+
import { encryption } from '@tatil/crypto';
|
|
108
|
+
|
|
109
|
+
const reservationId = 12345;
|
|
110
|
+
const encryptedId = await encryption(reservationId);
|
|
111
|
+
|
|
112
|
+
// URL oluşturma
|
|
113
|
+
const url = `/reservation/${encodeURIComponent(encryptedId)}`;
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 2. Server-Side Veri Şifreleme
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Server component veya API route
|
|
120
|
+
import { encrypt, decrypt } from '@tatil/crypto';
|
|
121
|
+
|
|
122
|
+
// Hassas veriyi şifreleme
|
|
123
|
+
const userData = {
|
|
124
|
+
id: 123,
|
|
125
|
+
email: 'user@example.com',
|
|
126
|
+
phone: '+905551234567'
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const encrypted = await encrypt(userData);
|
|
130
|
+
|
|
131
|
+
// Veriyi geri çözme
|
|
132
|
+
const decrypted = await decrypt(encrypted);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 3. Next.js API Route
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// app/api/v5/crypto/route.js
|
|
139
|
+
import { encrypt, decrypt } from '@tatil/crypto';
|
|
140
|
+
import { createResponse, createErrorResponse } from '@tatil/server-api';
|
|
141
|
+
|
|
142
|
+
export const POST = async (request) => {
|
|
143
|
+
const { action, data } = await request.json();
|
|
144
|
+
|
|
145
|
+
if (action === 'encrypt') {
|
|
146
|
+
const encrypted = await encrypt(data);
|
|
147
|
+
return createResponse('success', encrypted);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (action === 'decrypt') {
|
|
151
|
+
const decrypted = await decrypt(data);
|
|
152
|
+
return createResponse('success', decrypted);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
```
|
|
28
156
|
|
|
29
|
-
|
|
30
|
-
- **Returns:** Promise<string> - The encrypted value
|
|
157
|
+
## Lisans
|
|
31
158
|
|
|
32
|
-
|
|
159
|
+
MIT
|
|
33
160
|
|
|
34
|
-
|
|
161
|
+
## İletişim
|
|
35
162
|
|
|
36
|
-
|
|
37
|
-
- **Returns:** Promise<number> - The decrypted number value
|
|
163
|
+
Sorularınız için: Yaşar İçli <yasar.icli@tatilsepeti.com>
|
package/index.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import zlib from 'zlib';
|
|
3
|
+
import { promisify } from 'util';
|
|
1
4
|
import ClientApi from '@tatil/client-api';
|
|
2
5
|
|
|
6
|
+
// Variables
|
|
7
|
+
const ALGORITHM = 'aes-256-cbc';
|
|
8
|
+
const gzip = promisify(zlib.gzip);
|
|
9
|
+
const gunzip = promisify(zlib.gunzip);
|
|
10
|
+
|
|
11
|
+
const { CRYPTO_SECRET_KEY } = process.env;
|
|
12
|
+
|
|
13
|
+
// ============================================================
|
|
14
|
+
// API-BASED ENCRYPTION/DECRYPTION (Reservation IDs)
|
|
15
|
+
// ============================================================
|
|
16
|
+
|
|
3
17
|
/**
|
|
4
18
|
* Encrypts a value using the reservation encryption endpoint
|
|
5
19
|
* @param {string|number} value - The value to encrypt
|
|
@@ -36,7 +50,107 @@ export const decryption = async (value) => {
|
|
|
36
50
|
}
|
|
37
51
|
};
|
|
38
52
|
|
|
53
|
+
// ============================================================
|
|
54
|
+
// LOCAL AES-256 ENCRYPTION/DECRYPTION (Server-side only)
|
|
55
|
+
// ============================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Compress data using gzip
|
|
59
|
+
* @param {string} jsonString - JSON string to compress
|
|
60
|
+
* @returns {Buffer} - Compressed data
|
|
61
|
+
*/
|
|
62
|
+
const compress = async (jsonString) => {
|
|
63
|
+
return await gzip(jsonString, { level: 9 });
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Decompress data using gzip
|
|
68
|
+
* @param {Buffer} compressedData - Compressed data
|
|
69
|
+
* @returns {string} - Decompressed string
|
|
70
|
+
*/
|
|
71
|
+
const decompress = async (compressedData) => {
|
|
72
|
+
return await gunzip(compressedData);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Encrypt data using AES-256-CBC with compression
|
|
77
|
+
* @param {Object|string} data - Data to encrypt
|
|
78
|
+
* @param {string} secretKey - Secret key (default: process.env.CRYPTO_SECRET_KEY)
|
|
79
|
+
* @returns {string} - Encrypted data (IV + encrypted content, base64 encoded)
|
|
80
|
+
* @throws {Error} - If CRYPTO_SECRET_KEY is not set
|
|
81
|
+
*/
|
|
82
|
+
export const encrypt = async (data, secretKey) => {
|
|
83
|
+
const key = secretKey || CRYPTO_SECRET_KEY;
|
|
84
|
+
|
|
85
|
+
if (!key) {
|
|
86
|
+
throw new Error('CRYPTO_SECRET_KEY environment variable is not set');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const jsonString = typeof data === 'string' ? data : JSON.stringify(data);
|
|
90
|
+
|
|
91
|
+
// Compress the data first
|
|
92
|
+
const compressed = await compress(jsonString);
|
|
93
|
+
|
|
94
|
+
const iv = crypto.randomBytes(16);
|
|
95
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
96
|
+
|
|
97
|
+
let encrypted = cipher.update(compressed);
|
|
98
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
99
|
+
|
|
100
|
+
// Combine IV and encrypted data
|
|
101
|
+
const combined = Buffer.concat([iv, encrypted]);
|
|
102
|
+
|
|
103
|
+
// Convert to base64 for URL safety
|
|
104
|
+
return combined.toString('base64');
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Decrypt data using AES-256-CBC with decompression
|
|
109
|
+
* @param {string} encryptedData - Encrypted data (base64 encoded)
|
|
110
|
+
* @param {string} secretKey - Secret key (default: process.env.CRYPTO_SECRET_KEY)
|
|
111
|
+
* @returns {Object|string} - Decrypted data
|
|
112
|
+
* @throws {Error} - If CRYPTO_SECRET_KEY is not set
|
|
113
|
+
*/
|
|
114
|
+
export const decrypt = async (encryptedData, secretKey) => {
|
|
115
|
+
const key = secretKey || CRYPTO_SECRET_KEY;
|
|
116
|
+
|
|
117
|
+
if (!key) {
|
|
118
|
+
throw new Error('CRYPTO_SECRET_KEY environment variable is not set');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Decode from base64
|
|
122
|
+
const combined = Buffer.from(encryptedData, 'base64');
|
|
123
|
+
|
|
124
|
+
// Extract IV (first 16 bytes) and encrypted data
|
|
125
|
+
const iv = combined.subarray(0, 16);
|
|
126
|
+
const encrypted = combined.subarray(16);
|
|
127
|
+
|
|
128
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
129
|
+
|
|
130
|
+
let decrypted = decipher.update(encrypted);
|
|
131
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
132
|
+
|
|
133
|
+
// Decompress the data
|
|
134
|
+
const decompressed = await decompress(decrypted);
|
|
135
|
+
const decompressedString = decompressed.toString('utf8');
|
|
136
|
+
|
|
137
|
+
// Try to parse as JSON, return as string if fails
|
|
138
|
+
const parseJson = (text) => {
|
|
139
|
+
try {
|
|
140
|
+
return JSON.parse(text);
|
|
141
|
+
} catch {
|
|
142
|
+
return text;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return parseJson(decompressedString);
|
|
147
|
+
};
|
|
148
|
+
|
|
39
149
|
export default {
|
|
150
|
+
// API-based
|
|
40
151
|
encryption,
|
|
41
152
|
decryption,
|
|
153
|
+
// Local AES-256
|
|
154
|
+
encrypt,
|
|
155
|
+
decrypt,
|
|
42
156
|
};
|