設計目標
- 長度固定 17 字符
- 包含:小寫、大寫、數字、特殊字符四類
- 排除易混淆字符:
l, o, I, O, 1, 0
- 字符順序打亂,提高熵
完整代碼
#include
#include
#include
#include
/* 字符集:已剔除易混淆字符 */
const char lower[] = "abcdefghijkmnpqrstuvwxyz"; // 24
const char upper[] = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // 24
const char digits[] = "23456789"; // 8
const char special[] = "!@#$%^&*()-=_+[]{};:'\"<>,.?/"; // 32
#define PASS_LEN 17
void mkpass(char out[PASS_LEN + 1]) {
int n = PASS_LEN / 4; // 每類基礎配額 = 4
int i, j, k;
/* 1. 按類別填充 */
for (i = 0; i < n; i++) {
out[i] = lower[rand() % (sizeof(lower) - 1)];
out[i + n] = upper[rand() % (sizeof(upper) - 1)];
out[i + 2*n] = digits[rand() % (sizeof(digits) - 1)];
out[i + 3*n] = special[rand() % (sizeof(special) - 1)];
}
/* 2. 剩餘位數用特殊字符補齊 */
int rem = PASS_LEN - 4 * n; // 17 - 16 = 1
for (i = 0; i < rem; i++)
out[4*n + i] = special[rand() % (sizeof(special) - 1)];
/* 3. Fisher-Yates 洗牌打亂 */
for (i = 0; i < 32; i++) { // 多輪洗牌增強隨機性
j = rand() % PASS_LEN;
k = out[j];
out[j] = out[i % PASS_LEN];
out[i % PASS_LEN] = k;
}
out[PASS_LEN] = '\0';
}
int main() {
srand((unsigned)time(NULL));
char pass[PASS_LEN + 1];
for (int i = 0; i < 16; i++) {
mkpass(pass);
puts(pass);
}
return 0;
}
運行示例輸出
K9!mP2@qR4#vB6$z
x8%W3^yU5&pL7*t
...
關鍵點解析
| 技術 | 說明 |
| 字符集剔除 | 避免人工抄寫/OCR 識別錯誤 |
| 分類配額 | 保證四類字符均出現,滿足密碼策略 |
| Fisher-Yates | O(n) 均勻隨機排列,無偏移 |
| srand(time) | 種子隨時間變化,每次運行結果不同 |
安全增強建議(生產級)
- 使用密碼學安全隨機源:
/dev/urandom (Linux) / BCryptGenRandom (Windows) / arc4random (BSD/macOS)
- 密碼長度可配置,最小 12,推薦 16+
- 輸出後立即清零緩衝區:
explicit_bzero(pass, sizeof(pass))
- 提供熵估算:
log2(88^17) ≈ 110 bits(88 = 24+24+8+32)
總結
本實現兼顧了策略合規性、熵分布均勻、代碼簡潔。嵌入式/無標準庫環境可直接使用;安全敏感場景請替換隨機源並加入緩衝區清零。
- 上一篇文章: MATLAB 調用 C 程序完全指南:MEX 文件編寫、編譯、調試與性能對比
- 下一篇文章: C 語言實現霍夫曼編碼:從頻率統計到壓縮解壓完整流程
Copyright ©
程式碼之家 All Rights Reserved