雙因素認證(Two-Factor Authentication, 2FA)扮演著至關重要的角色。它像是一道額外的防線,確保即便密碼被竊取,不法分子也難以輕易突破。在眾多雙因素認證技術中,基于時間的一次性密碼(Time-Based One-Time Password, TOTP)算法因其安全性高、使用便捷而受到廣泛應用。
TOTP算法是一種基于時間的一次性密碼生成算法,它的核心思想是利用時間作為變化的因子來生成動態的密碼。這種算法通常與用戶的個人信息結合使用,如用戶名或電子郵件地址,以及一個共享的秘密密鑰。這個秘密密鑰在用戶端和服務端預先共享,是生成正確OTP的關鍵。
TOTP是如何工作的呢?
讓我們通過一個簡單的比喻來理解其原理。想象一下,你有一本只屬于你和你的朋友的書,書中記載了一連串的故事,每個故事都有一個編號。每當你想要和朋友傳遞一個秘密信息時,你會查找當前日期對應的故事編號,并從中選取特定的段落來傳遞信息。在這個例子中,書就像是秘密密鑰,故事編號對應于時間戳,而傳遞的信息則是一次性密碼。
具體到TOTP算法,它使用了哈希函數(如SHA-1、SHA-256等)和時間戳。當用戶想要登錄系統時,用戶的設備會計算當前時間與預設時間步長的差值,然后將這個差值與共享的秘密密鑰一起輸入到哈希函數中。哈希函數處理后輸出一串較長的二進制數據,這串數據再經過模運算,得到一個較短的數字,這個數字就是OTP。用戶需要在規定的時間內將這個OTP輸入到驗證系統中,系統同樣會根據相同的秘密密鑰和時間差值計算出一個OTP,并與用戶提供的OTP進行比對,若兩者一致,則認證成功。
在實現上,TOTP算法需要考慮到時間同步的問題。由于網絡延遲或者設備時鐘不準確,可能導致用戶設備與服務器之間的時間有偏差。因此,TOTP算法通常會有一個時間窗口(如30秒),允許在這個時間范圍內的OTP都是有效的。
TOTP的優勢在于其安全性和用戶體驗。由于OTP是基于時間和共享秘密密鑰生成的,即使黑客截獲了某個時刻的OTP,它也無法在其他時間點使用,因為OTP每隔一段時間就會變化。此外,用戶可以不需要記憶復雜的密碼,只需擁有注冊時分配的密鑰(通常存儲在硬件令牌或軟件應用中),就可以輕松完成身份驗證。
TOTP的實現
Base32編碼與解碼
Base32編碼原理:
Base32編碼是一種將二進制數據轉換成32種可打印字符的編碼方式。它主要用于電子郵件和URL中傳輸二進制數據。Base32使用A-Z的大寫字母(不使用C, E, G, I, O, Q, U, V)和數字2-7來表示數據。每8位二進制數據可以編碼為5個Base32字符,這意味著編碼后的數據長度是原始數據的大約1.33倍。
實現Base32編碼:
編碼過程涉及將輸入的字節數據分成5位一組,每組轉換為對應的Base32字符。例如,如果輸入字節是0x9A
,它對應于二進制的10011010
,然后將其分成兩組:1001
和1010
。每組轉換為Base32字符,分別是S
和K
。
實現Base32解碼:
解碼過程與編碼相反,它將Base32字符轉換回原始的字節數據。解碼函數需要處理輸入的Base32字符串,跳過任何非Base32字符(如填充的等號),并將每個字符轉換回相應的5位二進制值。然后,這些值被重新組合成字節數據。
HMAC-SHA1算法
HMAC-SHA1基本概念:
HMAC(Hash-based Message Authentication Code)是一種消息認證碼,它使用哈希算法(如SHA-1)和密鑰來提供消息的完整性保護和認證。SHA-1是一種廣泛使用的加密哈希函數,它可以產生一個160位(20字節)的哈希值。
在TOTP中的應用:
在TOTP中,HMAC-SHA1用于生成一個基于密鑰、時間戳和算法參數的哈希值。這個哈希值隨后被用來生成6位數的一次性密碼。通過使用HMAC-SHA1,TOTP確保了即使密鑰被泄露,生成的密碼也難以被預測。
時間戳處理
時間戳的重要性:
TOTP算法依賴于時間戳來生成密碼,因此時間同步至關重要。如果客戶端和服務器之間的時間不同步,生成的密碼可能會無效。
確保時間同步:
為了確保時間同步,可以采取以下措施:
- 使用網絡時間協議(NTP)來同步客戶端和服務器的時間。
- 在用戶設備上設置時間校驗機制,確保時間偏差在可接受范圍內。
密碼生成邏輯
從HMAC-SHA1輸出中提取密碼:
- 使用HMAC-SHA1算法和當前時間戳生成一個20字節的哈希值。
- 對哈希值進行處理,提取出用于生成密碼的部分。具體來說,取哈希值的最后一個字節的最低4位作為索引,從這個位置開始讀取接下來的4個字節。
- 將這4個字節視為一個整數,然后對
1000000
取模,得到一個6位數的密碼。
生成6位數的密碼:
- 將上述步驟得到的整數轉換為字符串形式,并確保它是一個6位數的密碼。如果需要,可以在前面補零。
TOTP 算法實現:雙因素認證的基石(C/C++代碼實現)
雙因素認證(2FA)作為一種增強安全性的方法應運而生。基于時間的一次性密碼(TOTP)是2FA的一種實現方式,它提供了一種動態生成、一次性使用的密碼,極大地提高了賬戶的安全性。下面實現類似Google Authenticator這樣的應用程序。
void hmac(void *dest,const void *key,uint32_t key_len,const void *msg,uint32_t msg_len,void (*hash)(char *dest, const char *str, int len),uint16_t block_size,uint16_t output_size
);
typedef struct
{uint32_t state[5];uint32_t count[2];unsigned char buffer[64];
} SHA1_CTX;void sha1_transform(uint32_t state[5], const unsigned char buffer[64]);
void sha1_init(SHA1_CTX * context);
void sha1_update(SHA1_CTX * context, const unsigned char *data, uint32_t len);
void sha1_final(unsigned char digest[20], SHA1_CTX * context);
void sha1(char *hash_out, const char *str, int len);
void bytes_array_reverse(uint8_t* bytes, int size);
int bytes_array_to_int(const uint8_t* bytes, int start, int end);
int base32_decode(const uint8_t *encoded, uint8_t *result, int bufSize);
char* str_upper(char* str);
char* str_pad_left(char* str, char pad, int len);
char* str_pad_right(char* str, char pad, int len);
int int_to_str(int i, char *buf, int buf_len);void get_2fa_code(char *secret, char code[7])
{char key[20];char hash[20];int key_len;uint64_t msg;str_upper(secret); //轉換為大寫以獲得有效的Base32格式key_len = base32_decode((uint8_t*)secret, (uint8_t*)key, 20); // 將機密解碼為字節數組msg = time(NULL) / 30; // TOTP是HOTP,種子為30秒。bytes_array_reverse((uint8_t*)&msg, 8); hmac(hash, key, key_len, (uint8_t*)&msg, 8, sha1, 64, 20); // 生成hmac哈希int offset = hash[19] & 0xF; int header = bytes_array_to_int((uint8_t*)hash, offset, offset + 4); // 從偏移量開始截斷4個字節header = header & 0x7fffffff; // 刪除最高有效位header = header % 1000000; // 生成小于7位的余數int_to_str(header, code, 7); // 將代碼轉換為字符串str_pad_left(code, '0', 6); // 從左起用0填充代碼,直到代碼長度為6
}
int main(int argc, char **argv)
{
...if (argc != 2) {printf("./ga [secret]\n");return (0);}get_2fa_code(argv[1], code);printf("Code :\n%s\n", code);return (0);
}
運行結果:
If you need the complete source code, please add the WeChat number (c17865354792)
總結
Google Authenticator 的核心原理是利用共享密鑰和一個隨時間變化的因子來生成一次性密碼,從而實現第二因素的身份驗證。這種方法既方便又安全,因為它不需要額外的硬件令牌,只需要用戶的智能設備即可。此外,由于 OTP 是一次性的,并且隨時間變化,即使黑客截獲了當前的 OTP,也無法在未來的時間點使用它來冒充用戶。
We also undertake the development of program requirements here. If necessary, please follow the WeChat official account 【程序猿編碼】and contact me