یک ماژول رمزنگاری (Crypto/Encryption) در زبان Go که با تمرکز بر امنیت، کارایی (Performance)، توسعهپذیری و رعایت استانداردهای حرفهای مهندسی نرمافزار طراحی شده است.
- Backend Serviceها
- Microservices
- سیستمهای ذخیرهسازی امن
- Secret Management
- Encryption Layer برای دادههای حساس
- فایلهای بزرگ (Streaming Encryption)
- رعایت idiomatic Go
- استفاده از best practiceهای مدرن رمزنگاری
- حداقل API Surface ولی قدرتمند
- قابلیت افزودن الگوریتمهای جدید بدون شکستن API
- استفاده از Authenticated Encryption
- مدیریت صحیح nonce و salt
- جلوگیری از الگوریتمهای ناامن یا deprecated
- کارایی بالا و حداقل allocation غیرضروری
- پشتیبانی از streaming برای دادههای بزرگ
- قابلیت Versioning برای backward compatibility
go get github.com/Skryldev/crypto| قابلیت | تکنولوژی | توضیحات و دلیل استفاده |
|---|---|---|
| Symmetric Encryption | AES-256-GCM | الگوریتم رمزنگاری متقارن با امنیت بالا و پشتیبانی از Authenticated Encryption (حفظ محرمانگی و صحت دادهها). مناسب برای دادههای حساس. |
| Key Derivation | PBKDF2 (SHA-256) | مشتقسازی امن کلید از پسورد، جلوگیری از brute-force و dictionary attack. استفاده از SHA-256 باعث افزایش مقاومت میشود. |
| Random | crypto/rand | تولید عدد تصادفی امن برای nonce، salt و کلیدها. استفاده از secure random باعث جلوگیری از پیشبینیپذیری میشود. |
| Encoding | base64 | تبدیل دادههای باینری به رشته برای ذخیره یا انتقال امن، بدون دستکاری محتوا. |
| AEAD | cipher.AEAD | Authenticated Encryption with Associated Data. تضمین میکند داده رمزنگاری شده تغییر نکرده و احراز اصالت انجام شده است. |
keyGen := crypto.DefaultKeyGenerator{}
key, err := keyGen.Generate(32) // 32 bytes = 256 bit
if err != nil {
panic(err)
}ctx := context.Background()
cipher, err := crypto.NewAESGCM(key)
if err != nil {
panic(err)
}plaintext := []byte("پیام محرمانه")
ciphertext, err := cipher.Encrypt(ctx, plaintext, nil)
if err != nil {
panic(err)
}decrypted, err := cipher.Decrypt(ctx, ciphertext, nil)
if err != nil {
panic(err)
}
fmt.Println(string(decrypted))aad := []byte("user-id-123")
ciphertext, _ := cipher.Encrypt(ctx, plaintext, aad)
decrypted, _ := cipher.Decrypt(ctx, ciphertext, aad)salt, err := crypto.GenerateSalt()
if err != nil {
panic(err)
}password := []byte("strong-password")
derivedKey := crypto.DeriveKey(
password,
salt,
crypto.DefaultIter,
crypto.DefaultKeySize,
)cipher, _ := crypto.NewAESGCM(derivedKey)
plaintext, _ := cipher.Decrypt(ctx, ciphertext, nil)inputFile, _ := os.Open("input.txt")
outputFile, _ := os.Create("encrypted.bin")
defer inputFile.Close()
defer outputFile.Close()
err := crypto.EncryptStream(cipher, inputFile, outputFile)
if err != nil {
panic(err)
}encFile, _ := os.Open("encrypted.bin")
decFile, _ := os.Create("decrypted.txt")
defer encFile.Close()
defer decFile.Close()
err := crypto.DecryptStream(cipher, encFile, decFile)
if err != nil {
panic(err)
}- توضیح: هر chunk جداگانه رمزگشایی میشود تا حافظه اشباع نشود.
- حافظه را اشباع نمیکند
- chunk-based است
- مناسب فایلهای چند گیگابایتی
- ✔ از AES-256-GCM استفاده میشود
- ✔ Nonce به صورت امن تولید میشود
- ✔ از crypto/rand استفاده شده
- ✔ از الگوریتم deprecated استفاده نشده
- ✔ از AEAD استفاده شده (Confidentiality + Integrity)
- ✔ مقایسهها constant-time هستند
- ✔ API سطح حمله کوچک دارد
- هرگز کلید را hardcode نکنید
- کلیدها را در KMS یا Vault نگهداری کنید
- از rotation دورهای استفاده کنید
- Salt و Version را ذخیره کنید
- برای production از Argon2id (در صورت نیاز) استفاده کنید
- کلیدها را در log چاپ نکنید
func main() {
ctx := context.Background()
fmt.Println("=== 🔐 مثال جامع ماژول Crypto ===")
// 1️⃣ تولید کلید تصادفی
keyGen := crypto.DefaultKeyGenerator{}
key, _ := keyGen.Generate(32) // 256-bit key
// 2️⃣ ساخت AES-GCM cipher با کلید
cipher, _ := crypto.NewAESGCM(key)
// 3️⃣ پیام اصلی و AAD
plaintext := []byte("سلام! این یک پیام محرمانه است.")
aad := []byte("user-id-123")
// 4️⃣ Encrypt معمولی
ciphertext, _ := cipher.Encrypt(ctx, plaintext, aad)
fmt.Println("Ciphertext (Base64):", crypto.ToBase64(ciphertext))
// 5️⃣ Decrypt معمولی
decrypted, _ := cipher.Decrypt(ctx, ciphertext, aad)
fmt.Println("Decrypted:", string(decrypted))
// 6️⃣ استفاده از PBKDF2 برای پسورد
password := []byte("strong-password")
salt, _ := crypto.GenerateSalt()
derivedKey := crypto.DeriveKey(password, salt, crypto.DefaultIter, crypto.DefaultKeySize)
cipherFromPassword, _ := crypto.NewAESGCM(derivedKey)
pbeCiphertext, _ := cipherFromPassword.Encrypt(ctx, plaintext, aad)
pbeDecrypted, _ := cipherFromPassword.Decrypt(ctx, pbeCiphertext, aad)
fmt.Println("PBKDF2 Decrypted:", string(pbeDecrypted))
// 7️⃣ Wrap کردن ciphertext در envelope versioned
wrapped := crypto.Wrap(crypto.Version1, ciphertext)
env, _ := crypto.Unwrap(wrapped)
fmt.Printf("Envelope Version: %x, Data Length: %d\n", env.Version, len(env.Data))
// 8️⃣ Base64 encode/decode
encoded := crypto.ToBase64(ciphertext)
decoded, _ := crypto.FromBase64(encoded)
fmt.Println("Decoded Base64 matches original?", string(decoded) == string(ciphertext))
// 9️⃣ Streaming Encryption / Decryption (فایلهای بزرگ)
// ایجاد فایل ورودی برای مثال
os.WriteFile("input.txt", plaintext, 0644)
inputFile, _ := os.Open("input.txt")
encryptedFile, _ := os.Create("encrypted.bin")
defer inputFile.Close()
defer encryptedFile.Close()
// EncryptStream
err := crypto.EncryptStream(cipher, inputFile, encryptedFile)
if err != nil {
panic(err)
}
fmt.Println("✅ فایل رمزنگاری شد: encrypted.bin")
// DecryptStream
encFile, _ := os.Open("encrypted.bin")
decFile, _ := os.Create("decrypted.txt")
defer encFile.Close()
defer decFile.Close()
err = crypto.DecryptStream(cipher, encFile, decFile)
if err != nil {
panic(err)
}
fmt.Println("✅ فایل رمزگشایی شد: decrypted.txt")
// خواندن خروجی برای بررسی
decryptedFile, _ := os.ReadFile("decrypted.txt")
fmt.Println("Decrypted file content:", string(decryptedFile))
}- Encryption همیشه همراه با AEAD انجام شود تا صحت و محرمانگی تضمین شود.
- Streaming Encryption فقط برای دادههای بزرگ کاربرد دارد.
- Envelope Versioned و Key Rotation برای سیستمهای Enterprise و long-lived data ضروری است.
- Base64 / Hex صرفاً برای storage/transfer استفاده میشود، خود encryption نیست.
- PBKDF2 / Argon2id برای تولید کلید از پسورد و جلوگیری از brute-force.
- Plug-able Cipher Interface امکان توسعه الگوریتمها بدون شکستن API را فراهم میکند.
- AES-GCM و AEAD بهترین روش symmetric encryption برای دادههای حساس است.
- Envelope Versioned برای key rotation و آیندهنگر بودن ضروری است.
- PBKDF2 / Argon2id تنها روش مناسب برای پسورد یا derivation از password است.
- Base64 فقط encoding است و امنیت اضافه نمیکند، فقط برای انتقال یا storage رشتهای کاربرد دارد.
- Streaming Encryption برای دادههای بزرگ و فایلهای حجیم حیاتی است.
- Nonce و Salt برای هر encrypt/derive باید منحصر به فرد باشند.
- کلیدها نباید در کد hardcoded باشند؛ از Vault / KMS / HSM استفاده کنید.
| نوع داده | حجم/اندازه | روش پیشنهادی | جزئیات و نکات امنیتی | استفاده از Base64 | Versioned Envelope | Streaming |
|---|---|---|---|---|---|---|
| Access Token | کوچک (<1KB) | AES-GCM Encrypt | AEAD تضمین محرمانگی و صحت، کلید از KMS/Vault | ✅ اگر DB رشتهای است | اختیاری | ❌ |
| Refresh Token | کوچک (<1KB) | AES-GCM Encrypt + Envelope Versioned | امکان key rotation و backward compatibility، ذخیره metadata | ✅ | ✅ | ❌ |
| Password (User) | کوچک | PBKDF2 / Argon2id → Store hash | هیچوقت plaintext ذخیره نشود، salt منحصر به فرد برای هر کاربر | ❌ | ❌ | ❌ |
| Short Secrets (API Keys) | کوچک | AES-GCM Encrypt | AEAD برای integrity | ✅ | اختیاری | ❌ |
| Large JSON / Blob / Logs | بزرگ (>1MB) | EncryptStream | chunk-based، memory-efficient، integrity هر chunk حفظ میشود | ✅ برای انتقال / storage رشتهای | اختیاری | ✅ |
| PDF / Document / Binary Files | بزرگ (>1MB) | EncryptStream | مناسب ذخیره در Object Storage، memory-efficient | ✅ اختیاری | اختیاری | ✅ |
| Critical / Sensitive Data | کوچک تا متوسط | AES-GCM Encrypt + Envelope Versioned | نسخهبندی، key rotation، metadata برای آینده | ✅ | ✅ | ❌ |
| Data with Context (AAD) | کوچک تا متوسط | AES-GCM Encrypt + AAD | تضمین integrity همراه با context اضافی | ✅ | اختیاری | ❌ |
- کلیدها جدا از DB ذخیره شوند (Vault / KMS / HSM)
- Nonce و Salt برای هر داده منحصر به فرد باشند
- Base64 فقط برای storage یا انتقال رشتهای استفاده شود
- Streaming Encryption برای فایلها و دادههای بزرگ الزامی است
- Versioned Envelope برای data lifecycle طولانی یا حساس توصیه میشود
- PBKDF2 / Argon2id برای پسوردها یا derivation از password امنترین روش است
💡 خلاصه ذهنی:
- داده کوچک → Encrypt معمولی + Base64 کافی است
- داده حساس و طولانیمدت → Envelope Versioned + AES-GCM
- فایل یا blob بزرگ → Streaming Encryption
- پسورد → Hash امن (PBKDF2/Argon2id)
- امن (Secure by Default)
- سریع (High Performance)
- توسعهپذیر (Extensible)
- versioned
- production-ready
- سیستمهای