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  toà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ột  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 Security  conqidence Uses  block  cipher Small  message   speed  (64  bytes),  in   cycles  per  byte[2] Large  message   speed  (8K),  in   cycles  per  byte

46.7  cpb 57.8  cpb Good Yes Davies-­‐Meyer-­‐ AES-­‐128 128  bits  (same  length   as  cipher  block  size)

MD2 128  bits Good  to  low 392  cpb No 184  cpb

MD4 128  bits Insecure 32  cpb No 5.8  cpb

MD5 128  bits 40.9  cpb No 7.7  cpb Very  low,  may  be   insecure

MDC-­‐2-­‐AES-­‐128 256  bits Very  high 93  cpb Yes 116  cpb

MDC-­‐2-­‐DES 128  bits Good 444  cpb Yes 444  cpb

RIPEMD-­‐160 160  bits High 62.2  cpb No 20.6  cpb

SHA1 160  bits High 53  cpb No 15.9  cpb

SHA-­‐256 256  bits Very  high 119  cpb No 116  cpb

SHA-­‐384 384  bits Very  high 171  cpb No 166  cpb

84

SHA-­‐512 512  bits Very  high 171  cpb No 166  cpb

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  toà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

Parallel-­‐izable

Large  message   speed  (8K)

Appropriate   for  hardware

Patent  restric-­‐ tions

Small  message   speed  (64   bytes)[4]

CMAC

~18  cpb

~18  cpb

Yes

Yes

No

A  universal  hash   and  AES

HMAC-­‐SHA1

90  cpb

20  cpb

Yes

No

No

Message  digest   function

MAC127

hash127  +  AES   ~6  cpb

~6  cpb

Yes

Yes

No

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

Yes

No

XMACC-­‐SHA1

162  cpb

29  cpb

Yes

Yes

Yes

Any  cipher  or   MD  function

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*)"...1...2...3...";              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*)"...1...2...3...";      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*)"...1...2...3...";      //  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

keylen  =  strlen((char*)key);

•  Với  OpenSSL      int                      i;      HMAC_CTX            ctx;      unsigned  int    len;      unsigned  char  out[20];      unsigned  char  *  key  =  (unsigned  char*)"secret";      int    //  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

1.  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:

2.  Viết  chương  trình  chat  client-­‐server  đơn  giản  trong  đó  kênh  truyền   được  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

3.  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.   4.  Viết  chương  trình  kiểm  tra  tính  toà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