Bài giảng Lập trình an toàn - Chương 5: Hàm băm và xác thực thông điệp cung cấp cho người học các kiến thức: Các loại hàm băm và MAC thông dụng, băm với OpenSSL, băm dữ liệu với CryptoAPI, xác thực thông điệp với HMAC, Salt. Mời các bạn cùng tham khảo nội dung chi tiết.
Chương 5 Hàm băm và xác thực thông điệp Hashes and Message Authentication Lương Ánh Hoàng hoangla@soict.hut.edu.vn Nội dung 5.1 Các loại hàm băm và MAC thông dụng 5.2 Băm với OpenSSL 5.3 Băm dữ liệu với CryptoAPI 5.4 Xác thực thông điệp với HMAC 5.5 Salt 82 5.1 Các hàm băm và MAC thông dụng • Hàm băm (hashes) – Nhận đầu vào là một xâu và đầu ra là một chuỗi bit có chiều dài xác định – Tỉ lệ đụng độ rất nhỏ – Dùng để kiểm tra tính tồn vẹn của dữ liệu nhưng khơng đảm bảo tính xác thực của dữ liệu – Thường kết hợp với mơ hình mã hóa cơng khai chứ khơng sử dụng mình – Các giải thuật băm thơng dụng: MD5, SHA1 83 5.1 Các hàm băm và MAC thơng dụng • Hàm băm (hashes) Algorithm Digest size Small message Security conqidence speed (64 bytes), in cycles per byte[2] Large message speed (8K), in cycles per byte Uses block cipher Davies-‐Meyer-‐ AES-‐128 128 bits (same length Good as cipher block size) 46.7 cpb 57.8 cpb Yes MD2 128 bits Good to low 392 cpb 184 cpb No MD4 128 bits Insecure 32 cpb 5.8 cpb No MD5 128 bits Very low, may be insecure 40.9 cpb 7.7 cpb No MDC-‐2-‐AES-‐128 256 bits Very high 93 cpb 116 cpb Yes MDC-‐2-‐DES 128 bits Good 444 cpb 444 cpb Yes RIPEMD-‐160 160 bits High 62.2 cpb 20.6 cpb No SHA1 160 bits High 53 cpb 15.9 cpb No SHA-‐256 256 bits Very high 119 cpb 116 cpb No SHA-‐384 384 bits Very high 171 cpb 166 cpb No SHA-‐512 512 bits Very high 171 cpb 166 cpb No 84 5.1 Các hàm băm và MAC thơng dụng • Xác thực thông điệp (Message Authentication Code) – Nhận đầu vào là một xâu và một khóa bí mật, đầu ra là một mã có chiều dài xác định – Dùng để kiểm tra tính tồn vẹn và xác thực của dữ liệu – Các giải thuật thông dụng: OMAC, CMAC, HMAC 85 5.1 Các hàm băm và MAC thông dụng • Xác thực thông điệp (Message Authentication Code) MAC Built upon Small message Large message speed (64 speed (8K) bytes)[4] Appropriate for hardware Patent restric-‐ tions Parallel-‐izable CMAC A universal hash ~18 cpb and AES ~18 cpb Yes No Yes HMAC-‐SHA1 Message digest function 90 cpb 20 cpb Yes No No MAC127 hash127 + AES ~6 cpb ~6 cpb Yes No Yes OMAC1 AES 29.5 cpb 37 cpb Yes No No OMAC2 AES 29.5 cpb 37 cpb Yes No No PMAC-‐AES Block cipher 72 cpb 70 cpb Yes Yes Yes RMAC Block cipher 89 cpb 80 cpb Yes No No UMAC32 UHASH and AES 19 cpb cpb No No Yes XMACC-‐SHA1 Any cipher or MD function 29 cpb Yes Yes Yes 162 cpb 86 5.2 Băm dữ liệu với OpenSSL • OpenSSL cung cấp hai loại giao diện với các hàm băm – Giao diện riêng rẽ với mỗi giải thuật băm cụ thể • Mỗi giải thuật băm có tệp tiêu đề riêng • Tên gọi các hàm là khác nhau cho các giải thuật băm – Giao diện chung EVP cho mọi loại hàm băm • Tệp tiêu đề chung: • Trình tự sử dụng như nhau: – Khởi tạo ngữ cảnh: EVP_DigestInit – Cập nhật dữ liệu băm: EVP_DigestUpdate – Lấy kết quả: EVP_DigestFinal 87 5.2 Băm dữ liệu với OpenSSL • VD: Băm với SHA1 #include int i; SHA_CTX ctx; unsigned char result[SHA_DIGEST_LENGTH]; /* SHA1 has a 20-‐byte digest */ unsigned char *s1 = (unsigned char*)"Testing"; unsigned char *s2 = (unsigned char*)" "; SHA1_Init(&ctx); SHA1_Update(&ctx, s1, strlen((char*)s1)); SHA1_Update(&ctx, s2, strlen((char*)s2)); /* Yes, the context object is last */ SHA1_Final(result, &ctx); printf("SHA1(\"%s%s\") = ", s1, s2); for (i = 0; i < SHA_DIGEST_LENGTH; i++) printf("%02x", result[i]); printf("\n"); 88 5.2 Băm dữ liệu với OpenSSL • VD: Băm với giao diện EVP #include #include #include int i , ol; EVP_MD_CTX ctx; unsigned char *result; unsigned char *s1 = (unsigned char*)"Testing"; unsigned char *s2 = (unsigned char*)" "; EVP_DigestInit(&ctx, EVP_sha1()); EVP_DigestUpdate(&ctx, s1, strlen((char*)s1)); EVP_DigestUpdate(&ctx, s2, strlen((char*)s2)); if (!(result = (unsigned char *)malloc(EVP_MD_CTX_block_size(&ctx))))abort(); EVP_DigestFinal(&ctx, result, &ol); printf("SHA1(\"%s%s\") = ", s1, s2); for (i = 0; i < ol; i++) printf("%02x", result[i]); printf("\n"); free(result); 89 5.3 Băm dữ liệu với CryptoAPI • Trình tự băm với CryptoAPI – – – – – – Tệp tiêu đề: Wincrypt.h Khởi tạo ngữ cảnh Provider: CryptAcquireContext Tạo đối tượng hash: CryptCreateHash Băm liên tiếp với: CryptHashData Lấy kết quả: CryptGetHashParam Giải phóng đói tượng hash: CryptDestroyHash 90 5.3 Băm dữ liệu với CryptoAPI • Ví dụ: Băm dữ liệu với thuật toán SHA-‐256 BYTE *pbData; DWORD cbData = sizeof(DWORD), cbHashSize, i; HCRYPTHASH hSHA256; HCRYPTPROV hProvider; unsigned char *s1 = (unsigned char*)"Testing"; unsigned char *s2 = (unsigned char*)" "; // Khởi tạo ngữ cảnh Provider CryptAcquireContext(&hProvider, 0, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0); // Tạo đối tượng hàm băm CryptCreateHash(hProvider, CALG_SHA_256, 0, 0, &hSHA256); // Thực hiện băm CryptHashData(hSHA256, s1, strlen((char*)s1), 0); CryptHashData(hSHA256, s2, strlen((char*)s2), 0); // Thực hiện băm… 91 5.3 Băm dữ liệu với CryptoAPI • Ví dụ: Băm dữ liệu với thuật toán SHA-‐256 (tiếp) // Lấy kích thước dữ liệu băm được CryptGetHashParam(hSHA256, HP_HASHSIZE, (BYTE *)&cbHashSize, &cbData, 0); pbData = (BYTE *)LocalAlloc(LMEM_FIXED, cbHashSize); // Lấy dữ liệu băm được CryptGetHashParam(hSHA256, HP_HASHVAL, pbData, &cbHashSize, 0); // Giải phóng đối tượng băm và ngữ cảnh Provider CryptDestroyHash(hSHA256); CryptReleaseContext(hProvider, 0); printf("SHA256(\"%s%s\") = ", s1, s2); for (i = 0; i < cbHashSize; i++) printf("%02x", pbData[i]); printf("\n"); LocalFree(pbData); 92 5.4 Xác thực thơng điệp với HMAC • Với OpenSSL – – – – – – – Tệp tiêu đều Gọi hàm HMAC_Init để khởi tạo ngữ cảnh và key sẽ sử dụng Liên tục gọi hàm HMAC_Update để cập nhật dữ liệu Gọi hàm HMAC_Final để kết thúc quá trình băm Gọi hàm HMAC_cleanup để xóa key khỏi bộ nhớ Có thể gọi hàm All-‐in-‐one HMAC Bên nhận kiểm tra lại bằng cách thực hiện băm với với cùng một key và giải thuật và so sánh kết quả 93 5.4 Xác thực thông điệp với HMAC • Với OpenSSL int i; HMAC_CTX ctx; unsigned int len; unsigned char out[20]; unsigned char * key = (unsigned char*)"secret"; int keylen = strlen((char*)key); // Khởi tạo HMAC với key là secret HMAC_Init(&ctx, key, keylen, EVP_sha1( )); // Thực hiện băm xâu "fr HMAC_Update(&ctx, (unsigned char*)"hash me pls", 11); // Lấy kết quả HMAC_Final(&ctx, out, &len); for (i = 0; i < len; i++) printf("%02x", out[i]); printf("\n"); 94 5.4 Xác thực thông điệp với HMAC • Với CryptAPI – Tạo đối tượng Hash với hàm CryptCreateHash, trong đó tham số hKey là một key đã được tạo trước – Thiết lập thông tin về giải thuật băm với hàm CryptSetHashParam – Thực hiện băm với hàm CryptHashData – Lấy kích thước, nội của dữ liệu băm được với hàm CryptGetHashParam – Giải phóng đói tượng Hash và Key 95 5.4 Xác thực thơng điệp với HMAC • Với CryptAPI BYTE out[20]; DWORD cbData = sizeof(out), i; HCRYPTKEY hKey; HMAC_INFO HMACInfo; HCRYPTHASH hHash; HCRYPTPROV hProvider; // Lấy ngữ cảnh provider CryptAcquireContext(&hProvider, 0,MS_ENH_RSA_AES_PROV,PROV_RSA_AES,CRYPT_VERIFYCONTEXT); // Sinh key từ mật khẩu hKey = CreateKeyFromPassword(hProvider,"secret"); // Tạo đối tượng băm CryptCreateHash(hProvider, CALG_HMAC, hKey, 0, &hHash); 96 5.4 Xác thực thơng điệp với HMAC • Với CryptAPI // Thiết lập giải thuật băm HMACInfo.HashAlgid = CALG_SHA1; HMACInfo.pbInnerString = HMACInfo.pbOuterString = 0; HMACInfo.cbInnerString = HMACInfo.cbOuterString = 0; CryptSetHashParam(hHash, HP_HMAC_INFO, (BYTE *)&HMACInfo, 0); // Thực hiện băm CryptHashData(hHash, (BYTE *)"Hash me plz", 11, 0); // Lấy kết quả CryptGetHashParam(hHash, HP_HASHVAL, out, &cbData, 0); for (i = 0; i < cbData; i++) printf("%02x", out[i]); printf("\n"); CryptDestroyHash(hHash); CryptDestroyKey(hKey); CryptReleaseContext(hProvider, 0); 97 5.5 Sử dụng Salt • Salt – Chuỗi dữ liệu thêm vào để tăng khơng gian khóa và chống lại hình thức replay-‐attack – Hai bên có thể thỏa thuận chung một salt nào đó thay đổi theo thời gian – Salt thường được thêm vào đầu thơng điệp gốc, sau đó thực hiện băm cả salt cả thông điệp 98 Bài tập Viết chương trình mã hóa và giải mã tệp tin bằng giải thuật AES-‐256 bit Mật khẩu nhập từ bàn phím Kiểm tra tính đúng đắn của kết quả bằng giải thuật SHA-‐256 Sử dụng thư viện OpenSSL Khuôn dạng dữ liệu của tệp tin sau khi mã hóa có thể như sau: Viết chương trình chat client-‐server đơn giản trong đó kênh truyền mã hóa theo giải thuật AES-‐256 Key được sinh ra từ mật khẩu thỏa thuận trước và không truyền qua mạng, Vector khởi tạo là mã BCD được thiết lập từ ngày và giờ hiện tại của hệ thống (Hàm API GetSystemTime) Ví dụ: Nếu hiện tại là 07h ngày 10/10/2011 thì giá trị dưới dạng hexa của vector khởi tạo là 2011101007000….00 99 Bài tập Viết chương trình băm nội dung một }ile bằng giải thuật HMAC-‐AES256, sử dụng thư viện OpenSSL Mật khẩu để băm nhập từ bàn phím.Kết quả băm được lưu vào cuối }ile Viết chương trình kiểm tra tính tồn vẹn của một }ile bằng giải thuật HMAC-‐AES256 Mật khẩu để kiểm tra nhập từ bàn phím 100 ... cpb 5. 8 cpb No MD5 128 bits Very low, may be insecure 40.9 cpb 7.7 cpb No MDC-‐ 2-? ?‐AES-‐128 256 bits Very high 93 cpb 116 cpb Yes MDC-‐ 2-? ?‐DES ...Nội dung 5. 1 Các loại hàm băm và MAC thông dụng 5. 2 Băm với OpenSSL 5. 3 Băm dữ liệu với CryptoAPI 5. 4 Xác thực thông điệp với HMAC 5. 5 Salt 82 5. 1 Các... RIPEMD-‐160 160 bits High 62.2 cpb 20.6 cpb No SHA1 160 bits High 53 cpb 15. 9 cpb No SHA-‐ 256 256 bits Very high 119 cpb 116 cpb No SHA-‐384