SlideShare a Scribd company logo
1 of 131
Download to read offline
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
LẬP	
  TRÌNH	
  AN	
  TOÀN	
  
Secure	
  Programming	
  
•  Cung	
  cấp	
  các	
  kiến	
  thức,	
  kỹ	
  thuật	
  cơ	
  bản	
  để	
  xây	
  dựng	
  các	
  ứng	
  dụng	
  an	
  
toàn.	
  
Mục	
  đích	
  
2	
  
•  Yêu	
  cầu	
  về	
  kiến	
  thức:	
  
–  An	
  ninh	
  mạng	
  
–  Ngôn	
  ngữ	
  lập	
  trình	
  C/C++.	
  
•  Lên	
  lớp	
  đầy	
  đủ	
  
Yêu	
  cầu	
  
3	
  
•  Thời	
  lượng:	
  45	
  tiết	
  
–  Lý	
  thuyết:	
  30	
  tiết	
  
–  Bài	
  tập:15	
  tiết	
  
Thời	
  lượng	
  môn	
  học	
  
4	
  
•  Secure	
  Program	
  Cookbook	
  for	
  C	
  and	
  C++,	
  Matt	
  Messier,	
  
John	
  Viega,	
  O'Reilly	
  2003.	
  
Tài	
  liệu	
  
5	
  
•  Chương	
  1.	
  Kiểm	
  tra	
  đầu	
  vào	
  
•  Chương	
  2.	
  Kiểm	
  soát	
  truy	
  nhập	
  
•  Chương	
  3.	
  Kiểm	
  soát	
  xung	
  đột	
  
•  Chương	
  4.	
  Mã	
  hóa	
  đối	
  xứng	
  
•  Chương	
  5.	
  Hàm	
  băm	
  và	
  xác	
  thực	
  thông	
  điệp	
  
•  Chương	
  6.	
  Mã	
  hóa	
  công	
  khai	
  
•  Chương	
  7.	
  Anti-­‐Tampering	
  
•  Chương	
  8.	
  Các	
  vấn	
  đề	
  khác	
  
Nội	
  dung	
  
6	
  
7	
  
•  Bài	
  tập	
  lớn:	
  70%	
  
•  Quá	
  trình:	
  30%	
  
Đánh	
  giá	
  
8	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  1.	
  Kiểm	
  tra	
  đầu	
  vào	
  
Input	
  Validation	
  
1.1	
  Nguyên	
  tắc	
  kiểm	
  tra.	
  
1.2	
  Các	
  hàm	
  định	
  dạng	
  xâu	
  (string	
  formatting)	
  .	
  
1.3	
  Tràn	
  bộ	
  đệm.	
  
1.4	
  Tràn	
  số	
  học.	
  
1.5	
  Kiểm	
  tra	
  tên	
  }ile	
  và	
  đường	
  dẫn.	
  
1.6	
  Giải	
  mã	
  URL	
  
1.7	
  Cross-­‐Site	
  Scripting	
  
1.8	
  SQL	
  Injection	
  
Nội	
  dung	
  
10	
  
•  Luôn	
  luôn	
  giả	
  định	
  dữ	
  liệu	
  đầu	
  vào	
  là	
  không	
  đáng	
  tin	
  cậy	
  
–  Dữ	
  liệu	
  từ	
  mạng	
  trong	
  mô	
  hình	
  client-­‐server	
  
–  Dữ	
  liệu	
  từ	
  người	
  dùng	
  
–  Dữ	
  liệu	
  từ	
  tệp	
  tin	
  
–  …	
  
•  Ưu	
  tiên	
  loại	
  bỏ	
  dữ	
  liệu	
  hơn	
  là	
  cố	
  gắng	
  sửa	
  chữa	
  dữ	
  liệu.	
  
•  Thực	
  hiện	
  kiểm	
  tra	
  đầu	
  vào	
  tại	
  nhiều	
  cấp,	
  nhiều	
  điểm	
  
–  Kiểm	
  tra	
  đầu	
  vào	
  ở	
  các	
  hàm	
  
–  Kiểm	
  tra	
  đầu	
  vào	
  giữa	
  các	
  module.	
  
–  …	
  
•  Không	
  tiếp	
  nhận	
  lệnh	
  trực	
  tiếp	
  từ	
  người	
  dùng	
  nếu	
  chưa	
  qua	
  kiểm	
  tra.	
  
•  Kiểm	
  tra	
  các	
  ký	
  tự	
  đặc	
  biệt,	
  dấu	
  nháy.	
  
•  Tìm	
  hiểu	
  và	
  sử	
  dụng	
  cơ	
  chế	
  trích	
  dẫn	
  (quoting	
  mechanism)	
  nếu	
  cần.	
  
•  Càng	
  hiểu	
  về	
  dữ	
  liệu	
  bao	
  nhiêu	
  càng	
  lọc	
  được	
  tốt	
  bấy	
  nhiêu.	
  
1.1	
  Các	
  nguyên	
  tắc	
  kiểm	
  tra	
  
11	
  
•  Họ	
  các	
  hàm	
  printf()	
  ,	
  syslog()	
  	
  cho	
  phép	
  định	
  dạng	
  dữ	
  liệu	
  rất	
  mềm	
  dẻo	
  và	
  
mạnh	
  mẽ	
  tuy	
  nhiên	
  cũng	
  cực	
  kỳ	
  nguy	
  hiểm.	
  
•  Thận	
  trọng	
  khi	
  sử	
  dụng	
  “%n”	
  
–  Tham	
  số	
  %n	
  cho	
  phép	
  ghi	
  ra	
  số	
  lượng	
  ký	
  tự	
  đã	
  kết	
  xuất	
  được	
  ra	
  một	
  địa	
  chỉ	
  bất	
  kỳ	
  chỉ	
  ra	
  
trong	
  tham	
  số	
  tương	
  ứng.	
  Nếu	
  không	
  tồn	
  tại	
  tham	
  số	
  nào	
  thì	
  printf	
  sẽ	
  ghi	
  đè	
  lên	
  một	
  vùng	
  
nào	
  đó	
  thuộc	
  stack	
  của	
  luồng	
  đang	
  thực	
  thi.	
  
–  VD.	
  
int 	
  counter	
  =	
  0;	
  
printf(“Hello%n”,&counter);	
  //	
  OK,	
  counter	
  =	
  5	
  
printf(“Hello%n”);	
  //	
  Nguy	
  hiểm	
  !!!	
  	
  
•  Không	
  sử	
  dụng	
  trực	
  tiếp	
  xâu	
  định	
  dạng	
  từ	
  nguồn	
  bên	
  ngoài	
  
–  Xâu	
  định	
  dạng	
  có	
  nguồn	
  gốc	
  từ	
  ngoài	
  chương	
  trình	
  có	
  thể	
  có	
  một	
  vài	
  ký	
  tự	
  đặc	
  biệt	
  mà	
  
chương	
  trình	
  chưa	
  lường	
  trước	
  được,	
  hoặc	
  không	
  có	
  tham	
  số	
  thay	
  thế	
  tương	
  ứng.	
  	
  
–  VD.	
  
	
  char 	
  str[1024];	
  
	
  gets(str);	
  
	
  printf(“Xin	
  chao:”);	
  
	
  printf(str);	
  //	
  Nguy	
  hiểm	
  !!!	
  
	
  printf(“%s”,str);	
  //	
  OK	
  	
  
1.2	
  Các	
  hàm	
  định	
  dạng	
  xâu	
  
12	
  
•  Thận	
  trọng	
  khi	
  sử	
  dụng	
  sprintf,	
  vsprintf	
  với	
  “%s”	
  
–  Các	
  hàm	
  trên	
  đều	
  giả	
  định	
  kích	
  thước	
  bộ	
  đệm	
  cho	
  xâu	
  đích	
  là	
  vô	
  hạn.	
  
–  Nên	
  chỉ	
  rõ	
  số	
  lượng	
  ký	
  tự	
  tối	
  đa	
  sẽ	
  sử	
  dụng	
  khi	
  dùng	
  với	
  %s.	
  
–  Nên	
  sử	
  dụng	
  snprintf,	
  vsnprintf	
  nếu	
  có	
  thể.	
  
–  VD	
  
char	
  str[1024];	
  
char	
  dst[32];	
  
gets(str);	
  
sprintf(dst,”Xau	
  vua	
  nhap	
  vao	
  la	
  %s”,str);	
  //	
  Nguy	
  hiểm	
  
sprintf(dst,”Xau	
  vua	
  nhap	
  vao	
  la	
  %.16s”,str);	
  //	
  OK	
  
snprintf(dst,32,”Xau	
  vua	
  nhap	
  vao	
  la	
  %s”,str);//	
  OK	
  
	
  
	
  
1.2	
  Các	
  hàm	
  định	
  dạng	
  xâu	
  
13	
  
•  Tràn	
  bộ	
  đệm	
  (Buffer	
  Over}low):	
  copy	
  dữ	
  liệu	
  vượt	
  quá	
  biên	
  của	
  một	
  bộ	
  
đệm	
  nào	
  đó	
  =>	
  đè	
  lên	
  vùng	
  nhớ	
  của	
  biến	
  (cấu	
  trúc)	
  khác.	
  
•  Phần	
  lớn	
  các	
  hàm	
  xử	
  lý	
  xâu	
  trong	
  C	
  đều	
  không	
  thực	
  hiện	
  kiểm	
  tra	
  biên	
  
của	
  bộ	
  đệm:	
  gets,	
  strcpy,	
  …	
  
•  VD1:	
  Dữ	
  liệu	
  bị	
  hỏng	
  
	
  int	
   	
  x	
  =	
  0;	
  
	
  char 	
  buff[8];	
  
	
  strcpy(buff,”Hello	
  	
  	
  AAAAAAAAAAAAAAAAAAAAAAAAAAAAA”);	
  
	
  printf(“%d”,x);	
  
•  VD2:	
  Stack	
  bị	
  hỏng	
  
	
  char 	
  name[8];	
  
	
  gets(name);	
  
	
  printf(name);	
  
	
  
1.3	
  Tràn	
  bộ	
  đệm	
  
14	
  
•  VD3:	
  Không	
  trở	
  về	
  được	
  từ	
  chương	
  trình	
  con	
  
	
  void	
  Hello()	
  
	
  {	
  
	
   	
  char	
  name[8];	
  
	
   	
  printf(“What	
  is	
  your	
  name	
  ?”);	
  
	
   	
  gets(name);	
  
	
   	
  printf(“Hello	
  %s	
  !”,	
  name); 	
  	
  
	
  } 	
  	
  
	
  void	
  main()	
  
	
  {	
  
	
   	
  Hello();	
  
	
   	
  printf(“Bye”);	
  
	
  }	
  
1.3	
  Tràn	
  bộ	
  đệm	
  
15	
  
•  VD4:	
  Tấn	
  công	
  có	
  chủ	
  ý	
  trên	
  bộ	
  đệm	
  
	
  void	
  Bye()	
  
	
  {	
  
	
   	
  printf(“Bye”);	
  
	
  }	
  
	
  void	
  Hello()	
  
	
  {	
  
	
   	
  void	
  (*p)()	
  =	
  Bye;	
  
	
   	
  char	
  name[8];	
  
	
   	
  printf(“What	
  is	
  your	
  name	
  ?”);	
  
	
   	
  gets(name);	
  
	
   	
  printf(“Hello	
  %s	
  !”,	
  name);	
  
	
   	
  p(); 	
  	
  
	
  } 	
  	
  
	
  void	
  main()	
  
	
  {	
  
	
   	
  Hello();	
  
	
  }	
  
1.3	
  Tràn	
  bộ	
  đệm	
  
16	
  
•  Giải	
  pháp:	
  	
  
–  Sử	
  dụng	
  các	
  hàm	
  strncpy,	
  memcpy…và	
  những	
  hàm	
  có	
  kiểm	
  soát	
  kích	
  thước	
  
bộ	
  đệm	
  một	
  cách	
  tường	
  minh.	
  
–  Sử	
  dụng	
  Stack	
  Guard	
  trong	
  các	
  trình	
  biên	
  dịch	
  hỗ	
  trợ.	
  	
  
–  Sử	
  dụng	
  DEP	
  (Data	
  Execution	
  Preventation)	
  trên	
  hệ	
  điều	
  hành	
  hỗ	
  trợ.	
  
–  Sử	
  dụng	
  ASLR	
  (Address	
  Space	
  Layout	
  Randomization)	
  trên	
  trình	
  biên	
  
dịch	
  và	
  hệ	
  điều	
  hành	
  hỗ	
  trợ.	
  
1.3	
  Tràn	
  bộ	
  đệm	
  
17	
  
•  Dữ	
  liệu	
  nhận	
  về	
  có	
  thể	
  có	
  sai	
  sót	
  trong	
  trường	
  liên	
  quan	
  đến	
  kích	
  
thước.	
  
•  Các	
  thao	
  tác	
  liên	
  quan	
  đến	
  số	
  nguyên	
  lớn	
  có	
  thể	
  bị	
  tràn,	
  lẫn	
  lộn	
  giữa	
  số	
  
nguyên	
  không	
  dấu	
  và	
  có	
  dấu	
  
•  VD1:	
  Tràn	
  số	
  
unsigned	
  	
  int	
  x	
  =	
  0xFFFFFFFF;	
  //	
  MAX_INT	
  
if 	
  (	
  x+5	
  >	
  5	
  )	
  printf	
  (“X	
  >	
  0”	
  )	
  
	
  else 	
  printf(“X	
  <	
  0”);	
  
•  VD2:	
  Dùng	
  sai	
  kiểu	
  có/không	
  dấu	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (x	
  <	
  MAX_SIZE)	
  {	
  	
  //	
  x,	
  số	
  byte	
  cần	
  cấp	
  phát	
  tùy	
  theo	
  giải	
  thuật	
  tính	
  được	
  
	
  	
  	
  if	
  (!(ptr	
  =	
  (unsigned	
  char	
  *)malloc(x)))	
  abort(	
  	
  );	
  
	
  }	
  	
  
	
  else	
  	
  
	
  {	
  
	
   	
   	
  	
  /*	
  Handle	
  the	
  error	
  condition	
  ...	
  */	
  
	
  }	
  
	
  	
  
	
  	
  	
  
1.4	
  Tràn	
  số	
  học	
  
18	
  
•  Dữ	
  liệu	
  nhận	
  về	
  có	
  thể	
  là	
  tên	
  }ile,	
  ứng	
  dụng	
  cần	
  xác	
  định	
  đường	
  dẫn	
  
tuyệt	
  đối	
  nếu	
  cần	
  thiết.	
  
•  Dùng	
  hàm	
  realpath()	
  trên	
  Unix/Linux	
  và	
  GetFullPathName	
  trên	
  
Windows.	
  
•  Sử	
  dụng	
  realpath()	
  
§  Nguyên	
  mẫu:	
  	
  
	
  char	
  *realpath(const	
  char	
  *pathname,	
  char	
  resolved_path[MAXPATHLEN]);	
  
§  Thận	
  trọng:	
  Có	
  thể	
  tràn	
  resolved_path	
  và	
  không	
  thread-­‐safe.	
  
§  Thư	
  viện:	
  stdlih.h	
  
§  VD	
  
	
  char	
  resolved[1024];	
  
	
  char	
  *	
  result	
  =	
  realpath("printf.c",resolved);	
  
	
  printf("%s",result);	
  
	
  	
  	
  
1.5	
  Kiểm	
  tra	
  tên	
  qile	
  và	
  đường	
  dẫn	
  
19	
  
•  Sử	
  dụng	
  GetFullPathName()	
  
§  Thư	
  viện:	
  windows.h	
  
§  Nguyên	
  mẫu:	
  	
  
	
  DWORD	
  GetFullPathName(LPCTSTR	
  lpFileName,	
  DWORD	
  nBufferLength,	
  LPTSTR	
  
	
   	
   	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  lpBuffer,	
  LPTSTR	
  *lpFilePath);	
  
§  VD:	
  
	
  int 	
  nBufferLen	
  =	
  0;	
  
	
  LPTSTR 	
  lpBuffer;	
  
	
  
	
  nBufferLen	
  =	
  GetFullPathName(L"test.c",0,0,0);	
  
	
  if	
  (nBufferLen>0)	
  
	
  {	
  
	
   	
  lpBuffer	
  =	
  new	
  TCHAR[nBufferLen+1];	
  
	
   	
  GetFullPathName(L"test.c",nBufferLen,lpBuffer,0);	
  
	
   	
  wprintf(L"%s",lpBuffer);	
  
	
  }	
  
	
  	
  
	
  	
  	
  
1.5	
  Kiểm	
  tra	
  tên	
  qile	
  và	
  đường	
  dẫn	
  
20	
  
•  RFC	
  1738	
  quy	
  định	
  cách	
  mã	
  hóa	
  các	
  ký	
  tự	
  không	
  nhìn	
  thấy	
  được	
  trong	
  
URL	
  dưới	
  dạng	
  “%<Mã	
  hexa>”.	
  
•  VD:	
   	
  http://m%61il.google.com	
  
	
  http://m%25%36%31il.google.com	
  
•  Cách	
  giải	
  mã:	
  duyệt	
  từ	
  đầu	
  đến	
  cuối	
  ,	
  tìm	
  các	
  ký	
  tự	
  %	
  và	
  thay	
  thế	
  bằng	
  
mã	
  ASCII	
  tương	
  ứng.	
  
•  Không	
  sử	
  dụng	
  các	
  hàm	
  xử	
  lý	
  xâu	
  chuẩn	
  vì	
  có	
  thể	
  có	
  ký	
  tự	
  NULL	
  trong	
  
URL.	
  
	
  	
  
	
  	
  	
  
1.6	
  Giải	
  mã	
  URL	
  
21	
  
•  Cross-­‐Site	
  Scripting	
  (XSS)	
  là	
  hình	
  thức	
  tấn	
  công	
  vào	
  trình	
  duyệt	
  người	
  
dùng	
  bắt	
  nguồn	
  từ	
  việc	
  kiểm	
  tra	
  lỏng	
  lẻo	
  từ	
  server.	
  
•  Có	
  thể	
  dẫn	
  đến	
  thất	
  thoát	
  thông	
  tin	
  nhạy	
  cảm:	
  mật	
  khẩu,	
  session,	
  
cookie…	
  
•  Thực	
  hiện	
  bằng	
  cách	
  chèn	
  mã	
  HTML/JAVASCRIPT	
  vào	
  dữ	
  liệu	
  sẽ	
  hiển	
  
thị	
  ra	
  trình	
  duyệt	
  =>	
  đoạn	
  mã	
  sẽ	
  chạy	
  trên	
  trình	
  duyệt	
  của	
  nạn	
  nhân.	
  
•  VD.	
  Một	
  ứng	
  dụng	
  web	
  có	
  hai	
  trang	
  
–  Hello.php:	
  Hiển	
  thị	
  form	
  và	
  nhận	
  tên	
  của	
  người	
  dùng.	
  
–  Chao.php:	
  hiển	
  thị	
  tên	
  nhận	
  được	
  lại	
  cho	
  người	
  dùng.	
  
	
  	
  
	
  	
  	
  
1.7	
  Cross-­‐Site	
  Scripting	
  
22	
  
•  File	
  Hello.php	
  
<HTML>	
  
Xin	
  chào,	
  vui	
  lòng	
  nhập	
  tên	
  bạn	
  
<FORM	
  action="chao.php"	
  method=“POST">	
  
<input	
  type="text"	
  name="name"/><br/>	
  
<input	
  type="submit"	
  value="Submit">	
  
</FORM>	
  
</HTML>	
  
•  File	
  Chao.php	
  
<?PHP	
  
echo	
  "Xin	
  chao	
  ".$_POST['name'];	
  
?>	
  
•  Demo	
  
•  Với	
  tên	
  là	
  :	
  Secure	
  
•  Với	
  tên	
  là:	
  Secure	
  <script>alert('XSS	
  was	
  found	
  !');</script> 	
  	
  
•  Với	
  tên	
  là:	
  Secure	
  <s%63ript>alert(‘Hacked’);</s%63ript>	
  
•  Giải	
  pháp:	
  Lọc	
  bỏ	
  các	
  thẻ	
  HTML	
  khỏi	
  dữ	
  liệu	
  từ	
  người	
  dùng.	
  Mỗi	
  ngôn	
  
ngữ	
  lập	
  trình	
  có	
  một	
  cách	
  riêng.	
  
1.7	
  Cross-­‐Site	
  Scripting	
  
23	
  
•  SQL	
  Injection:	
  Tấn	
  công	
  vào	
  CSDL	
  thông	
  qua	
  dữ	
  liệu	
  nhập	
  từ	
  trình	
  
duyệt.	
  
•  Lợi	
  dụng	
  việc	
  kiểm	
  tra	
  lỏng	
  lẻo	
  từ	
  đầu	
  vào,	
  chèn	
  mã	
  lệnh	
  SQL	
  vào	
  các	
  
truy	
  vấn	
  đến	
  CSDL	
  của	
  ứng	
  dụng	
  web.	
  	
  
•  Thường	
  lợi	
  dụng	
  	
  dấu	
  nháy	
  “	
  ‘	
  “	
  để	
  kết	
  thúc	
  câu	
  truy	
  vấn	
  SQL	
  hoặc	
  thêm	
  
các	
  câu	
  truy	
  vấn	
  khác.	
  
•  VD:	
  Lệnh	
  so	
  sánh	
  tên	
  và	
  mật	
  khẩu	
  trong	
  SQL	
  
–  select	
  *	
  from	
  users	
  where	
  username	
  =	
  ‘$user’	
  and	
  password	
  =	
  ‘$pass’	
  	
  
–  Nếu	
  $user	
  hoặc	
  $pass	
  chứa	
  dấu	
  “’”	
  thì	
  SQL	
  sẽ	
  hiểu	
  nhầm	
  nội	
  dung	
  truy	
  
vấn…	
  
•  Các	
  kỹ	
  thuật	
  khai	
  thác:	
  An	
  ninh	
  mạng	
  
•  VD:	
  Một	
  ứng	
  dụng	
  web	
  muốn	
  kiểm	
  tra	
  tên	
  và	
  mật	
  khẩu	
  gồm	
  hai	
  trang	
  
–  ask.php:	
  Hiện	
  form	
  đăng	
  nhập	
  và	
  thu	
  nhận	
  tên,	
  mật	
  khẩu	
  
–  login.php:	
  Kết	
  nối	
  đến	
  CSDL	
  và	
  kiểm	
  tra	
  
1.8	
  SQL	
  Injection	
  
24	
  
•  VD	
  (tiếp	
  
–  File	
  ask.php	
  
	
  <HTML>	
  
Vui	
  long	
  nhap	
  ten	
  va	
  mat	
  khau	
  
<FORM	
  action="login.php"	
  method="GET">	
  
Ten:	
  <INPUT	
  type="text"	
  name="user"/><BR/>	
  
Mat	
  khau:<INPUT	
  type="text"	
  name="pass"/><BR/>	
  
<INPUT	
  type="submit"	
  name="Submit">	
  	
  
</FORM>	
  
	
  	
  
1.8	
  SQL	
  Injection	
  
25	
  
•  VD	
  (tiếp)	
  
–  File	
  login.php	
  
	
  <?PHP	
  
$db_server	
  =	
  "localhost";	
  
$db_username=	
  "root";	
  
$db_password=	
  "123456";	
  
$db	
  =	
  "test";	
  
$table	
  =	
  "users";	
  
$conn	
  =	
  mysql_connect($server,$db_username,$db_password);	
  
if	
  (!$conn)	
  
	
  {	
  
	
   	
  echo	
  "Khong	
  ket	
  noi	
  dc	
  den	
  CSDL";	
  
	
   	
  return;	
  
	
  }	
  
$ret	
  	
  =	
  mysql_select_db($db,$conn);	
  
1.8	
  SQL	
  Injection	
  
26	
  
 if	
  (!$ret) 	
  {	
  
	
   	
  echo	
  "Khong	
  ton	
  tai	
  CSLD	
  tuong	
  ung";	
  
	
   	
  return;	
  
	
   	
  }	
  
$user	
  =	
  $_GET['name'];	
  
$pass	
  =	
  $_GET['pass'];	
  
	
  
$sql	
  =	
  "select	
  *	
  from	
  $table	
  where	
  username='$user'	
  and	
  password='$pass'";	
  
echo	
  $sql;	
  
$ret	
  =mysql_query($sql,$conn);	
  
if	
  (mysql_num_rows($ret)>0)	
  
	
   	
  echo	
  "Dang	
  nhap	
  thanh	
  cong";	
  
else	
  
	
   	
  echo	
  "Sai	
  ten	
  hoac	
  mat	
  khau";	
  
	
  	
  
?>	
  
1.8	
  SQL	
  Injection	
  
27	
  
•  Tấn	
  công	
  
–  username	
  =	
  a’	
  or	
  ‘1’=‘1	
  
–  password	
  =	
  b’	
  or	
  ‘1’=‘1	
  
–  …	
  
•  Phòng	
  chống	
  
–  Loại	
  bỏ	
  tất	
  cả	
  các	
  dấu	
  ‘	
  và	
  các	
  ký	
  tự	
  đặc	
  biệt	
  nếu	
  cần.	
  
–  Sử	
  dụng	
  escaped	
  string	
  	
  
•  Với	
  php/mysql:	
  mysql_real_escape_string,	
  hoặc	
  thêm	
  ‘’.	
  
•  Với	
  SQL	
  server:	
  thêm	
  ký	
  tự	
  	
  ‘	
  trước	
  ký	
  tự	
  đặc	
  biệt.	
  
•  Với	
  Oracle	
  DB:	
  thêm	
  ký	
  tự	
  ‘’	
  trước	
  ký	
  tự	
  đặc	
  biệt.	
  
	
  	
  
1.8	
  SQL	
  Injection	
  
28	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  2.	
  Kiểm	
  soát	
  truy	
  nhập	
  
Access	
  Control	
  
2.1	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  Unix/Linux	
  
2.2	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  Windows	
  
2.3	
  Hạ	
  thấp	
  quyền	
  truy	
  nhập	
  của	
  tiến	
  trình	
  
2.4	
  Xóa	
  }ile	
  an	
  toàn	
  
2.5	
  Hạn	
  chế	
  quyền	
  truy	
  nhập	
  trên	
  }ile	
  
2.6	
  Khóa	
  }ile	
  
2.7	
  Tạo	
  }ile	
  tạm	
  
2.8	
  Hạn	
  chế	
  truy	
  nhập	
  đến	
  hệ	
  thống	
  }ile	
  
	
  
Nội	
  dung	
  
30	
  
•  Trên	
  Unix/Linux	
  tất	
  cả	
  các	
  tài	
  nguyên	
  đều	
  được	
  coi	
  là	
  }ile:	
  tệp	
  tin,	
  ổ	
  đĩa,	
  
bộ	
  nhớ,	
  thiết	
  bị….	
  
•  Mỗi	
  }ile	
  kiểm	
  soát	
  bởi	
  user	
  id	
  và	
  group	
  id.	
  
•  Mỗi	
  tiến	
  trình	
  có	
  ba	
  quyền:	
  effective	
  user	
  id,	
  real	
  user	
  id,	
  saved	
  user	
  id.	
  
Effective	
  user	
  id	
  được	
  sử	
  dụng	
  trong	
  phần	
  lớn	
  các	
  kiểm	
  tra.	
  	
  
•  Mỗi	
  tiến	
  trình	
  cũng	
  thuộc	
  về	
  ba	
  nhóm:	
  effective	
  group	
  id,	
  real	
  group	
  id,	
  
saved	
  group	
  id.	
  
•  Có	
  ba	
  loại	
  quyền	
  
•  Đọc	
  (read)	
  
•  Ghi	
  (write)	
  
•  Thực	
  thi	
  (execute)	
  
2.1	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  Unix/
Linux	
  
31	
  
•  Mỗi	
  }ile	
  sẽ	
  có	
  ba	
  nhóm	
  quyền	
  tương	
  ứng	
  với:	
  user	
  id,	
  group	
  id,	
  và	
  
other.	
  
-­‐rwxr-­‐xr-­‐x	
  1	
   	
  Luong	
  Anh	
  Hoang	
   	
  None	
   	
  17964	
   	
  Aug	
  28	
  23:45	
  test.exe	
  
•  Khi	
  tiến	
  trình	
  tạo	
  một	
  }ile	
  hoặc	
  tài	
  nguyên,	
  hệ	
  thống	
  sẽ	
  gán	
  user	
  id	
  và	
  
group	
  id	
  cho	
  }ile	
  mới	
  đó	
  bằng	
  effective	
  user	
  id	
  và	
  effective	
  group	
  id	
  của	
  
tiến	
  trình.	
  
•  Khi	
  tiến	
  trình	
  truy	
  nhập	
  một	
  }ile	
  hoặc	
  tài	
  nguyên,	
  hệ	
  thống	
  sẽ	
  lần	
  lượt	
  
so	
  sánh	
  user	
  id,	
  group	
  id	
  của	
  tiến	
  trình	
  và	
  }ile	
  và	
  chọn	
  ra	
  tập	
  quyền	
  
tương	
  ứng.	
  Nếu	
  không	
  khớp	
  thì	
  lớp	
  quyền	
  thứ	
  3	
  sẽ	
  được	
  sử	
  dụng.	
  
2.1	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  Unix/
Linux	
  
32	
  
•  Mỗi	
  }ile	
  cũng	
  có	
  thể	
  có	
  3	
  bit	
  đặc	
  biệt	
  
•  Sticky.	
  Nếu	
  bit	
  này	
  được	
  thiết	
  lập,	
  người	
  dùng	
  sẽ	
  không	
  thể	
  xóa	
  hay	
  đổi	
  tên	
  
}ile	
  của	
  người	
  khác	
  nằm	
  trong	
  thưc	
  mục	
  mà	
  người	
  dùng	
  quản	
  lý.	
  Mặc	
  định	
  
là	
  không	
  được	
  thiết	
  lập.	
  
•  Setuid:	
  Bit	
  này	
  liên	
  quan	
  đến	
  quá	
  trình	
  tạo	
  một	
  tiến	
  trình	
  mới.	
  Nếu	
  bit	
  này	
  
được	
  thiết	
  lập,	
  tiến	
  trình	
  được	
  tạo	
  từ	
  }ile	
  này	
  sẽ	
  không	
  kế	
  thừa	
  quyền	
  từ	
  
tiến	
  trình	
  cha,	
  mà	
  sẽ	
  có	
  quyền	
  từ	
  user	
  id	
  của	
  chính	
  }ile	
  đó.	
  
•  Setgid:	
  	
  
•  Đối	
  với	
  }ile	
  thực	
  thi,	
  nếu	
  bit	
  này	
  được	
  thiết	
  lập	
  thì	
  một	
  tiến	
  trình	
  mới	
  
được	
  tạo	
  sẽ	
  có	
  quyền	
  từ	
  groupd	
  id	
  của	
  }ile	
  đó	
  chứ	
  không	
  kế	
  thừa	
  từ	
  
tiến	
  trình	
  cha	
  (tương	
  tự	
  Setuid).	
  
•  Đối	
  với	
  thưc	
  mục,	
  nếu	
  bit	
  này	
  được	
  thiết	
  lập	
  thì	
  các	
  }ile	
  tạo	
  trong	
  thư	
  
mục	
  này	
  sẽ	
  có	
  groupd	
  id	
  của	
  thư	
  mục	
  cha,	
  chứ	
  không	
  kế	
  thừa	
  từ	
  tiến	
  
trình	
  tạo	
  ra	
  }ile	
  đó.	
  
2.1	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  Unix/
Linux	
  
33	
  
•  Windows	
  sử	
  dụng	
  ACL:	
  Access	
  Control	
  List	
  để	
  phân	
  quyền	
  tài	
  
nguyên.	
  
•  Các	
  tài	
  nguyên	
  của	
  Windows:	
  }ile,	
  registry,	
  mutex,	
  event,	
  IPC…	
  
được	
  kiểm	
  soát	
  thông	
  qua	
  DACL	
  và	
  SACL.	
  
•  DACL	
  là	
  danh	
  sách	
  các	
  ACE,	
  mỗi	
  ACE	
  là	
  một	
  luật	
  quy	
  định	
  một	
  
quyền	
  hạn	
  cụ	
  thể.	
  
•  DACL	
  rỗng	
  tương	
  đương	
  với	
  việc	
  tất	
  cả	
  mọi	
  người	
  có	
  toàn	
  quyền	
  
truy	
  nhập	
  tới	
  đối	
  tượng.	
  
•  Mỗi	
  ACE	
  bao	
  gồm	
  3	
  thông	
  tin:	
  	
  
•  SID:	
  Đại	
  diện	
  cho	
  một	
  user	
  hay	
  một	
  group	
  trong	
  hệ	
  thống	
  
•  Quyền	
  truy	
  nhập	
  
•  Giá	
  trị	
  boolean	
  tương	
  ứng	
  với	
  cho	
  phép	
  hay	
  không	
  cho	
  phép.	
  
2.2	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  
Windows	
  
34	
  
•  Các	
  quyền	
  truy	
  nhập	
  
	
  
2.2	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  
Windows	
  
35	
  
TÊN	
   Diễn	
  giải	
  
DELETE	
   The	
  ability	
  to	
  delete	
  the	
  object	
  
READ_CONTROL	
  
The	
  ability	
  to	
  read	
  the	
  object's	
  security	
  
descriptor,	
  not	
  including	
  its	
  SACL	
  
SYNCHRONIZE	
  
The	
  ability	
  for	
  a	
  thread	
  to	
  wait	
  for	
  the	
  object	
  
to	
  be	
  put	
  into	
  the	
  signaled	
  state;	
  not	
  all	
  
objects	
  support	
  this	
  functionality	
  
WRITE_DAC	
   The	
  ability	
  to	
  modify	
  the	
  object's	
  DACL	
  
WRITE_OWNER	
   The	
  ability	
  to	
  set	
  the	
  object's	
  owner	
  
GENERIC_READ	
   The	
  ability	
  to	
  read	
  from	
  or	
  query	
  the	
  object	
  
GENERIC_WRITE	
   The	
  ability	
  to	
  write	
  to	
  or	
  modify	
  the	
  object	
  
GENERIC_EXECUTE	
  
The	
  ability	
  to	
  execute	
  the	
  object	
  (applies	
  
primarily	
  to	
  }iles)	
  
GENERIC_ALL	
   Full	
  control	
  
•  Ví	
  dụ	
  ACE	
  
•  DENY	
  	
  	
  	
  	
  	
  GENERIC_ALL	
  	
  	
  	
  	
  	
  	
  	
  	
  Everyone:	
  Cấm	
  mọi	
  quyền	
  với	
  group	
  Everyone	
  
•  ALLOW	
  	
  GENERIC_WRITE	
  	
  	
  Marketing:	
  Cho	
  phép	
  nhóm	
  group	
  Marketing	
  
được	
  quyền	
  ghi	
  
•  Mỗi	
  đối	
  tượng	
  đều	
  có	
  một	
  Owner,	
  chính	
  là	
  người	
  tạo	
  ra	
  đối	
  
tượng.	
  
•  Owner	
  có	
  toàn	
  quyền	
  với	
  đối	
  tượng	
  bất	
  kể	
  trong	
  DACL	
  có	
  cấm	
  
hay	
  không.	
  
•  Owner	
  có	
  thể	
  bị	
  chiếm	
  bởi	
  user	
  khác.	
  
	
  
2.2	
  Cơ	
  chế	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  
Windows	
  
36	
  
•  Nếu	
  một	
  tiến	
  trình	
  có	
  đặc	
  quyền	
  cao,	
  thực	
  hiện	
  các	
  thao	
  tác	
  nguy	
  hiểm	
  
=>	
  cần	
  hạ	
  thấp	
  quyền	
  trước	
  khi	
  thực	
  hiện.	
  
•  Tiến	
  trình	
  có	
  thể	
  kiểm	
  tra	
  real	
  user	
  id,	
  real	
  group	
  id	
  bằng	
  lệnh	
  getuid	
  (),	
  
getgid().	
  Đây	
  là	
  các	
  đặc	
  quyền	
  kế	
  thừa	
  từ	
  tiến	
  trình	
  cha.	
  
•  Tiến	
  trình	
  có	
  thể	
  kiểm	
  tra	
  effective	
  user	
  id	
  và	
  effective	
  group	
  id	
  bằng	
  
lệnh	
  geteuid()	
  và	
  getegid().	
  Đây	
  thường	
  là	
  user	
  id	
  có	
  đặc	
  quyền	
  cao	
  
hơn	
  (do	
  được	
  khởi	
  chạy	
  từ	
  super	
  user,	
  hoặc	
  các	
  bit	
  setuid	
  được	
  bật).	
  
•  Tiến	
  trình	
  từ	
  bỏ	
  đặc	
  quyền	
  bằng	
  việc	
  thiết	
  lập	
  group	
  mới	
  chính	
  là	
  real	
  
user	
  id	
  qua	
  lệnh	
  	
  
•  setgroups():	
  Thiết	
  lập	
  lại	
  nhóm	
  của	
  tiến	
  trình.	
  	
  
•  setegid():	
  Thiết	
  lập	
  lại	
  effective	
  group	
  id	
  của	
  tiến	
  trình.	
  
•  seteuid():	
  Thiết	
  lập	
  lại	
  effective	
  user	
  id	
  của	
  tiến	
  trình.	
  
	
  
2.3	
  Hạ	
  thấp	
  quyền	
  truy	
  nhập	
  của	
  tiến	
  trình	
  
37	
  
•  Thông	
  thường,	
  một	
  }ile	
  sau	
  khi	
  xóa	
  sẽ	
  được	
  hệ	
  điều	
  hành	
  đánh	
  dấu	
  là	
  
xóa,	
  nội	
  dung	
  chưa	
  hoàn	
  toàn	
  bị	
  loại	
  bỏ	
  trên	
  đĩa.	
  
•  Giải	
  pháp	
  
•  Ghi	
  đè	
  thông	
  tin	
  khác	
  nhiều	
  lần	
  lên	
  đĩa.	
  
•  Ghi	
  đè	
  dữ	
  liệu	
  ngâu	
  nhiên	
  nhiều	
  lần	
  lên	
  đĩa.	
  
•  Ghi	
  đè	
  sử	
  dụng	
  mẫu	
  định	
  sẵn	
  lên	
  đĩa.	
  
•  Sau	
  mỗi	
  chu	
  kỳ	
  ghi,	
  sử	
  dụng	
  fsync	
  để	
  đồng	
  bộ	
  với	
  đĩa,	
  vô	
  hiệu	
  hóa	
  cơ	
  chế	
  
cache.	
  Hoặc	
  lệnh	
  f}lush()	
  nếu	
  sử	
  dụng	
  thư	
  viện	
  C.	
  
•  Một	
  vài	
  mẫu	
  được	
  sử	
  dụng	
  
•  static	
  unsigned	
  char	
  single_pats[16]	
  =	
  {	
  0x00,	
  0x11,	
  0x22,	
  0x33,	
  0x44,	
  
0x55,	
  0x66,	
  0x77,	
  0x88,	
  0x99,	
  0xaa,	
  0xbb,	
  0xcc,	
  0xdd,	
  0xee,	
  0xff	
  };	
  	
  
•  static	
  unsigned	
  char	
  triple_pats[6][3]	
  =	
  {	
  {	
  0x92,	
  0x49,	
  0x24	
  },	
  {	
  0x49,	
  0x24,	
  
0x92	
  },	
  {	
  0x24,	
  0x92,	
  0x49	
  },	
  {	
  0x6d,	
  0xb6,	
  0xdb	
  },	
  {	
  0xb6,	
  0xdb,	
  0x6d	
  },	
  
{	
  0xdb,	
  0x6d,	
  0xb6	
  }	
  };	
  	
  
	
  
2.4	
  Xóa	
  qile	
  an	
  toàn	
  
38	
  
•  Unix/Linux	
  sử	
  dụng	
  umask	
  cho	
  mỗi	
  tiến	
  trình	
  để	
  vô	
  hiệu	
  hóa	
  một	
  vài	
  
bit	
  khi	
  tiến	
  trình	
  tạo	
  }ile.	
  
•  Hàm	
  fopen,	
  open	
  luôn	
  luôn	
  tạo	
  }ile	
  với	
  quyền	
  666.	
  
•  Giả	
  sử	
  tiến	
  trình	
  muốn	
  tạo	
  }ile	
  với	
  quyền	
  666:	
  
requested_permissions	
  =	
  0666;	
  	
  
actual_permissions	
  =	
  requested_permissions	
  &	
  ~umask(	
  );	
  
•  Ứng	
  dụng	
  thay	
  đổi	
  umask	
  bằng	
  hàm	
  umask()	
  trước	
  khi	
  thực	
  hiện	
  lời	
  
gọi	
  tạo	
  }ile.	
  
#include	
  <sys/types.h>	
  
#include	
  <sys/stat.h>	
  	
  
mode_t	
   	
  umask(mode_t	
   	
  mask);	
  	
  
	
  
	
  
	
  
2.5	
  Hạn	
  chế	
  quyền	
  truy	
  nhập	
  trên	
  qile	
  
39	
  
•  Tiến	
  trình	
  muốn	
  kiểm	
  soát	
  truy	
  nhập	
  trên	
  một	
  phần	
  của	
  }ile	
  hay	
  toàn	
  
bộ	
  }ile	
  để	
  tránh	
  xung	
  đột	
  khi	
  có	
  nhiều	
  tiến	
  trình	
  cùng	
  truy	
  	
  nhập	
  trên	
  
}ile.	
  
•  Unix/Linux	
  cung	
  cấp	
  cơ	
  chế	
  khóa	
  mềm:	
  Mọi	
  tiến	
  trình	
  đều	
  có	
  quyền	
  
giành	
  được	
  khóa	
  và	
  thao	
  tác	
  trên	
  }ile,	
  tuy	
  nhiên	
  không	
  phải	
  tiến	
  trình	
  
nào	
  cũng	
  tuân	
  thủ	
  theo	
  khóa	
  và	
  có	
  thể	
  phá	
  hỏng	
  dữ	
  liệu	
  của	
  tiến	
  trình	
  
khác.	
  
•  Windows	
  thực	
  hiện	
  vấn	
  đề	
  này	
  tốt	
  hơn	
  bằng	
  khóa	
  cứng.	
  Có	
  hai	
  loại	
  
khóa:	
  
•  Shared	
  Lock:	
  Cho	
  phép	
  các	
  tiến	
  trình	
  khác	
  (kể	
  cả	
  tiến	
  trình	
  giành	
  được	
  
khóa)	
  đọc	
  nhưng	
  không	
  được	
  ghi	
  vào	
  một	
  phần	
  đã	
  khóa	
  của	
  }ile.	
  	
  
•  Exclusive	
  Lock	
  :	
  Cấm	
  tất	
  cả	
  các	
  tiến	
  trình	
  khác	
  không	
  được	
  đọc	
  hay	
  ghi	
  vào	
  
phần	
  đã	
  khóa	
  của	
  }ile.	
  Tiến	
  trình	
  giành	
  được	
  khóa	
  có	
  quyền	
  đọc	
  hoặc	
  ghi	
  
vào	
  }ile.	
  
	
  
	
  
	
  
2.6	
  Khóa	
  qile	
  
40	
  
•  Các	
  hàm	
  khóa	
  }ile	
  trên	
  Windows	
  
•  LockFile,	
  UnlockFile:	
  Khóa	
  và	
  mở	
  khóa	
  đồng	
  bộ,	
  sẽ	
  không	
  trở	
  về	
  đến	
  khi	
  
giành	
  được	
  khóa	
  hoặc	
  mở	
  được	
  khóa.	
  
•  LockFileEx,	
  UnlockFileEx:	
  Khóa	
  và	
  mở	
  khóa	
  đồng	
  bộ	
  hoặc	
  bất	
  đồng	
  bộ.	
  
•  Khóa	
  }ile	
  cũng	
  có	
  thể	
  xác	
  định	
  lúc	
  tạo	
  lập/truy	
  nhập	
  }ile	
  thông	
  qua	
  hàm	
  
CreateFile.	
  
•  Đoạn	
  chương	
  trình	
  sau	
  sẽ	
  mở	
  một	
  }ile	
  để	
  đọc	
  với	
  chế	
  độ	
  Shared	
  Lock.	
  
	
  char 	
  buff[1024];	
  
	
  DWORD 	
  bytesRead	
  =	
  0;	
  
	
  HANDLE 	
  fileHandle	
  =	
  NULL;	
  
	
  fileHandle	
  =	
  CreateFile(L"C:SecureProgrammingTest.txt",	
  
	
   	
   	
   	
  GENERIC_READ|GENERIC_WRITE,	
  
	
   	
   	
   	
  FILE_SHARE_READ|FILE_SHARE_WRITE,	
  
	
   	
   	
   	
  0,	
  
	
   	
   	
   	
  OPEN_ALWAYS,	
  
	
   	
   	
   	
  FILE_ATTRIBUTE_NORMAL,	
  
	
   	
   	
   	
  0);	
  
	
  	
  
2.6	
  Khóa	
  qile	
  
41	
  
•  VD	
  (tiếp)	
  
	
  ReadFile(fileHandle,buff,128,&bytesRead,0);	
  
	
  buff[bytesRead]	
  =	
  0;	
  
	
  printf("File	
  content:%sn",buff);	
  
	
  LockFile(fileHandle,0,0,100,0); 	
  //	
  Exclusive	
  Lock	
  
	
  printf("File	
  is	
  locked,	
  press	
  any	
  key	
  to	
  unlock...n"); 	
  	
  
	
  getch();	
  
	
  UnlockFile(fileHandle,0,0,100,0);	
  
	
  printf("File	
  is	
  unlockedn");	
  
	
  getch();	
  
	
  CloseHandle(fileHandle);	
  
	
  	
  
2.6	
  Khóa	
  qile	
  
42	
  
•  Ứng	
  dụng	
  tạo	
  }ile	
  tạm	
  để	
  lưu	
  trữ	
  thông	
  tin	
  tạm	
  thời	
  của	
  chương	
  trình.	
  
•  File	
  tạm	
  nên	
  được	
  tạo	
  lập	
  một	
  cách	
  an	
  toàn,	
  và	
  xóa	
  khi	
  kết	
  thúc	
  chương	
  
trình.	
  
•  Trên	
  unix/linux:	
  
•  Hàm	
  mkstemp()	
  có	
  thể	
  sử	
  dụng	
  để	
  tạo	
  }ile	
  tạm	
  với	
  tên	
  ngẫu	
  nhiên.	
  
•  Ứng	
  dụng	
  cần	
  xóa	
  }ile	
  theo	
  tên,	
  ngay	
  sau	
  lời	
  gọi	
  mkstemp	
  để	
  đảm	
  bảo	
  không	
  tiến	
  
trình	
  nào	
  truy	
  nhập	
  được.	
  
•  Sau	
  khi	
  tiến	
  trình	
  kết	
  thúc	
  một	
  cách	
  bình	
  thường/không	
  bình	
  thường,	
  }ile	
  tạm	
  sẽ	
  
không	
  thể	
  truy	
  nhập	
  được	
  nữa.	
  
•  VD	
  
	
  char	
  	
  szPath[]	
  =	
  “fileXXXXXX";	
  
	
  int	
  fd; 	
  	
  
	
  fd	
  =	
  mkstemp(szPath);	
  
	
  unlink(szPath);	
  
	
  printf("Temperary	
  file	
  created,	
  press	
  any	
  key	
  to	
  continue...");	
  
	
  write(fd,"Hello",5);	
  
	
  close(fd);	
  
2.7	
  Tạo	
  qile	
  tạm	
  
43	
  
•  Trên	
  Windows:	
  
•  Không	
  có	
  hàm	
  tương	
  đương	
  mkstemp()	
  
•  GetTempFileName()	
  sinh	
  tên	
  }ile	
  ngẫu	
  nhiên	
  nhưng	
  dễ	
  đoán.	
  
•  GetTempPath()	
  lấy	
  đường	
  dẫn	
  đến	
  thư	
  mục	
  tạm	
  của	
  người	
  dùng	
  hiện	
  tại.	
  
•  Tạo	
  }ile	
  bằng	
  hàm	
  CreateFile	
  với	
  hai	
  thuộc	
  tính	
  FILE_ATTRIBUTE_TEMPORARY	
  và	
  
FILE_FLAG_DELETE_ON_CLOSE	
  
•  VD	
  
HANDLE 	
  }ileHandle	
  =	
  NULL;	
  
}ileHandle	
  =	
  CreateFile(L"C:SecureProgrammingTmp.txt",	
  
	
   	
  GENERIC_READ|GENERIC_WRITE,	
  
	
   	
  FILE_SHARE_READ|FILE_SHARE_WRITE,	
  
	
   	
  0,	
  
	
   	
  OPEN_ALWAYS, 	
   	
  	
  
	
  FILE_ATTRIBUTE_TEMPORARY|	
  
	
  FILE_FLAG_DELETE_ON_CLOSE,	
  
	
   	
   	
   	
  0);	
  
	
  	
  
	
  
	
  
	
  
	
  
2.7	
  Tạo	
  qile	
  tạm	
  
44	
  
•  Trên	
  Unix/Linux,	
  ứng	
  dụng	
  có	
  thể	
  tự	
  giới	
  hạn	
  phạm	
  vi	
  truy	
  nhập	
  hệ	
  
thống	
  tệp	
  tin	
  của	
  mình	
  bằng	
  lệnh	
  chroot()	
  
•  Sau	
  khi	
  gọi	
  chroot():	
  
•  Tiến	
  trình	
  không	
  thể	
  mở	
  rộng	
  phạm	
  vi	
  truy	
  nhập	
  bằng	
  lệnh	
  chroot	
  lần	
  nữa..	
  
•  Tiến	
  trình	
  chỉ	
  có	
  thể	
  thu	
  hẹp	
  hơn	
  nữa	
  phạm	
  vi	
  truy	
  nhập	
  của	
  mình.	
  
•  Tiến	
  trình	
  phải	
  chủ	
  động	
  gọi	
  thêm	
  chdir()	
  để	
  lệnh	
  chroot	
  có	
  hiệu	
  lực.	
  
•  VD:	
  
	
  #include	
  <unistd.h>	
  
	
  chroot("/new/root/directory");	
  
	
  chdir("/");	
  
	
  	
  
	
  
	
  
	
  
	
  
	
  
2.8	
  Hạn	
  chế	
  truy	
  nhập	
  đến	
  hệ	
  thống	
  qile	
  
45	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  3.	
  Kiểm	
  soát	
  xung	
  đột	
  
Synchronization	
  Technique	
  
3.1	
  Khái	
  niệm	
  
3.2	
  Đoạn	
  găng	
  (Critical	
  Section).	
  
3.3	
  Đèn	
  hiệu	
  (Semaphore)	
  	
  
3.4	
  Mutex	
  
3.5	
  Event	
  
3.6	
  SRW	
  Lock	
  
Nội	
  dung	
  
47	
  
§  Xung	
  đột	
  là	
  vấn	
  đề	
  phát	
  sinh	
  khi	
  nhiều	
  luồng	
  của	
  chương	
  trình	
  chạy	
  
trên	
  bộ	
  vi	
  xử	
  lý	
  đa	
  nhân	
  cùng	
  truy	
  nhập	
  một	
  tài	
  nguyên	
  hệ	
  thống.	
  
§  Ví	
  dụ	
  
3.1	
  Khái	
  niệm	
  
48	
  
int	
  x	
  =	
  0;	
  
DWORD 	
  WINAPI	
  Thread(LPVOID	
  	
  lpParam)	
  
{	
  
	
  for	
  (int	
  i=0;i<2000000;i++)	
  x++;	
  
	
  return	
  0;	
  
}	
  
int	
  _tmain(int	
  argc,	
  _TCHAR*	
  argv[])	
  
{	
  
	
  
	
  HANDLE	
  hThread1	
  =	
  CreateThread(NULL,NULL,Thread,NULL,NULL,NULL);	
  
	
  HANDLE	
  hThread2	
  =	
  CreateThread(NULL,NULL,Thread,NULL,NULL,NULL);	
  
	
  WaitForSingleObject(hThread1,INFINITE);	
  
	
  WaitForSingleObject(hThread2,INFINITE);	
  
	
  printf("X=%d",x);	
  
	
  getch();	
  
	
  return	
  0;	
  
}	
  
§  Đoạn	
  găng	
  (Critical	
  Section)	
  là	
  đoạn	
  chương	
  trình	
  được	
  bảo	
  vệ	
  bởi	
  hệ	
  
điều	
  hành	
  sao	
  cho	
  tại	
  mọi	
  thời	
  điểm	
  chỉ	
  có	
  một	
  luồng	
  được	
  phép	
  thực	
  
thi.	
  
§  Sử	
  dụng	
  
§  Khai	
  báo:	
   	
  CRITICAL_SECTION 	
  cs	
  
§  Khởi	
  tạo:	
   	
  InitializeCriticalSection(&cs)	
  
§  Sử	
  dụng	
  
	
  EnterCriticalSection(&cs)	
  
	
  //	
  Bắt	
  đầu	
  đoạn	
  găng	
  
	
  …	
  
	
  //	
  Kết	
  thúc	
  đoạn	
  găng	
  
	
  LeaveCriticalSection(&cs)	
  
	
  //	
  	
  
	
  DeleteCriticalSection(&cs)	
  
§  Ví	
  dụ	
  
§  Đặc	
  điểm:	
  chỉ	
  có	
  tác	
  dụng	
  trong	
  cùng	
  một	
  tiến	
  trình	
  
3.2	
  Đoạn	
  găng	
  
49	
  
§  Đèn	
  hiệu	
  (Semaphore)	
  dùng	
  để	
  giới	
  hạn	
  số	
  lượng	
  luồng	
  tối	
  đa	
  được	
  
phép	
  thực	
  thi	
  cùng	
  một	
  đoạn	
  chương	
  trình.	
  
§  Sử	
  dụng	
  
§  Khai	
  báo:	
   	
  HANDLE 	
  hSemaphore	
  
§  Khởi	
  tạo:	
   	
  hSemaphore	
  =	
  CreateSemaphore(NULL,5,5,NULL)	
  
§  Sử	
  dụng	
  
	
  WaitForSingleObject(hSemaphore,	
  0L)	
  
	
  //	
  
	
  …	
  
	
  //	
  
	
  ReleaseSemaphore(hSemaphore,1,NULL)	
  
	
  //	
  
	
  CloseHandle(hSemaphore)	
  
§  Ví	
  dụ	
  
§  Đặc	
  điểm	
  
§  Dùng	
  chung	
  được	
  giữa	
  các	
  tiến	
  trình	
  
§  Tốc	
  độ	
  chậm	
  hơn	
  CRITICAL_SECTION	
  
3.3	
  Đèn	
  hiệu	
  
50	
  
§  Mutex	
  dùng	
  để	
  bảo	
  vệ	
  tài	
  nguyên	
  của	
  chương	
  trình,	
  tại	
  một	
  thời	
  điểm	
  
chỉ	
  cho	
  phép	
  một	
  luồng	
  của	
  một	
  tiến	
  trình	
  truy	
  nhập.	
  
§  Sử	
  dụng	
  
§  Khai	
  báo:	
   	
  HANDLE 	
  hMutex;	
  
§  Khởi	
  tạo:	
   	
  hMutex	
  =	
  CreateMutex(NULL,	
  FALSE,	
  NULL)	
  
§  Sử	
  dụng	
  
	
  WaitForSingleObject(hMutex,	
  INFINITE)	
  
	
  //	
  
	
  …	
  
	
  //	
  
	
  ReleaseMutex(hMutex)	
  
§  Ví	
  dụ	
  
§  Đặc	
  điểm	
  
§  Chậm	
  hơn	
  CRITICAL_SECTION	
  
§  Có	
  thể	
  đồng	
  bộ	
  giữa	
  các	
  tiến	
  trình	
  
3.4	
  Mutex	
  
51	
  
§  Event	
  dùng	
  đồng	
  bộ	
  hoạt	
  động	
  của	
  các	
  luồng	
  thông	
  qua	
  cơ	
  chế	
  báo	
  
hiệu.	
  
§  Sử	
  dụng	
  
§  Khai	
  báo:	
   	
  HANDLE 	
  hEvent;	
  
§  Khởi	
  tạo:	
   	
  hMutex	
  =	
  CreateEvent(NULL,	
  TRUE,	
  FALSE,	
  “MyEvent”)	
  
§  Sử	
  dụng	
  
	
  WaitForSingleObject(hEvent,	
  INFINITE)	
  
	
  //	
  
	
  …	
  
	
  SetEvent(hEvent) 	
   	
  //	
  Báo	
  hiệu	
  các	
  luồng	
  khác	
  
	
  ResetEvent(hEvent) 	
  //	
  Chặn	
  các	
  luồng	
  khác	
  
	
  …	
  
	
  //	
  
	
  CloseHandle(hEvent)	
  
§  Ví	
  dụ	
  
3.5	
  Event	
  
52	
  
§  SRW	
  Lock	
  (Slim	
  Reader	
  Writer	
  Lock	
  )dùng	
  đồng	
  bộ	
  hoạt	
  động	
  của	
  các	
  
luồng	
  thông	
  tương	
  tự	
  như	
  đoạn	
  găng	
  
§  Sử	
  dụng	
  
§  Khai	
  báo:	
   	
  SRWLOCK	
   	
  lock;	
  
§  Khởi	
  tạo:	
   	
  InitializeSRWLock(&lock);	
  
§  Sử	
  dụng	
  
	
  AcquireSRWLockShared(&lock)	
  
	
  AcquireSRWLockExclusive(&lock)	
  
	
  //	
  
	
  …	
  
	
  //	
  
	
  ReleaseSRWLockShared(&lock)	
  
	
  ReleaseSRWLockExclusive(&lock)	
  
§  Ví	
  dụ	
  
3.5	
  SRW	
  Lock	
  
53	
  
1.  Viết	
  chương	
  trình	
  chat	
  Client	
  và	
  Server	
  với	
  kênh	
  truyền	
  đã	
  mã	
  
hóa	
  	
  bằng	
  thuật	
  toán	
  AES-­‐256,	
  sử	
  dụng	
  thư	
  viện	
  OpenSSL	
  và	
  
CryptoAPI.	
  Mật	
  khẩu	
  mã	
  hóa	
  là	
  :	
  123456.	
  Việc	
  mã	
  hóa	
  và	
  việc	
  
nhận	
  dữ	
  liệu	
  được	
  thực	
  hiện	
  đồng	
  thời	
  trên	
  2	
  luồng	
  riêng	
  biệt,	
  sử	
  
dụng	
  cơ	
  chế	
  đồng	
  bộ	
  CRITICAL_SECTION	
  
2.  Viết	
  chương	
  trình	
  mã	
  hóa	
  và	
  giải	
  mã	
  tệp	
  tin	
  theo	
  thuật	
  toán	
  
AES-­‐256,	
  với	
  tên	
  nhập	
  từ	
  bàn	
  phím,	
  mật	
  khẩu	
  mã	
  hóa	
  là	
  :nopass.	
  
Sử	
  dụng	
  thư	
  viện	
  OpenSSL	
  và	
  CryptoAPI	
  
Bài	
  tập	
  
54	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  4.	
  Mã	
  hóa	
  đối	
  xứng	
  
Symmetric	
  Crytography	
  
4.1	
  Biểu	
  diễn	
  khóa	
  
4.2	
  Chuyển	
  đổi	
  chuỗi	
  hexa	
  và	
  khóa	
  nhị	
  phân.	
  
4.3	
  Mã	
  hóa	
  và	
  giải	
  mã	
  Base64	
  	
  
4.4	
  Các	
  phương	
  pháp	
  mã	
  hóa	
  đối	
  xứng	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
4.6	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  Microsoft	
  Crypto	
  API	
  
Nội	
  dung	
  
56	
  
•  Khóa	
  đối	
  xứng:	
  	
  Một	
  số	
  rất	
  lớn	
  sử	
  dụng	
  để	
  mã	
  hóa	
  và	
  giải	
  mã	
  thông	
  
điệp.	
  
•  Biểu	
  diễn	
  khóa:	
  
•  Phân	
  tách	
  thành	
  các	
  byte	
  và	
  lưu	
  dưới	
  dạng	
  một	
  mảng.	
  
unsigned	
  char	
  	
  key[KEYLEN_BYTES]	
  
•  Biểu	
  diễn	
  dưới	
  dạng	
  số	
  nguyên	
  lớn	
  nếu	
  khóa	
  có	
  chiều	
  dài	
  64-­‐bit	
  
long	
  	
  	
  	
  	
  	
  long	
  	
  	
  	
  	
  	
  	
  key	
  
•  Biểu	
  diễn	
  dưới	
  dạng	
  chuỗi	
  chữ	
  số	
  hexa	
  
	
  char 	
  key[]=“AF12B5C7E0…”	
  
•  Biểu	
  diễn	
  dưới	
  dạng	
  xâu	
  ASCII	
  (mật	
  khẩu).	
  
	
  char 	
  key[]=“secret!!!”	
  
•  Lưu	
  ý	
  về	
  tính	
  “endian”	
  của	
  máy	
  thực	
  hiện	
  mã	
  hóa.	
  
4.1	
  Biểu	
  diễn	
  khóa	
  
57	
  
•  Chuyển	
  đổi	
  khóa	
  nhị	
  phân	
  sang	
  dạng	
  chuỗi	
  chữ	
  số	
  hexa	
  
	
  #define 	
  MAX_KEY_LEN 	
  32	
  
	
  unsigned	
  char	
  key[MAX_KEY_LEN];	
  
	
  char 	
  	
  result[MAX_KEY_LEN*2+1];	
  
	
  for	
  (int	
  i=0;i<MAX_KEY_LEN;i++)	
  
	
   	
  sprintf(result+i*2,"%2X",key[i]);	
  
	
  printf("Key:%s",result);	
  
	
  
4.2	
  Chuyển	
  đổi	
  chuỗi	
  hexa	
  và	
  khóa	
  nhị	
  
phân	
  	
  
58	
  
•  Chuyển	
  đổi	
  chuỗi	
  hexa	
  sang	
  khóa	
  
nhị	
  phân	
  
	
  
char	
  Hex2Dec(char	
  c)	
  
{	
  
	
  	
  	
  	
  	
  if	
  (('a'<=c)&&(c<='z'))	
  return	
  c	
  -­‐	
  'a'+10;	
  
	
  	
  	
  	
  	
  if	
  (('A'<=c)&&(c<='Z'))	
  return	
  c	
  -­‐	
  'A'+10;	
  
	
  	
  	
  	
  	
  if	
  (('0'<=c)&&(c<='9'))	
  return	
  c	
  -­‐	
  '0';	
  
	
  	
  	
  	
  	
  return	
  -­‐1;	
  
}	
  
…	
  
#define 	
  MAX_KEY_LENGTH	
  32 	
  	
  
char	
  hexa[]="AF125C4D8E";	
  
unsigned	
  char	
  key[MAX_KEY_LENGTH];	
  
int	
  keylen	
  =	
  strlen(hexa);	
  
char	
  c1,c2;	
  
if	
  ((keylen%2!=0)||(keylen/2	
  >	
  	
  
	
  
	
  
MAX_KEY_LENGTH))	
  
printf("Invalid	
  key	
  length");	
  
keylen	
  =	
  keylen/2;	
  
for	
  (int	
  i=0;i<keylen;i++)	
  
{	
  
	
  c1	
  =	
  Hex2Dec(hexa[i*2]);	
  
	
  c2	
  =	
  Hex2Dec(hexa[i*2+1]);	
  
	
  if	
  ((c1==-­‐1)||(c2==-­‐1))	
  
	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  printf("Invalid	
  character	
  !!!");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  };	
  
	
  key[i]	
  =	
  (c1<<4)|c2;	
  
};	
  
	
  
4.2	
  Chuyển	
  đổi	
  chuỗi	
  hexa	
  và	
  khóa	
  nhị	
  
phân	
  	
  
59	
  
•  Mã	
  hóa	
  Base64	
  	
  	
  
•  Sử	
  dụng	
  6-­‐bit	
  để	
  mã	
  hóa	
  dữ	
  liệu	
  và	
  biểu	
  diễn	
  dưới	
  dạng	
  các	
  chữ	
  cái	
  ASCII.	
  
•  Cứ	
  3	
  byte	
  dữ	
  liệu	
  vào	
  sẽ	
  được	
  biểu	
  diễn	
  thành	
  4	
  byte	
  dữ	
  liệu	
  ra.	
  
•  Các	
  ký	
  tự	
  ra	
  nằm	
  trong	
  khoảng:	
  	
  
•  ‘A’	
  –	
  ‘Z’	
  tương	
  đương	
  các	
  giá	
  trị	
  của	
  từ	
  mã	
  từ	
  0-­‐25.	
  
•  ‘a’	
  –	
  ‘z’	
  tương	
  đương	
  các	
  giá	
  trị	
  của	
  từ	
  mã	
  từ	
  26-­‐51.	
  
•  ‘0’-­‐	
  ‘9’	
  tương	
  đương	
  các	
  giá	
  trị	
  từ	
  mã	
  từ	
  52-­‐61.	
  
•  ‘+’	
  ,	
  ‘-­‐’	
  tương	
  ứng	
  với	
  các	
  giá	
  trị	
  mã	
  62,63.	
  
•  Nếu	
  dữ	
  liệu	
  vào	
  có	
  kích	
  thước	
  không	
  chia	
  hết	
  cho	
  3	
  sẽ	
  thì	
  được	
  thêm	
  vào	
  bằng	
  ký	
  tự	
  
‘=‘.	
  
•  VD	
  
	
  Dữ	
  liệu	
  gốc:	
  ‘A’	
  –	
  0100.0001	
  
	
  Dữ	
  liệu	
  mã	
  hóa	
  dạng	
  Base64:	
  010000.010000.000000.000000	
  ~	
  QQ==	
  
	
  Dữ	
  liệu	
  gốc:	
  ‘AA’	
  –	
  0100.0001.0100.0001	
  
	
  Dữ	
  liệu	
  mã	
  hóa	
  dạng	
  Base64:	
  010000.010100.000100.000000	
  ~	
  QUE=	
  
	
  Dữ	
  liệu	
  gốc:	
  ‘AAA’	
  –	
  0100.0001.0100.0001.0100.0001	
  
	
  Dữ	
  liệu	
  dạng	
  mã	
  hóa	
  Base64:	
  010000.010100.000101.000001	
  ~	
  QUFB	
  
	
   	
   	
   	
  	
  
	
   	
   	
   	
   	
  	
  
4.3	
  Mã	
  hóa	
  và	
  giải	
  mã	
  Base64	
  
60	
  
•  Mã	
  hóa	
  Base64	
  	
  	
  
	
   	
   	
  	
  
	
   	
   	
   	
   	
  	
  
4.3	
  Mã	
  hóa	
  và	
  giải	
  mã	
  Base64	
  
61	
  
Value	
   Char	
  
	
  	
  
Value	
   Char	
  
	
  	
  
Value	
   Char	
  
	
  	
  
Value	
   Char	
  
0	
   A	
   16	
   Q	
   32	
   g	
   48	
   w	
  
1	
   B	
   17	
   R	
   33	
   h	
   49	
   x	
  
2	
   C	
   18	
   S	
   34	
   i	
   50	
   y	
  
3	
   D	
   19	
   T	
   35	
   j	
   51	
   z	
  
4	
   E	
   20	
   U	
   36	
   k	
   52	
   0	
  
5	
   F	
   21	
   V	
   37	
   l	
   53	
   1	
  
6	
   G	
   22	
   W	
   38	
   m	
   54	
   2	
  
7	
   H	
   23	
   X	
   39	
   n	
   55	
   3	
  
8	
   I	
   24	
   Y	
   40	
   o	
   56	
   4	
  
9	
   J	
   25	
   Z	
   41	
   p	
   57	
   5	
  
10	
   K	
   26	
   a	
   42	
   q	
   58	
   6	
  
11	
   L	
   27	
   b	
   43	
   r	
   59	
   7	
  
12	
   M	
   28	
   c	
   44	
   s	
   60	
   8	
  
13	
   N	
   29	
   d	
   45	
   t	
   61	
   9	
  
14	
   O	
   30	
   e	
   46	
   u	
   62	
   +	
  
15	
   P	
   31	
   f	
   47	
   v	
   63	
   /	
  
•  Đoạn	
  chương	
  trình	
  mã	
  hóa	
  Base64:	
  	
  P4.5	
  –	
  Secure	
  C	
  Programming	
  
Cookbook	
  
•  Đoạn	
  chương	
  trình	
  giải	
  mã	
  Base64:	
  P4.6	
  –	
  Secure	
  C	
  Programming	
  
Cookbook	
  
4.3	
  Mã	
  hóa	
  và	
  giải	
  mã	
  Base64	
  
62	
  
•  Mã	
  hóa	
  đối	
  xứng:	
  Sử	
  dụng	
  chung	
  một	
  khóa	
  cho	
  mã	
  hóa	
  và	
  giải	
  mã	
  
•  Có	
  hai	
  loại:	
  Mã	
  khối	
  và	
  mã	
  dòng	
  
•  Có	
  nhiều	
  chế	
  độ	
  mã	
  hóa:	
  ECB,	
  CBC,	
  CFB,	
  OFB,	
  CTR,	
  CWC…	
  	
  
•  Có	
  nhiều	
  giải	
  thuật:	
  
	
  
4.4	
  Các	
  phương	
  pháp	
  mã	
  hóa	
  đối	
  xứng	
  
63	
  
Cipher	
   Key	
  size	
   Speed[4]	
   Implementation	
   Notes	
  
AES	
   128	
  bits[5]	
  
14.1	
  cpb	
  in	
  asm,	
  22.6	
  cpb	
  in	
  
C	
  
Brian	
  Gladman's[6]	
  
The	
  assembly	
  version	
  currently	
  works	
  only	
  
on	
  Windows.	
  
AES	
   128	
  bits	
   41.3	
  cpb	
   OpenSSL	
  
Triple	
  DES	
   192	
  bits[7]	
   108.2	
  cpb	
   OpenSSL	
  
SNOW	
  2.0	
   128	
  or	
  256	
  bits	
   6.4	
  cpb	
  
Fast	
  reference	
  
implementation[8]	
  
This	
  implementation	
  is	
  written	
  in	
  C.	
  
RC4	
  
Up	
  to	
  256	
  bits	
  
(usually	
  128	
  bits)	
  
10.7	
  cpb	
   OpenSSL	
  
Serpent	
   128,	
  192,	
  or	
  256	
  bits	
   35.6	
  cpb	
  
Fast	
  reference	
  
implementation	
  
It	
  gets	
  a	
  lot	
  faster	
  on	
  64-­‐bit	
  platforms	
  and	
  
is	
  at	
  least	
  as	
  fast	
  as	
  AES	
  in	
  hardware.	
  
Blowfish	
  
Up	
  to	
  256	
  bits	
  
(usually	
  128	
  bits)	
  
23.2	
  cpb	
   OpenSSL	
  
•  Thư	
  viện	
  OpenSSL:	
  Thư	
  viện	
  mã	
  nguồn	
  mở,	
  mạnh	
  mẽ	
  và	
  dễ	
  sử	
  dụng.	
  
•  OpenSSL	
  hỗ	
  trợ:	
  
•  Nhiều	
  thuật	
  toán	
  mã	
  hóa:	
  AES,	
  DES	
  ,	
  3DES,	
  Blow}ish,	
  CAST,	
  Idea,	
  RC2,	
  RC5.	
  
•  Nhiều	
  chế	
  độ	
  mã	
  hóa:	
  ECB,	
  CBC,	
  CFB,	
  OFB,	
  CTR…	
  
•  Mã	
  hóa	
  dòng:	
  RC4.	
  
•  Các	
  giải	
  thuật	
  băm:	
  MD2,	
  MD4,	
  MD5,SHA-­‐1,SHA-­‐224,SHA-­‐256…	
  
•  MAC:	
  HMAC.	
  MDC2	
  
•  Các	
  giải	
  thuật	
  mã	
  hóa	
  công	
  khai:	
  DH,	
  DSA,	
  RSA,	
  ECC	
  
•  Sử	
  dụng	
  thư	
  viện:	
  
•  Trên	
  Unix/Linux:	
  Tải	
  source	
  về	
  và	
  biên	
  dịch.	
  Kết	
  quả	
  là	
  }ile	
  	
  libcrypto.[so/
a],	
  libssl.[so/a]	
  và	
  các	
  }ile	
  .h	
  để	
  include	
  vào	
  chương	
  trình.	
  
•  Trên	
  Windows:	
  Tải	
  bản	
  binary	
  đã	
  biên	
  dịch	
  sẵn:	
  libeay32.dll,	
  ssleay32.dll,	
  
tệp	
  tiêu	
  đề	
  (.h)	
  và	
  tệp	
  thư	
  viện	
  (.lib).	
  Link	
  http://www.ie7pro.com/
openssl.html	
  
	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
64	
  
•  Giao	
  diện	
  OpenSSL	
  EVP	
  
•  Là	
  API	
  mức	
  cao	
  của	
  OpenSSL,	
  cho	
  phép	
  truy	
  nhập	
  đến	
  các	
  thuật	
  toán	
  ở	
  mức	
  
thấp	
  một	
  cách	
  tập	
  trung,	
  dễ	
  dàng.	
  
•  Tệp	
  tiêu	
  đề	
  <openssl/evp.h>.	
  
•  Tệp	
  thư	
  viện:	
  libeay32.lib,	
  ssleay32.lib	
  
•  Mã	
  hóa	
  AES	
  với	
  OpenSSL	
  EVP.	
  
•  Khởi	
  tạo	
  khóa,	
  vector	
  khởi	
  tạo,	
  salt	
  với	
  EVP_BytesToKey	
  hoặc	
  tự	
  chọn	
  một	
  
bộ	
  Key,	
  IV	
  nào	
  đó.	
  
•  Khởi	
  tạo	
  ngữ	
  cảnh	
  mã	
  hóa	
  với	
  hàm	
  EVP_EncryptInit_ex.	
  
•  Khởi	
  tạo	
  ngữ	
  cảnh	
  giải	
  mã	
  với	
  hàm	
  EVP_DecryptInit_ex.	
  
•  Mã	
  hóa	
  dữ	
  liệu	
  bằng	
  việc	
  liên	
  tục	
  gọi	
  hàm	
  EVP_EncryptUpdate,	
  kết	
  thúc	
  
quá	
  trình	
  mã	
  hóa	
  bằng	
  hàm	
  EVP_EncryptFinal_ex.	
  
•  Giải	
  mã	
  dữ	
  liệu	
  bằng	
  việc	
  liên	
  tục	
  gọi	
  hàm	
  EVP_DecryptUpdate,	
  kết	
  thúc	
  
quá	
  trình	
  giải	
  mã	
  bằng	
  hàm	
  EVP_DecryptFinal_ex.	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
65	
  
•  VD	
  
•  Sinh	
  key	
  và	
  iv	
  bằng	
  hàm	
  EVP_BytesToKey	
  
char 	
  	
  	
  	
  	
  key[32];	
  
char 	
  	
  	
  	
  	
  iv[32]; 	
   	
  	
  
char 	
  *	
  key_data	
  =	
  “nopass”; 	
  	
  
unsigned	
  int	
  salt[]	
  =	
  {12345,	
  54321};	
  
EVP_BytesToKey(EVP_aes_256_cbc(),	
  EVP_sha1(),	
  salt,	
  key_data,	
  6,	
  1,	
  key,	
  
iv);	
  
•  Khởi	
  tạo	
  ngữ	
  cảnh	
  mã	
  hóa	
  với	
  key	
  và	
  iv	
  đã	
  chọn	
  
EVP_CIPHER_CTX 	
  e_ctx;	
  
EVP_CIPHER_CTX_init(&e_ctx);	
  
EVP_EncryptInit_ex(&e_ctx,	
  EVP_aes_256_cbc(),NULL,	
  key,	
  iv);	
  
•  Khởi	
  tạo	
  ngữ	
  cảnh	
  giải	
  mã	
  với	
  key	
  và	
  iv	
  đã	
  chọn	
  
EVP_CIPHER_CTX 	
  d_ctx;	
  
EVP_CIPHER_CTX_init(&d_ctx);	
  
EVP_DecryptInit_ex(&d_ctx,	
  EVP_aes_256_cbc(),NULL,	
  key,	
  iv);	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
66	
  
•  VD	
  (tiếp)	
  
•  Mã	
  hóa	
  với	
  ngữ	
  cảnh	
  đã	
  được	
  khởi	
  tạo	
  
char	
  *	
   	
  plaintext=“Hello”;	
  
int 	
  len	
  =	
  strlen(plaintext);	
  
char 	
  ciphertext[1024];	
  
int	
   	
  c_len	
  =	
  0,	
  f_len	
  =	
  0;	
  
/*	
  Gọi	
  lại	
  hàm	
  này	
  để	
  cho	
  phép	
  OpenSSL	
  sử	
  dụng	
  lại	
  ngữ	
  cảnh	
  phiên	
  mã	
  	
  
hóa	
  trước	
  */	
  
EVP_EncryptInit_ex(e,	
  NULL,	
  NULL,	
  NULL,	
  NULL);	
  
…	
  
//	
  Mỗi	
  chu	
  kỳ	
  Update,	
  c_len	
  sẽ	
  chứa	
  số	
  byte	
  của	
  xâu	
  mã	
  được	
  
EVP_EncryptUpdate(e,	
  ciphertext,	
  &c_len,	
  plaintext,	
  len);	
  
…	
  
//	
  Cuối	
  chu	
  kỳ	
  Update,	
  f_len	
  sẽ	
  chưa	
  số	
  byte	
  còn	
  lại	
  của	
  xâu	
  mã	
  
EVP_EncryptFinal_ex(e,	
  ciphertext+c_len,	
  &f_len);	
  
…	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
67	
  
•  VD	
  (tiếp)	
  
•  Giải	
  mã	
  với	
  ngữ	
  cảnh	
  đã	
  được	
  khởi	
  tạo	
  
	
  
char 	
  plaintext[1024];	
  
int 	
  p_len	
  =	
  0;	
  
/*	
  Gọi	
  lại	
  hàm	
  này	
  để	
  cho	
  phép	
  OpenSSL	
  sử	
  dụng	
  lại	
  ngữ	
  cảnh	
  phiên	
  giãi	
  
mã	
  	
  hóa	
  trước	
  */	
  
EVP_DecryptInit_ex(e,	
  NULL,	
  NULL,	
  NULL,	
  NULL);	
  
…	
  
//	
  Giải	
  mã	
  với	
  ciphertext	
  và	
  len	
  được	
  cung	
  cấp	
  trước	
  
EVP_DecryptUpdate(e,	
  plaintext,	
  &p_len,	
  ciphertext,	
  *len);	
  
…	
  
//	
  Kết	
  thúc	
  quá	
  trình	
  giải	
  mã,	
  cập	
  nhật	
  dữ	
  liệu	
  còn	
  lại	
  vào	
  plaintext.	
  
EVP_DecryptFinal_ex(e,	
  plaintext+p_len,	
  &f_len);	
  
4.5	
  Mã	
  hóa	
  đối	
  xứng	
  với	
  OpenSSL	
  
68	
  
•  Thư	
  viện	
  CryptoAPI	
  
•  Cung	
  cấp	
  các	
  hàm	
  mật	
  mã	
  học	
  cơ	
  bản	
  thông	
  qua	
  các	
  Cryptographic	
  Service	
  
Providers	
  (CSP).	
  	
  
•  Microsoft	
  Base	
  Cryptographic	
  Service	
  Provider:	
  RC2,	
  RC4,	
  DES	
  
•  Microsoft	
  Enhanced	
  Cryptographic	
  Service	
  Provider:	
  Triple-­‐DES	
  
•  Microsoft	
  AES	
  Cryptographic	
  Service	
  Provider:	
  AES	
  
•  …	
  
•  Cung	
  cấp	
  các	
  hàm	
  mã	
  hóa	
  và	
  giải	
  mã	
  chứng	
  thư	
  số,	
  và	
  đồng	
  thời	
  bổ	
  sung	
  
các	
  hàm	
  băm.	
  
•  Cung	
  cấp	
  các	
  hàm	
  quản	
  lý	
  và	
  lưu	
  trữ	
  chứng	
  thư	
  số.	
  
•  Các	
  hàm	
  mã	
  thông	
  điệp	
  hóa	
  mức	
  cao	
  (Simpli}ied	
  Message	
  Functions).	
  
•  Các	
  hàm	
  mã	
  hóa	
  thông	
  điệp	
  mức	
  thấp	
  (Low-­‐Level	
  Message	
  Functions).	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
69	
  
•  Thư	
  viện	
  CryptoAPI	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
70	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Tệp	
  tiêu	
  đề	
  wincript.h	
  
•  Thư	
  viện	
  Crypt32.lib	
  
•  Trình	
  tự	
  sử	
  dụng	
  
	
  
	
  
	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
71	
  
Khởi	
  tạo	
  
Provider	
  
Tạo	
  khóa	
  
• Ngẫu	
  nhiên	
  
• Từ	
  mật	
  khẩu	
  
• Từ	
  bên	
  ngoài	
  
Đặt	
  chế	
  độ	
  mã	
  
• CBC	
  
• ECB	
  
• …	
  
Thiết	
  lập	
  vector	
  
khởi	
  tạo	
  
Thực	
  hiện	
  Mã	
  
hóa/Giải	
  mã	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Khởi	
  tạo	
  ngữ	
  cảnh	
  Provider	
  thông	
  qua	
  hàm	
  CryptAcquireContext	
  
	
  BOOL	
  WINAPI	
  CryptAcquireContext(__out	
  HCRYPTPROV*	
  phProv,	
  	
  
	
   	
   	
   	
  __in	
  LPCTSTR	
  pszContainer,	
  	
  
	
   	
   	
   	
  __in	
  LPCTSTR	
  pszProvider,	
  	
  
	
   	
   	
   	
  __in	
  DWORD	
  dwProvType,	
  	
  
	
   	
   	
   	
  __in	
  DWORD	
  dwFlags	
  );	
  
VD:	
  
HCRYPTPROV	
   	
  hProvider;	
  
if	
  (!CryptAcquireContext(&hProvider,	
  	
  
	
   	
   	
   	
  0,	
  	
  
	
   	
   	
   	
  MS_ENH_RSA_AES_PROV,	
  	
  
	
   	
   	
   	
  PROV_RSA_AES,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
   	
   	
  CRYPT_VERIFYCONTEXT))	
  
	
   	
  	
  return	
  0;	
  
	
  	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
72	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Sử	
  dụng	
  Key	
  thông	
  qua	
  một	
  trong	
  ba	
  hàm.	
  Kết	
  quả	
  trả	
  về	
  là	
  đối	
  tượng	
  
HCRYPTKEY	
  
•  CryptGenKey(	
  ):	
  Sinh	
  khóa	
  ngẫu	
  nhiên.	
  
•  CryptDeriveKey(	
  ):	
  Sinh	
  khóa	
  từ	
  mật	
  khẩu.	
  
•  CryptImportKey(	
  )	
  :	
  Sinh	
  khóa	
  từ	
  một	
  đối	
  tượng	
  trong	
  bộ	
  nhớ.	
  
	
  
VD1.	
  Sinh	
  khóa	
  ngẫu	
  nhiên	
  
	
  
DWORD	
  dwFlags;	
  	
  
HCRYPTKEY	
  hKey;	
  	
  
DWORD	
  dwSize	
  =	
  256; 	
  	
  
dwFlags	
  =	
  ((dwSize	
  <<	
  16)	
  &	
  0xFFFF0000)	
  |	
  CRYPT_EXPORTABLE;	
  	
  
if	
  (!CryptGenKey(hProvider,	
  CALG_AES_256,	
  dwFlags,	
  &hKey))	
  return	
  0;	
  
	
  
	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
73	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
VD2.	
  Sinh	
  khóa	
  từ	
  mật	
  khẩu:	
  Cần	
  phải	
  băm	
  mật	
  khẩu	
  và	
  truyền	
  vào	
  hàm	
  CryptDeriveKey	
  
char	
  	
  *	
  password	
  =	
  “nopass”; 	
   	
  	
  
BOOL	
  bResult;	
  	
  
DWORD	
  cbData;	
  	
  
HCRYPTKEY	
  hKey;	
  	
   	
  //	
  Lưu	
  Key	
  
HCRYPTHASH	
  hHash;	
   	
  //	
  Lưu	
  giá	
  trị	
  băm	
  của	
  mật	
  khẩu	
  
if	
  (!CryptCreateHash(hProvider,	
  CALG_SHA1,	
  0,	
  0,	
  &hHash))	
  //	
  Khởi	
  tạo	
  hàm	
  băm	
  
	
  return	
  0;	
  	
  
cbData	
  =	
  lstrlen(password)	
  *	
  sizeof(TCHAR);	
  	
  
if	
  (!CryptHashData(hHash,	
  (BYTE	
  *)password,	
  cbData,	
  0))	
  	
  //	
  Băm	
  mật	
  khẩu	
  
	
  {	
  	
  
	
   	
  CryptDestroyHash(hHash);	
  	
  
	
   	
  return	
  0;	
  	
  
	
  }	
  
//	
  Tạo	
  key	
  từ	
  giá	
  trị	
  băm	
  của	
  mật	
  khẩu	
  
bResult	
  =	
  CryptDeriveKey(hProvider,	
  CALG_AES_256,	
  hHash,	
  CRYPT_EXPORTABLE,	
  
&hKey);	
  	
  
CryptDestroyHash(hHash);	
  	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
74	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Thiết	
  lập	
  chế	
  độ	
  mã	
  hóa	
  CBC	
  với	
  hàm	
  CryptSetKeyParam	
  
	
  DWORD 	
  dwMode	
  =	
  CRYPT_MODE_CBC;	
  
	
  CryptSetKeyParam(hKey,	
  KP_MODE,	
  (BYTE	
  *)&dwMode,	
  0);	
  
•  Sinh	
  ngẫu	
  nhiên	
  vector	
  khởi	
  tạo	
  (IV)	
  
BOOL	
  bResult;	
   	
   	
  	
  //	
  Lưu	
  kết	
  quả	
  
BYTE	
  *pbTemp;	
   	
   	
  //	
  Lưu	
  vector	
  khởi	
  tạo	
  
DWORD	
  dwBlockLen,	
  dwDataLen;	
  	
  
dwDataLen	
  =	
  sizeof(dwBlockLen);	
  
//	
  Lấy	
  kích	
  thước	
  block	
  của	
  thuật	
  toán	
  mã	
  hóa	
  
	
  if	
  (!CryptGetKeyParam(hKey,	
  KP_BLOCKLEN,	
  (BYTE	
  *)&dwBlockLen,	
  &dwDataLen,	
  
0))	
  return	
  0;	
  
dwBlockLen	
  /=	
  8;	
  	
  
if	
  (!(pbTemp	
  =	
  (BYTE	
  *)LocalAlloc(LMEM_FIXED,	
  dwBlockLen)))	
  	
  return	
  FALSE;	
  
//	
  Sinh	
  ngẫu	
  nhiên	
  IV	
  	
  
bResult	
  =	
  CryptGenRandom(hProvider,	
  dwBlockLen,	
  pbTemp);	
  
//	
  Thiết	
  lập	
  IV	
  
bResult	
  =	
  CryptSetKeyParam(hKey,	
  KP_IV,	
  pbTemp,	
  0);	
  	
  
LocalFree(pbTemp);	
  	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
75	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Mã	
  hóa	
  với	
  CryptEncrypt	
  
•  Với	
  các	
  giải	
  thuật	
  mã	
  hóa	
  dòng	
  thì	
  kích	
  thước	
  dữ	
  liệu	
  ra	
  =	
  kích	
  thước	
  dữ	
  liệu	
  vào.	
  
•  Với	
  các	
  giải	
  thuật	
  mã	
  hóa	
  khối	
  thì	
  kích	
  thước	
  dữ	
  liệu	
  ra	
  <=	
  	
  kích	
  thước	
  dữ	
  liệu	
  vào	
  
+	
  kích	
  thước	
  khối.	
  
•  Hàm	
  CryptEncrypt	
  sẽ	
  ghi	
  đè	
  dữ	
  liệu	
  mã	
  hóa	
  được	
  vào	
  bộ	
  đệm	
  chứa	
  dữ	
  liệu	
  vào.	
  
•  Đoạn	
  chương	
  trình	
  thực	
  hiện	
  mã	
  hóa	
  chung	
  cho	
  cả	
  hai	
  loại.	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
76	
  
ALG_ID 	
  Algid; 	
   	
   	
  //	
  Giải	
  thuật	
  mã	
  
char 	
  *	
  pbData	
  =	
  "Hello	
  CryptAPI";	
   	
  //	
  Xâu	
  nguồn	
  cần	
  mã	
  
char 	
  *	
  pbResult	
  =	
  0; 	
   	
  //	
  Xâu	
  kết	
  quả	
  
DWORD 	
  dwDataLen	
  =	
  0,dwBlockLen	
  =	
  0;	
  
	
  cbData	
  =	
  strlen(pbData); 	
  //	
  Chiều	
  dài	
  xâu	
  nguồn	
  
	
  	
  dwDataLen	
  =	
  sizeof(ALG_ID);	
  
//	
  Lấy	
  thông	
  tin	
  về	
  giải	
  thuật	
  mã	
  hóa	
  với	
  key	
  cho	
  trước	
  
	
  	
  if	
  (!CryptGetKeyParam(hKey,	
  KP_ALGID,	
  (BYTE	
  *)&Algid,	
  &dwDataLen,	
  0))	
  	
  
	
  return	
  0;	
  
	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Mã	
  hóa	
  với	
  CryptEncrypt	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
77	
  
if	
  (GET_ALG_TYPE(Algid)	
  !=	
  ALG_TYPE_STREAM)	
  	
  //	
  Mã	
  hóa	
  khối	
  
	
  	
  {	
  
	
  	
  	
  	
   	
  dwDataLen	
  =	
  sizeof(DWORD);	
   	
  	
  
	
  	
  	
  	
   	
  ret	
  =	
  CryptGetKeyParam(hKey,	
  	
  KP_BLOCKLEN,	
  (BYTE*)&dwBlockLen,	
  	
  
	
   	
   	
  &dwDataLen,	
  0);	
  //	
  Lấy	
  kích	
  thước	
  block	
  theo	
  bit	
  
	
  dwBlockLen	
  =	
  dwBlockLen/8;	
  //	
  Đổi	
  kích	
  thước	
  block	
  ra	
  đơn	
  vị	
  byte	
  
	
  	
  //	
  Cấp	
  phát	
  bộ	
  nhớ	
  để	
  chứa	
  kết	
  quả	
  	
  	
  
	
  pbResult	
  =	
  (char*)malloc(cbData+dwBlockLen);	
  
	
  memcpy(pbResult,pbData,cbData);	
  
	
  //	
  Thực	
  hiện	
  mã	
  hóa,	
  kết	
  quả	
  là	
  dwDataLen	
  byte	
  lưu	
  trong	
  pbResult	
  
	
  dwDataLen	
  =	
  cbData; 	
  	
  
	
  CryptEncrypt(hKey,	
  0,	
  TRUE,	
  0,	
  (BYTE*)pbResult,	
  &dwDataLen,	
  	
   	
  
	
   	
  cbData+16))	
  ;	
  
}	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Mã	
  hóa	
  với	
  CryptEncrypt	
  (tiếp)	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
78	
  
else 	
  //	
  Mã	
  hóa	
  dòng	
  
{	
  
	
  //	
  Cấp	
  phát	
  bộ	
  nhớ	
  lưu	
  kết	
  quả	
  
	
  pbResult	
  =	
  (char*)malloc(cbData);	
  
	
  //	
  Bảo	
  toàn	
  dữ	
  liệu	
  nguồn	
  
	
  memcpy(pbResult,pbData,cbData);	
  
	
  //	
  Thực	
  hiện	
  mã	
  hóa	
  
	
  CryptEncrypt(hKey,0,TRUE,0,pbResult,&dwDataLen,cbData);	
  
	
  
}	
  
•  Sử	
  dụng	
  thư	
  viện	
  CryptoAPI	
  để	
  thực	
  hiện	
  mã	
  hóa	
  đối	
  xứng	
  thông	
  điệp	
  
với	
  thuật	
  toán	
  AES.	
  
•  Giải	
  mã	
  với	
  CryptDecrypt	
  
•  Kích	
  thước	
  dữ	
  liệu	
  đích	
  <=	
  kích	
  thước	
  dữ	
  liệu	
  nguồn	
  
•  Thực	
  hiện	
  đơn	
  giản	
  hơn	
  so	
  với	
  CryptEncrypt	
  
•  Ví	
  dụ	
  
	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
79	
  
char	
  *	
  pbData	
  ;	
   	
   	
  //	
  Dữ	
  liệu	
  nguồn	
  
DWORD 	
  cbData; 	
   	
  //	
  Kích	
  thước	
  nguồn	
  
char	
  *	
  pbResult;	
   	
   	
  //	
  Dữ	
  liệu	
  đích	
  
DWORD 	
  dwDataLen; 	
  //	
  Kích	
  thước	
  đích	
  
…	
  
//	
  Cấp	
  phát	
  bộ	
  nhớ	
  và	
  sao	
  chép	
  dữ	
  liệu	
  nguồn	
  vào	
  đích	
  
pbResult	
  =	
  (char*)malloc(cbData);	
  
memcpy(pbResult,	
  pbData,	
  cbData);	
  
dwDataLen	
  =	
  cbDataLen;	
  
//	
  Giải	
  mã,	
  kết	
  quả	
  là	
  dwDataLen	
  byte	
  lưu	
  trong	
  pbResult	
  
CryptDecrypt(hKey,0,TRUE,0,pbResult,&dwDataLen);	
  
•  Trao	
  đổi	
  khóa	
  với	
  OpenSSL	
  
•  CryptoAPI	
  không	
  cho	
  phép	
  nhập	
  và	
  xuất	
  khóa	
  dạng	
  thô	
  như	
  OpenSSL.	
  
•  Để	
  trao	
  đổi	
  khóa	
  với	
  thư	
  viện	
  khác,	
  cần	
  mã	
  hóa	
  khóa	
  theo	
  giải	
  thuật	
  
AT_KEYEXCHANGE,	
  và	
  thực	
  hiện	
  nhập	
  xuất	
  dưới	
  dạng	
  cấu	
  trúc	
  BLOB.	
  
•  Hàm	
  CryptImportKeyvà	
  CryptExportKey	
  dùng	
  để	
  thực	
  hiện	
  nhập	
  xuất	
  
khóa.	
  
•  Xem	
  thêm	
  phần	
  5.26,	
  5.27	
  trong	
  Secure	
  Programming	
  Cookbook.	
  	
  
4.6	
  Microsoft	
  Crypto	
  API	
  
80	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  5.	
  Hàm	
  băm	
  và	
  xác	
  thực	
  
thông	
  điệp	
  
Hashes	
  and	
  Message	
  Authentication	
  
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	
  
Nội	
  dung	
  
82	
  
•  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	
  
5.1	
  Các	
  hàm	
  băm	
  và	
  MAC	
  thông	
  dụng	
  
83	
  
•  Hàm	
  băm	
  (hashes)	
  
5.1	
  Các	
  hàm	
  băm	
  và	
  MAC	
  thông	
  dụng	
  
84	
  
Algorithm	
   Digest	
  size	
   Security	
  conqidence	
  
Small	
  message	
  
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	
  
as	
  cipher	
  block	
  size)	
  
Good	
   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	
  
•  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	
  
5.1	
  Các	
  hàm	
  băm	
  và	
  MAC	
  thông	
  dụng	
  
85	
  
•  Xác	
  thực	
  thông	
  điệp	
  (Message	
  Authentication	
  Code)	
  
5.1	
  Các	
  hàm	
  băm	
  và	
  MAC	
  thông	
  dụng	
  
86	
  
MAC	
   Built	
  upon	
  
Small	
  message	
  
speed	
  (64	
  
bytes)[4]	
  
Large	
  message	
  
speed	
  (8K)	
  
Appropriate	
  
for	
  hardware	
  
Patent	
  restric-­‐
tions	
  
Parallel-­‐izable	
  
CMAC	
  
A	
  universal	
  hash	
  
and	
  AES	
  
~18	
  cpb	
   ~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	
  
162	
  cpb	
   29	
  cpb	
   Yes	
   Yes	
   Yes	
  
•  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:	
  <openssl/evp.h>	
  
•  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.	
  
5.2	
  Băm	
  dữ	
  liệu	
  với	
  OpenSSL	
  
87	
  
•  VD:	
  Băm	
  với	
  SHA1	
  
5.2	
  Băm	
  dữ	
  liệu	
  với	
  OpenSSL	
  
88	
  
	
  #include	
  <openssl/sha.h>	
  
	
  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");	
  
•  VD:	
  Băm	
  với	
  giao	
  diện	
  EVP	
  
5.2	
  Băm	
  dữ	
  liệu	
  với	
  OpenSSL	
  
89	
  
#include	
  <openssl/evp.h>	
  
#include	
  <stdio.h>	
  
#include	
  <string.h>	
  
	
  	
  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);	
  
•  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	
  
5.3	
  Băm	
  dữ	
  liệu	
  với	
  CryptoAPI	
  
90	
  
•  Ví	
  dụ:	
  Băm	
  dữ	
  liệu	
  với	
  thuật	
  toán	
  SHA-­‐256	
  
5.3	
  Băm	
  dữ	
  liệu	
  với	
  CryptoAPI	
  
91	
  
	
  	
  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…	
  
	
  	
  	
  
•  Ví	
  dụ:	
  Băm	
  dữ	
  liệu	
  với	
  thuật	
  toán	
  SHA-­‐256	
  (tiếp)	
  
5.3	
  Băm	
  dữ	
  liệu	
  với	
  CryptoAPI	
  
92	
  
	
  	
  //	
  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);	
  	
  	
  
	
  	
  	
  
•  Với	
  OpenSSL	
  
–  Tệp	
  tiêu	
  đều	
  <openssl/hmac.h>	
  
–  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ả	
  
5.4	
  Xác	
  thực	
  thông	
  điệp	
  với	
  HMAC	
  
93	
  
•  Với	
  OpenSSL	
  
5.4	
  Xác	
  thực	
  thông	
  điệp	
  với	
  HMAC	
  
94	
  
	
  	
  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");	
  
•  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	
  
	
  
5.4	
  Xác	
  thực	
  thông	
  điệp	
  với	
  HMAC	
  
95	
  
•  Với	
  CryptAPI	
  
	
  
5.4	
  Xác	
  thực	
  thông	
  điệp	
  với	
  HMAC	
  
96	
  
	
  	
  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);	
  
	
  	
  	
  
•  Với	
  CryptAPI	
  
	
  
5.4	
  Xác	
  thực	
  thông	
  điệp	
  với	
  HMAC	
  
97	
  
//	
  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);	
  
	
  	
  	
  
•  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.	
  
	
  
5.5	
  Sử	
  dụng	
  Salt	
  
98	
  
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:	
  
	
  <Kích	
  thước><Nội	
  dung	
  tệp	
  tin	
  đã	
  mã><Giá	
  trị	
  băm	
  SHA-­‐256>	
  
	
  
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	
  
	
  
Bài	
  tập	
  
99	
  
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.	
  
	
  
Bài	
  tập	
  
100	
  
Lương	
  Ánh	
  Hoàng	
  
hoangla@soict.hut.edu.vn	
  
Chương	
  6.	
  Mã	
  hóa	
  công	
  khai	
  
Public	
  Key	
  Cryptography	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  
6.2	
  Chữ	
  ký	
  số	
  
6.3	
  Biểu	
  diễn	
  khóa	
  
6.4	
  Kết	
  nối	
  SSL	
  
6.5	
  Hạ	
  tầng	
  khóa	
  công	
  khai	
  
	
  
Nội	
  dung	
  
102	
  
•  Mã	
  hóa	
  bất	
  đối	
  xứng	
  
•  Là	
  các	
  giải	
  thuật	
  sử	
  dụng	
  một	
  cặp	
  khóa	
  cho	
  việc	
  mã	
  hóa	
  và	
  giải	
  mã	
  
•  Dữ	
  liệu	
  được	
  mã	
  hóa	
  bằng	
  khóa	
  công	
  khai	
  sẽ	
  được	
  giải	
  mã	
  bằng	
  
khóa	
  bí	
  mật	
  và	
  ngược	
  lại.	
  
•  Các	
  giải	
  thuật	
  thông	
  dụng:	
  RSA,	
  DSA,	
  Dif}ie-­‐Hellman.	
  
•  Không	
  sử	
  dụng	
  trực	
  tiếp	
  để	
  mã	
  hóa	
  dữ	
  liệu	
  vì	
  tốc	
  độ	
  rất	
  chậm.	
  
•  Thường	
  được	
  sử	
  dụng	
  để	
  
•  Trao	
  đổi	
  khóa	
  đối	
  xứng	
  trong	
  phiên	
  truyền	
  mật	
  
•  Chữ	
  ký	
  số	
  
•  Xác	
  nhận	
  danh	
  tính	
  
•  …	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  	
  
103	
  
•  OpenSSL	
  RSA	
  
•  Thường	
  được	
  sử	
  dụng	
  trao	
  đổi	
  khóa	
  
•  Lưu	
  trữ	
  tất	
  cả	
  thông	
  tin	
  về	
  một	
  khóa	
  dưới	
  cấu	
  trúc	
  RSA.	
  
•  Tệp	
  tiêu	
  đề	
  rsa.h	
  
•  Sinh	
  cặp	
  khóa	
  đối	
  xứng	
  bằng	
  hàm	
  	
  
	
  
RSA	
  *RSA_generate_key(int	
  bits,	
  	
  	
  //	
  Kích	
  thước	
  khóa:	
  1024,2048…	
  
	
   	
   	
  unsigned	
  long	
  exp,//	
  Số	
  mũ:	
  3,	
  17,	
  65537	
  	
  
	
   	
   	
  void	
  (*cb)(int,	
  int,	
  void),	
  	
  //	
  Callback	
  
	
   	
   	
  void	
  *cb_arg);	
  
	
  	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  	
  
104	
  
•  Mã	
  hóa	
  với	
  khóa	
  công	
  khai	
  
•  Sử	
  dụng	
  hàm	
  RSA_public_encrypt:	
  
	
  int	
  RSA_public_encrypt(int	
  l,	
  //	
  Chiều	
  dài	
  dữ	
  liệu 	
  	
  
	
   	
   	
  unsigned	
  char	
  *pt,	
  //	
  Xâu/số	
  cần	
  mã	
  
	
   	
   	
  unsigned	
  char	
  *ct,	
  //	
  Kết	
  quả	
  
	
   	
   	
  RSA	
  *r,	
   	
   	
  	
  	
  	
  //	
  Cấu	
  trúc	
  RSA 	
  	
  
	
   	
   	
  int	
  p); 	
   	
  	
  	
  	
  //	
  Kiểu	
  padding	
  
	
  Kết	
  quả	
  trả	
  về:	
  chiều	
  dài	
  xâu	
  mã	
  được. 	
  	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  	
  
105	
  
•  Giải	
  mã	
  với	
  khóa	
  bí	
  mật	
  
•  Sử	
  dụng	
  hàm	
  RSA_private_decrypt:	
  
	
  int	
  RSA_private_decrypt(int	
  l,	
  	
  	
  
	
   	
   	
  unsigned	
  char	
  *ct,	
  	
  
	
   	
   	
  unsigned	
  char	
  *pt,	
  
	
   	
   	
  	
  RSA	
  *r,	
  	
  
	
   	
   	
  int	
  p);	
  
	
  Kết	
  quả	
  trả	
  về:	
  chiều	
  dài	
  xâu	
  giải	
  mã	
  được	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  	
  
106	
  
•  Bài	
  tập	
  
–  Viết	
  chương	
  trình	
  chat	
  console	
  client-­‐server	
  sử	
  dụng	
  giải	
  thuật	
  
RSA.	
  Chỉ	
  chia	
  sẻ	
  public	
  key	
  trên	
  đường	
  truyền.	
  
6.1	
  Mã	
  hóa	
  với	
  OpenSSL	
  RSA	
  	
  
107	
  
•  Chữ	
  ký	
  số	
  dữ	
  liệu	
  nhằm	
  xác	
  thực	
  danh	
  tính	
  của	
  người	
  gửi,	
  tương	
  tự	
  
như	
  HMAC	
  nhưng	
  sử	
  dụng	
  giải	
  thuật	
  RSA	
  
•  Quá	
  trình	
  ký	
  số	
  dữ	
  liệu	
  nhận	
  đầu	
  vào	
  là	
  giá	
  trị	
  băm	
  của	
  thông	
  điệp,	
  
khóa	
  bí	
  mật	
  của	
  người	
  gửi,	
  đầu	
  ra	
  là	
  giá	
  trị	
  hàm	
  băm	
  đã	
  được	
  mã	
  hóa.	
  
•  Bên	
  nhận	
  thực	
  hiện	
  quá	
  trình	
  ngược	
  lại:	
  tính	
  giá	
  trị	
  băm	
  của	
  thông	
  
điệp,	
  giải	
  mã	
  giá	
  trị	
  băm	
  đã	
  mã	
  hóa	
  của	
  bên	
  gửi	
  bằng	
  khóa	
  công	
  khai	
  và	
  
so	
  sánh	
  hai	
  giá	
  trị	
  băm	
  này.	
  
•  Hacker	
  không	
  thể	
  giả	
  mạo	
  giá	
  trị	
  băm	
  vì	
  không	
  có	
  khóa	
  bí	
  mật	
  của	
  bên	
  
gửi.	
  
6.2	
  Chữ	
  ký	
  số	
  	
  
108	
  
•  Sơ	
  đồ	
  ký	
  
6.2	
  Chữ	
  ký	
  số	
  	
  
109	
  
Dữ	
  liệu	
  
Giá	
  trị	
  băm	
  
(MD)	
  
Hash	
  
(SHA1)	
  
Chữ	
  ký	
  
Khóa	
  bí	
  mật	
  
Mã	
  hóa	
  
Dữ	
  liệu	
  +	
  Chữ	
  
ký	
  
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming
Lập Trình an toàn - Secure programming

More Related Content

What's hot

Bai tap-thuc-hanh-he-quan-tri-csdl
Bai tap-thuc-hanh-he-quan-tri-csdlBai tap-thuc-hanh-he-quan-tri-csdl
Bai tap-thuc-hanh-he-quan-tri-csdlgiang nguyen le
 
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng Lương Bá Hợp
 
Tư duy logic và giải quyết vấn đề
Tư duy logic và giải quyết vấn đềTư duy logic và giải quyết vấn đề
Tư duy logic và giải quyết vấn đềLê Văn Duy
 
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"Tú Cao
 
Bai 02 cac thanh phan phan cung may tinh
Bai 02  cac thanh phan phan cung may tinhBai 02  cac thanh phan phan cung may tinh
Bai 02 cac thanh phan phan cung may tinhQuang Nguyễn Thái
 
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu học
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu họcXây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu học
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu họcsunflower_micro
 
Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Hồ Lợi
 
Phương Pháp Nghiên Cứu Định Tính
Phương Pháp Nghiên Cứu Định Tính Phương Pháp Nghiên Cứu Định Tính
Phương Pháp Nghiên Cứu Định Tính nataliej4
 
Cơ sở dữ liệu phân tán
Cơ sở dữ liệu phân tánCơ sở dữ liệu phân tán
Cơ sở dữ liệu phân tánQuy Nguyen
 
Tai lieu ve raid
Tai lieu ve raidTai lieu ve raid
Tai lieu ve raidHuynh MVT
 
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạn
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạnbáo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạn
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạnnataliej4
 
Lightweight Transactions in Scylla versus Apache Cassandra
Lightweight Transactions in Scylla versus Apache CassandraLightweight Transactions in Scylla versus Apache Cassandra
Lightweight Transactions in Scylla versus Apache CassandraScyllaDB
 
Bàn về đọc sách
Bàn về đọc sáchBàn về đọc sách
Bàn về đọc sáchNgoc Ha Pham
 
Phân tích và thiết kế HTTT
Phân tích và thiết kế HTTTPhân tích và thiết kế HTTT
Phân tích và thiết kế HTTTLy hai
 
Xây dựng biểu đồ use case
Xây dựng biểu đồ use caseXây dựng biểu đồ use case
Xây dựng biểu đồ use caseTrung Chinh Hà
 
Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Hồ Lợi
 
Sizing Your Scylla Cluster
Sizing Your Scylla ClusterSizing Your Scylla Cluster
Sizing Your Scylla ClusterScyllaDB
 
Các thuật ngữ viết tắt trong tin học
Các thuật ngữ viết tắt trong tin họcCác thuật ngữ viết tắt trong tin học
Các thuật ngữ viết tắt trong tin họcRosie2505
 

What's hot (20)

Bai tap-thuc-hanh-he-quan-tri-csdl
Bai tap-thuc-hanh-he-quan-tri-csdlBai tap-thuc-hanh-he-quan-tri-csdl
Bai tap-thuc-hanh-he-quan-tri-csdl
 
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng
Đồ án tốt nghiệp : Xậy dựng hệ thống quản lý doanh nghiệp đa nền tảng
 
Tư duy logic và giải quyết vấn đề
Tư duy logic và giải quyết vấn đềTư duy logic và giải quyết vấn đề
Tư duy logic và giải quyết vấn đề
 
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"
Slide báo cáo đồ án tốt nghiệp "Website cửa hàng điện thoại trực tuyến"
 
Bai 02 cac thanh phan phan cung may tinh
Bai 02  cac thanh phan phan cung may tinhBai 02  cac thanh phan phan cung may tinh
Bai 02 cac thanh phan phan cung may tinh
 
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu học
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu họcXây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu học
Xây dựng dự án thư viện điện tử cho các trường trung học phổ thông và tiểu học
 
Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12
 
Phương Pháp Nghiên Cứu Định Tính
Phương Pháp Nghiên Cứu Định Tính Phương Pháp Nghiên Cứu Định Tính
Phương Pháp Nghiên Cứu Định Tính
 
Cơ sở dữ liệu phân tán
Cơ sở dữ liệu phân tánCơ sở dữ liệu phân tán
Cơ sở dữ liệu phân tán
 
Tai lieu ve raid
Tai lieu ve raidTai lieu ve raid
Tai lieu ve raid
 
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạn
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạnbáo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạn
báo cáo bài tập lớn phân tích thiết kế hệ thống quản lý khách sạn
 
Lightweight Transactions in Scylla versus Apache Cassandra
Lightweight Transactions in Scylla versus Apache CassandraLightweight Transactions in Scylla versus Apache Cassandra
Lightweight Transactions in Scylla versus Apache Cassandra
 
Bàn về đọc sách
Bàn về đọc sáchBàn về đọc sách
Bàn về đọc sách
 
Phân tích và thiết kế HTTT
Phân tích và thiết kế HTTTPhân tích và thiết kế HTTT
Phân tích và thiết kế HTTT
 
Xây dựng biểu đồ use case
Xây dựng biểu đồ use caseXây dựng biểu đồ use case
Xây dựng biểu đồ use case
 
Báo Cáo Thực Tập Ứng Dụng Công Nghệ Thông Tin Vào Công Tác Quản Lý
Báo Cáo Thực Tập Ứng Dụng Công Nghệ Thông Tin Vào Công Tác Quản LýBáo Cáo Thực Tập Ứng Dụng Công Nghệ Thông Tin Vào Công Tác Quản Lý
Báo Cáo Thực Tập Ứng Dụng Công Nghệ Thông Tin Vào Công Tác Quản Lý
 
Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Bài tập CTDL và GT 1
Bài tập CTDL và GT 1
 
Sizing Your Scylla Cluster
Sizing Your Scylla ClusterSizing Your Scylla Cluster
Sizing Your Scylla Cluster
 
Các thuật ngữ viết tắt trong tin học
Các thuật ngữ viết tắt trong tin họcCác thuật ngữ viết tắt trong tin học
Các thuật ngữ viết tắt trong tin học
 
Com201 slide 5
Com201   slide 5Com201   slide 5
Com201 slide 5
 

Similar to Lập Trình an toàn - Secure programming

Similar to Lập Trình an toàn - Secure programming (20)

Basic C programming
Basic C programmingBasic C programming
Basic C programming
 
Slide pointer sepro
Slide pointer seproSlide pointer sepro
Slide pointer sepro
 
Control structure in C
Control structure in CControl structure in C
Control structure in C
 
T4
T4T4
T4
 
Chapter07 io
Chapter07 ioChapter07 io
Chapter07 io
 
OOP_02_Java can ban.pdf
OOP_02_Java can ban.pdfOOP_02_Java can ban.pdf
OOP_02_Java can ban.pdf
 
Oop unit 02 java cơ bản
Oop unit 02 java cơ bảnOop unit 02 java cơ bản
Oop unit 02 java cơ bản
 
C đến C++ phần 1
C đến C++ phần 1C đến C++ phần 1
C đến C++ phần 1
 
Buffer overflow(bao cao)
Buffer overflow(bao cao)Buffer overflow(bao cao)
Buffer overflow(bao cao)
 
Ctdl lab01
Ctdl lab01Ctdl lab01
Ctdl lab01
 
Bài tập mẫu C và C++ có giải
Bài tập mẫu C và C++ có giảiBài tập mẫu C và C++ có giải
Bài tập mẫu C và C++ có giải
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapc
 
CáC KiểU Dữ LiệU
CáC KiểU Dữ LiệUCáC KiểU Dữ LiệU
CáC KiểU Dữ LiệU
 
Oop unit 10 ngoại lệ
Oop unit 10 ngoại lệOop unit 10 ngoại lệ
Oop unit 10 ngoại lệ
 
C9 templates
C9 templatesC9 templates
C9 templates
 
C9 templates
C9 templatesC9 templates
C9 templates
 
06 tong quan ve ngon ngu c
06 tong quan ve ngon ngu c06 tong quan ve ngon ngu c
06 tong quan ve ngon ngu c
 
Slide py-sys-devops-final-v1
Slide py-sys-devops-final-v1Slide py-sys-devops-final-v1
Slide py-sys-devops-final-v1
 
String c++
String c++String c++
String c++
 
Giao trinh bai tap c va c++
Giao trinh bai tap c va c++Giao trinh bai tap c va c++
Giao trinh bai tap c va c++
 

Lập Trình an toàn - Secure programming

  • 1. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   LẬP  TRÌNH  AN  TOÀN   Secure  Programming  
  • 2. •  Cung  cấp  các  kiến  thức,  kỹ  thuật  cơ  bản  để  xây  dựng  các  ứng  dụng  an   toàn.   Mục  đích   2  
  • 3. •  Yêu  cầu  về  kiến  thức:   –  An  ninh  mạng   –  Ngôn  ngữ  lập  trình  C/C++.   •  Lên  lớp  đầy  đủ   Yêu  cầu   3  
  • 4. •  Thời  lượng:  45  tiết   –  Lý  thuyết:  30  tiết   –  Bài  tập:15  tiết   Thời  lượng  môn  học   4  
  • 5. •  Secure  Program  Cookbook  for  C  and  C++,  Matt  Messier,   John  Viega,  O'Reilly  2003.   Tài  liệu   5  
  • 6. •  Chương  1.  Kiểm  tra  đầu  vào   •  Chương  2.  Kiểm  soát  truy  nhập   •  Chương  3.  Kiểm  soát  xung  đột   •  Chương  4.  Mã  hóa  đối  xứng   •  Chương  5.  Hàm  băm  và  xác  thực  thông  điệp   •  Chương  6.  Mã  hóa  công  khai   •  Chương  7.  Anti-­‐Tampering   •  Chương  8.  Các  vấn  đề  khác   Nội  dung   6  
  • 8. •  Bài  tập  lớn:  70%   •  Quá  trình:  30%   Đánh  giá   8  
  • 9. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  1.  Kiểm  tra  đầu  vào   Input  Validation  
  • 10. 1.1  Nguyên  tắc  kiểm  tra.   1.2  Các  hàm  định  dạng  xâu  (string  formatting)  .   1.3  Tràn  bộ  đệm.   1.4  Tràn  số  học.   1.5  Kiểm  tra  tên  }ile  và  đường  dẫn.   1.6  Giải  mã  URL   1.7  Cross-­‐Site  Scripting   1.8  SQL  Injection   Nội  dung   10  
  • 11. •  Luôn  luôn  giả  định  dữ  liệu  đầu  vào  là  không  đáng  tin  cậy   –  Dữ  liệu  từ  mạng  trong  mô  hình  client-­‐server   –  Dữ  liệu  từ  người  dùng   –  Dữ  liệu  từ  tệp  tin   –  …   •  Ưu  tiên  loại  bỏ  dữ  liệu  hơn  là  cố  gắng  sửa  chữa  dữ  liệu.   •  Thực  hiện  kiểm  tra  đầu  vào  tại  nhiều  cấp,  nhiều  điểm   –  Kiểm  tra  đầu  vào  ở  các  hàm   –  Kiểm  tra  đầu  vào  giữa  các  module.   –  …   •  Không  tiếp  nhận  lệnh  trực  tiếp  từ  người  dùng  nếu  chưa  qua  kiểm  tra.   •  Kiểm  tra  các  ký  tự  đặc  biệt,  dấu  nháy.   •  Tìm  hiểu  và  sử  dụng  cơ  chế  trích  dẫn  (quoting  mechanism)  nếu  cần.   •  Càng  hiểu  về  dữ  liệu  bao  nhiêu  càng  lọc  được  tốt  bấy  nhiêu.   1.1  Các  nguyên  tắc  kiểm  tra   11  
  • 12. •  Họ  các  hàm  printf()  ,  syslog()    cho  phép  định  dạng  dữ  liệu  rất  mềm  dẻo  và   mạnh  mẽ  tuy  nhiên  cũng  cực  kỳ  nguy  hiểm.   •  Thận  trọng  khi  sử  dụng  “%n”   –  Tham  số  %n  cho  phép  ghi  ra  số  lượng  ký  tự  đã  kết  xuất  được  ra  một  địa  chỉ  bất  kỳ  chỉ  ra   trong  tham  số  tương  ứng.  Nếu  không  tồn  tại  tham  số  nào  thì  printf  sẽ  ghi  đè  lên  một  vùng   nào  đó  thuộc  stack  của  luồng  đang  thực  thi.   –  VD.   int  counter  =  0;   printf(“Hello%n”,&counter);  //  OK,  counter  =  5   printf(“Hello%n”);  //  Nguy  hiểm  !!!     •  Không  sử  dụng  trực  tiếp  xâu  định  dạng  từ  nguồn  bên  ngoài   –  Xâu  định  dạng  có  nguồn  gốc  từ  ngoài  chương  trình  có  thể  có  một  vài  ký  tự  đặc  biệt  mà   chương  trình  chưa  lường  trước  được,  hoặc  không  có  tham  số  thay  thế  tương  ứng.     –  VD.    char  str[1024];    gets(str);    printf(“Xin  chao:”);    printf(str);  //  Nguy  hiểm  !!!    printf(“%s”,str);  //  OK     1.2  Các  hàm  định  dạng  xâu   12  
  • 13. •  Thận  trọng  khi  sử  dụng  sprintf,  vsprintf  với  “%s”   –  Các  hàm  trên  đều  giả  định  kích  thước  bộ  đệm  cho  xâu  đích  là  vô  hạn.   –  Nên  chỉ  rõ  số  lượng  ký  tự  tối  đa  sẽ  sử  dụng  khi  dùng  với  %s.   –  Nên  sử  dụng  snprintf,  vsnprintf  nếu  có  thể.   –  VD   char  str[1024];   char  dst[32];   gets(str);   sprintf(dst,”Xau  vua  nhap  vao  la  %s”,str);  //  Nguy  hiểm   sprintf(dst,”Xau  vua  nhap  vao  la  %.16s”,str);  //  OK   snprintf(dst,32,”Xau  vua  nhap  vao  la  %s”,str);//  OK       1.2  Các  hàm  định  dạng  xâu   13  
  • 14. •  Tràn  bộ  đệm  (Buffer  Over}low):  copy  dữ  liệu  vượt  quá  biên  của  một  bộ   đệm  nào  đó  =>  đè  lên  vùng  nhớ  của  biến  (cấu  trúc)  khác.   •  Phần  lớn  các  hàm  xử  lý  xâu  trong  C  đều  không  thực  hiện  kiểm  tra  biên   của  bộ  đệm:  gets,  strcpy,  …   •  VD1:  Dữ  liệu  bị  hỏng    int    x  =  0;    char  buff[8];    strcpy(buff,”Hello      AAAAAAAAAAAAAAAAAAAAAAAAAAAAA”);    printf(“%d”,x);   •  VD2:  Stack  bị  hỏng    char  name[8];    gets(name);    printf(name);     1.3  Tràn  bộ  đệm   14  
  • 15. •  VD3:  Không  trở  về  được  từ  chương  trình  con    void  Hello()    {      char  name[8];      printf(“What  is  your  name  ?”);      gets(name);      printf(“Hello  %s  !”,  name);      }      void  main()    {      Hello();      printf(“Bye”);    }   1.3  Tràn  bộ  đệm   15  
  • 16. •  VD4:  Tấn  công  có  chủ  ý  trên  bộ  đệm    void  Bye()    {      printf(“Bye”);    }    void  Hello()    {      void  (*p)()  =  Bye;      char  name[8];      printf(“What  is  your  name  ?”);      gets(name);      printf(“Hello  %s  !”,  name);      p();      }      void  main()    {      Hello();    }   1.3  Tràn  bộ  đệm   16  
  • 17. •  Giải  pháp:     –  Sử  dụng  các  hàm  strncpy,  memcpy…và  những  hàm  có  kiểm  soát  kích  thước   bộ  đệm  một  cách  tường  minh.   –  Sử  dụng  Stack  Guard  trong  các  trình  biên  dịch  hỗ  trợ.     –  Sử  dụng  DEP  (Data  Execution  Preventation)  trên  hệ  điều  hành  hỗ  trợ.   –  Sử  dụng  ASLR  (Address  Space  Layout  Randomization)  trên  trình  biên   dịch  và  hệ  điều  hành  hỗ  trợ.   1.3  Tràn  bộ  đệm   17  
  • 18. •  Dữ  liệu  nhận  về  có  thể  có  sai  sót  trong  trường  liên  quan  đến  kích   thước.   •  Các  thao  tác  liên  quan  đến  số  nguyên  lớn  có  thể  bị  tràn,  lẫn  lộn  giữa  số   nguyên  không  dấu  và  có  dấu   •  VD1:  Tràn  số   unsigned    int  x  =  0xFFFFFFFF;  //  MAX_INT   if  (  x+5  >  5  )  printf  (“X  >  0”  )    else  printf(“X  <  0”);   •  VD2:  Dùng  sai  kiểu  có/không  dấu                  if  (x  <  MAX_SIZE)  {    //  x,  số  byte  cần  cấp  phát  tùy  theo  giải  thuật  tính  được        if  (!(ptr  =  (unsigned  char  *)malloc(x)))  abort(    );    }      else      {          /*  Handle  the  error  condition  ...  */    }             1.4  Tràn  số  học   18  
  • 19. •  Dữ  liệu  nhận  về  có  thể  là  tên  }ile,  ứng  dụng  cần  xác  định  đường  dẫn   tuyệt  đối  nếu  cần  thiết.   •  Dùng  hàm  realpath()  trên  Unix/Linux  và  GetFullPathName  trên   Windows.   •  Sử  dụng  realpath()   §  Nguyên  mẫu:      char  *realpath(const  char  *pathname,  char  resolved_path[MAXPATHLEN]);   §  Thận  trọng:  Có  thể  tràn  resolved_path  và  không  thread-­‐safe.   §  Thư  viện:  stdlih.h   §  VD    char  resolved[1024];    char  *  result  =  realpath("printf.c",resolved);    printf("%s",result);         1.5  Kiểm  tra  tên  qile  và  đường  dẫn   19  
  • 20. •  Sử  dụng  GetFullPathName()   §  Thư  viện:  windows.h   §  Nguyên  mẫu:      DWORD  GetFullPathName(LPCTSTR  lpFileName,  DWORD  nBufferLength,  LPTSTR                              lpBuffer,  LPTSTR  *lpFilePath);   §  VD:    int  nBufferLen  =  0;    LPTSTR  lpBuffer;      nBufferLen  =  GetFullPathName(L"test.c",0,0,0);    if  (nBufferLen>0)    {      lpBuffer  =  new  TCHAR[nBufferLen+1];      GetFullPathName(L"test.c",nBufferLen,lpBuffer,0);      wprintf(L"%s",lpBuffer);    }             1.5  Kiểm  tra  tên  qile  và  đường  dẫn   20  
  • 21. •  RFC  1738  quy  định  cách  mã  hóa  các  ký  tự  không  nhìn  thấy  được  trong   URL  dưới  dạng  “%<Mã  hexa>”.   •  VD:    http://m%61il.google.com    http://m%25%36%31il.google.com   •  Cách  giải  mã:  duyệt  từ  đầu  đến  cuối  ,  tìm  các  ký  tự  %  và  thay  thế  bằng   mã  ASCII  tương  ứng.   •  Không  sử  dụng  các  hàm  xử  lý  xâu  chuẩn  vì  có  thể  có  ký  tự  NULL  trong   URL.             1.6  Giải  mã  URL   21  
  • 22. •  Cross-­‐Site  Scripting  (XSS)  là  hình  thức  tấn  công  vào  trình  duyệt  người   dùng  bắt  nguồn  từ  việc  kiểm  tra  lỏng  lẻo  từ  server.   •  Có  thể  dẫn  đến  thất  thoát  thông  tin  nhạy  cảm:  mật  khẩu,  session,   cookie…   •  Thực  hiện  bằng  cách  chèn  mã  HTML/JAVASCRIPT  vào  dữ  liệu  sẽ  hiển   thị  ra  trình  duyệt  =>  đoạn  mã  sẽ  chạy  trên  trình  duyệt  của  nạn  nhân.   •  VD.  Một  ứng  dụng  web  có  hai  trang   –  Hello.php:  Hiển  thị  form  và  nhận  tên  của  người  dùng.   –  Chao.php:  hiển  thị  tên  nhận  được  lại  cho  người  dùng.             1.7  Cross-­‐Site  Scripting   22  
  • 23. •  File  Hello.php   <HTML>   Xin  chào,  vui  lòng  nhập  tên  bạn   <FORM  action="chao.php"  method=“POST">   <input  type="text"  name="name"/><br/>   <input  type="submit"  value="Submit">   </FORM>   </HTML>   •  File  Chao.php   <?PHP   echo  "Xin  chao  ".$_POST['name'];   ?>   •  Demo   •  Với  tên  là  :  Secure   •  Với  tên  là:  Secure  <script>alert('XSS  was  found  !');</script>     •  Với  tên  là:  Secure  <s%63ript>alert(‘Hacked’);</s%63ript>   •  Giải  pháp:  Lọc  bỏ  các  thẻ  HTML  khỏi  dữ  liệu  từ  người  dùng.  Mỗi  ngôn   ngữ  lập  trình  có  một  cách  riêng.   1.7  Cross-­‐Site  Scripting   23  
  • 24. •  SQL  Injection:  Tấn  công  vào  CSDL  thông  qua  dữ  liệu  nhập  từ  trình   duyệt.   •  Lợi  dụng  việc  kiểm  tra  lỏng  lẻo  từ  đầu  vào,  chèn  mã  lệnh  SQL  vào  các   truy  vấn  đến  CSDL  của  ứng  dụng  web.     •  Thường  lợi  dụng    dấu  nháy  “  ‘  “  để  kết  thúc  câu  truy  vấn  SQL  hoặc  thêm   các  câu  truy  vấn  khác.   •  VD:  Lệnh  so  sánh  tên  và  mật  khẩu  trong  SQL   –  select  *  from  users  where  username  =  ‘$user’  and  password  =  ‘$pass’     –  Nếu  $user  hoặc  $pass  chứa  dấu  “’”  thì  SQL  sẽ  hiểu  nhầm  nội  dung  truy   vấn…   •  Các  kỹ  thuật  khai  thác:  An  ninh  mạng   •  VD:  Một  ứng  dụng  web  muốn  kiểm  tra  tên  và  mật  khẩu  gồm  hai  trang   –  ask.php:  Hiện  form  đăng  nhập  và  thu  nhận  tên,  mật  khẩu   –  login.php:  Kết  nối  đến  CSDL  và  kiểm  tra   1.8  SQL  Injection   24  
  • 25. •  VD  (tiếp   –  File  ask.php    <HTML>   Vui  long  nhap  ten  va  mat  khau   <FORM  action="login.php"  method="GET">   Ten:  <INPUT  type="text"  name="user"/><BR/>   Mat  khau:<INPUT  type="text"  name="pass"/><BR/>   <INPUT  type="submit"  name="Submit">     </FORM>       1.8  SQL  Injection   25  
  • 26. •  VD  (tiếp)   –  File  login.php    <?PHP   $db_server  =  "localhost";   $db_username=  "root";   $db_password=  "123456";   $db  =  "test";   $table  =  "users";   $conn  =  mysql_connect($server,$db_username,$db_password);   if  (!$conn)    {      echo  "Khong  ket  noi  dc  den  CSDL";      return;    }   $ret    =  mysql_select_db($db,$conn);   1.8  SQL  Injection   26  
  • 27.  if  (!$ret)  {      echo  "Khong  ton  tai  CSLD  tuong  ung";      return;      }   $user  =  $_GET['name'];   $pass  =  $_GET['pass'];     $sql  =  "select  *  from  $table  where  username='$user'  and  password='$pass'";   echo  $sql;   $ret  =mysql_query($sql,$conn);   if  (mysql_num_rows($ret)>0)      echo  "Dang  nhap  thanh  cong";   else      echo  "Sai  ten  hoac  mat  khau";       ?>   1.8  SQL  Injection   27  
  • 28. •  Tấn  công   –  username  =  a’  or  ‘1’=‘1   –  password  =  b’  or  ‘1’=‘1   –  …   •  Phòng  chống   –  Loại  bỏ  tất  cả  các  dấu  ‘  và  các  ký  tự  đặc  biệt  nếu  cần.   –  Sử  dụng  escaped  string     •  Với  php/mysql:  mysql_real_escape_string,  hoặc  thêm  ‘’.   •  Với  SQL  server:  thêm  ký  tự    ‘  trước  ký  tự  đặc  biệt.   •  Với  Oracle  DB:  thêm  ký  tự  ‘’  trước  ký  tự  đặc  biệt.       1.8  SQL  Injection   28  
  • 29. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  2.  Kiểm  soát  truy  nhập   Access  Control  
  • 30. 2.1  Cơ  chế  kiểm  soát  truy  nhập  trên  Unix/Linux   2.2  Cơ  chế  kiểm  soát  truy  nhập  trên  Windows   2.3  Hạ  thấp  quyền  truy  nhập  của  tiến  trình   2.4  Xóa  }ile  an  toàn   2.5  Hạn  chế  quyền  truy  nhập  trên  }ile   2.6  Khóa  }ile   2.7  Tạo  }ile  tạm   2.8  Hạn  chế  truy  nhập  đến  hệ  thống  }ile     Nội  dung   30  
  • 31. •  Trên  Unix/Linux  tất  cả  các  tài  nguyên  đều  được  coi  là  }ile:  tệp  tin,  ổ  đĩa,   bộ  nhớ,  thiết  bị….   •  Mỗi  }ile  kiểm  soát  bởi  user  id  và  group  id.   •  Mỗi  tiến  trình  có  ba  quyền:  effective  user  id,  real  user  id,  saved  user  id.   Effective  user  id  được  sử  dụng  trong  phần  lớn  các  kiểm  tra.     •  Mỗi  tiến  trình  cũng  thuộc  về  ba  nhóm:  effective  group  id,  real  group  id,   saved  group  id.   •  Có  ba  loại  quyền   •  Đọc  (read)   •  Ghi  (write)   •  Thực  thi  (execute)   2.1  Cơ  chế  kiểm  soát  truy  nhập  trên  Unix/ Linux   31  
  • 32. •  Mỗi  }ile  sẽ  có  ba  nhóm  quyền  tương  ứng  với:  user  id,  group  id,  và   other.   -­‐rwxr-­‐xr-­‐x  1    Luong  Anh  Hoang    None    17964    Aug  28  23:45  test.exe   •  Khi  tiến  trình  tạo  một  }ile  hoặc  tài  nguyên,  hệ  thống  sẽ  gán  user  id  và   group  id  cho  }ile  mới  đó  bằng  effective  user  id  và  effective  group  id  của   tiến  trình.   •  Khi  tiến  trình  truy  nhập  một  }ile  hoặc  tài  nguyên,  hệ  thống  sẽ  lần  lượt   so  sánh  user  id,  group  id  của  tiến  trình  và  }ile  và  chọn  ra  tập  quyền   tương  ứng.  Nếu  không  khớp  thì  lớp  quyền  thứ  3  sẽ  được  sử  dụng.   2.1  Cơ  chế  kiểm  soát  truy  nhập  trên  Unix/ Linux   32  
  • 33. •  Mỗi  }ile  cũng  có  thể  có  3  bit  đặc  biệt   •  Sticky.  Nếu  bit  này  được  thiết  lập,  người  dùng  sẽ  không  thể  xóa  hay  đổi  tên   }ile  của  người  khác  nằm  trong  thưc  mục  mà  người  dùng  quản  lý.  Mặc  định   là  không  được  thiết  lập.   •  Setuid:  Bit  này  liên  quan  đến  quá  trình  tạo  một  tiến  trình  mới.  Nếu  bit  này   được  thiết  lập,  tiến  trình  được  tạo  từ  }ile  này  sẽ  không  kế  thừa  quyền  từ   tiến  trình  cha,  mà  sẽ  có  quyền  từ  user  id  của  chính  }ile  đó.   •  Setgid:     •  Đối  với  }ile  thực  thi,  nếu  bit  này  được  thiết  lập  thì  một  tiến  trình  mới   được  tạo  sẽ  có  quyền  từ  groupd  id  của  }ile  đó  chứ  không  kế  thừa  từ   tiến  trình  cha  (tương  tự  Setuid).   •  Đối  với  thưc  mục,  nếu  bit  này  được  thiết  lập  thì  các  }ile  tạo  trong  thư   mục  này  sẽ  có  groupd  id  của  thư  mục  cha,  chứ  không  kế  thừa  từ  tiến   trình  tạo  ra  }ile  đó.   2.1  Cơ  chế  kiểm  soát  truy  nhập  trên  Unix/ Linux   33  
  • 34. •  Windows  sử  dụng  ACL:  Access  Control  List  để  phân  quyền  tài   nguyên.   •  Các  tài  nguyên  của  Windows:  }ile,  registry,  mutex,  event,  IPC…   được  kiểm  soát  thông  qua  DACL  và  SACL.   •  DACL  là  danh  sách  các  ACE,  mỗi  ACE  là  một  luật  quy  định  một   quyền  hạn  cụ  thể.   •  DACL  rỗng  tương  đương  với  việc  tất  cả  mọi  người  có  toàn  quyền   truy  nhập  tới  đối  tượng.   •  Mỗi  ACE  bao  gồm  3  thông  tin:     •  SID:  Đại  diện  cho  một  user  hay  một  group  trong  hệ  thống   •  Quyền  truy  nhập   •  Giá  trị  boolean  tương  ứng  với  cho  phép  hay  không  cho  phép.   2.2  Cơ  chế  kiểm  soát  truy  nhập  trên   Windows   34  
  • 35. •  Các  quyền  truy  nhập     2.2  Cơ  chế  kiểm  soát  truy  nhập  trên   Windows   35   TÊN   Diễn  giải   DELETE   The  ability  to  delete  the  object   READ_CONTROL   The  ability  to  read  the  object's  security   descriptor,  not  including  its  SACL   SYNCHRONIZE   The  ability  for  a  thread  to  wait  for  the  object   to  be  put  into  the  signaled  state;  not  all   objects  support  this  functionality   WRITE_DAC   The  ability  to  modify  the  object's  DACL   WRITE_OWNER   The  ability  to  set  the  object's  owner   GENERIC_READ   The  ability  to  read  from  or  query  the  object   GENERIC_WRITE   The  ability  to  write  to  or  modify  the  object   GENERIC_EXECUTE   The  ability  to  execute  the  object  (applies   primarily  to  }iles)   GENERIC_ALL   Full  control  
  • 36. •  Ví  dụ  ACE   •  DENY            GENERIC_ALL                  Everyone:  Cấm  mọi  quyền  với  group  Everyone   •  ALLOW    GENERIC_WRITE      Marketing:  Cho  phép  nhóm  group  Marketing   được  quyền  ghi   •  Mỗi  đối  tượng  đều  có  một  Owner,  chính  là  người  tạo  ra  đối   tượng.   •  Owner  có  toàn  quyền  với  đối  tượng  bất  kể  trong  DACL  có  cấm   hay  không.   •  Owner  có  thể  bị  chiếm  bởi  user  khác.     2.2  Cơ  chế  kiểm  soát  truy  nhập  trên   Windows   36  
  • 37. •  Nếu  một  tiến  trình  có  đặc  quyền  cao,  thực  hiện  các  thao  tác  nguy  hiểm   =>  cần  hạ  thấp  quyền  trước  khi  thực  hiện.   •  Tiến  trình  có  thể  kiểm  tra  real  user  id,  real  group  id  bằng  lệnh  getuid  (),   getgid().  Đây  là  các  đặc  quyền  kế  thừa  từ  tiến  trình  cha.   •  Tiến  trình  có  thể  kiểm  tra  effective  user  id  và  effective  group  id  bằng   lệnh  geteuid()  và  getegid().  Đây  thường  là  user  id  có  đặc  quyền  cao   hơn  (do  được  khởi  chạy  từ  super  user,  hoặc  các  bit  setuid  được  bật).   •  Tiến  trình  từ  bỏ  đặc  quyền  bằng  việc  thiết  lập  group  mới  chính  là  real   user  id  qua  lệnh     •  setgroups():  Thiết  lập  lại  nhóm  của  tiến  trình.     •  setegid():  Thiết  lập  lại  effective  group  id  của  tiến  trình.   •  seteuid():  Thiết  lập  lại  effective  user  id  của  tiến  trình.     2.3  Hạ  thấp  quyền  truy  nhập  của  tiến  trình   37  
  • 38. •  Thông  thường,  một  }ile  sau  khi  xóa  sẽ  được  hệ  điều  hành  đánh  dấu  là   xóa,  nội  dung  chưa  hoàn  toàn  bị  loại  bỏ  trên  đĩa.   •  Giải  pháp   •  Ghi  đè  thông  tin  khác  nhiều  lần  lên  đĩa.   •  Ghi  đè  dữ  liệu  ngâu  nhiên  nhiều  lần  lên  đĩa.   •  Ghi  đè  sử  dụng  mẫu  định  sẵn  lên  đĩa.   •  Sau  mỗi  chu  kỳ  ghi,  sử  dụng  fsync  để  đồng  bộ  với  đĩa,  vô  hiệu  hóa  cơ  chế   cache.  Hoặc  lệnh  f}lush()  nếu  sử  dụng  thư  viện  C.   •  Một  vài  mẫu  được  sử  dụng   •  static  unsigned  char  single_pats[16]  =  {  0x00,  0x11,  0x22,  0x33,  0x44,   0x55,  0x66,  0x77,  0x88,  0x99,  0xaa,  0xbb,  0xcc,  0xdd,  0xee,  0xff  };     •  static  unsigned  char  triple_pats[6][3]  =  {  {  0x92,  0x49,  0x24  },  {  0x49,  0x24,   0x92  },  {  0x24,  0x92,  0x49  },  {  0x6d,  0xb6,  0xdb  },  {  0xb6,  0xdb,  0x6d  },   {  0xdb,  0x6d,  0xb6  }  };       2.4  Xóa  qile  an  toàn   38  
  • 39. •  Unix/Linux  sử  dụng  umask  cho  mỗi  tiến  trình  để  vô  hiệu  hóa  một  vài   bit  khi  tiến  trình  tạo  }ile.   •  Hàm  fopen,  open  luôn  luôn  tạo  }ile  với  quyền  666.   •  Giả  sử  tiến  trình  muốn  tạo  }ile  với  quyền  666:   requested_permissions  =  0666;     actual_permissions  =  requested_permissions  &  ~umask(  );   •  Ứng  dụng  thay  đổi  umask  bằng  hàm  umask()  trước  khi  thực  hiện  lời   gọi  tạo  }ile.   #include  <sys/types.h>   #include  <sys/stat.h>     mode_t    umask(mode_t    mask);           2.5  Hạn  chế  quyền  truy  nhập  trên  qile   39  
  • 40. •  Tiến  trình  muốn  kiểm  soát  truy  nhập  trên  một  phần  của  }ile  hay  toàn   bộ  }ile  để  tránh  xung  đột  khi  có  nhiều  tiến  trình  cùng  truy    nhập  trên   }ile.   •  Unix/Linux  cung  cấp  cơ  chế  khóa  mềm:  Mọi  tiến  trình  đều  có  quyền   giành  được  khóa  và  thao  tác  trên  }ile,  tuy  nhiên  không  phải  tiến  trình   nào  cũng  tuân  thủ  theo  khóa  và  có  thể  phá  hỏng  dữ  liệu  của  tiến  trình   khác.   •  Windows  thực  hiện  vấn  đề  này  tốt  hơn  bằng  khóa  cứng.  Có  hai  loại   khóa:   •  Shared  Lock:  Cho  phép  các  tiến  trình  khác  (kể  cả  tiến  trình  giành  được   khóa)  đọc  nhưng  không  được  ghi  vào  một  phần  đã  khóa  của  }ile.     •  Exclusive  Lock  :  Cấm  tất  cả  các  tiến  trình  khác  không  được  đọc  hay  ghi  vào   phần  đã  khóa  của  }ile.  Tiến  trình  giành  được  khóa  có  quyền  đọc  hoặc  ghi   vào  }ile.         2.6  Khóa  qile   40  
  • 41. •  Các  hàm  khóa  }ile  trên  Windows   •  LockFile,  UnlockFile:  Khóa  và  mở  khóa  đồng  bộ,  sẽ  không  trở  về  đến  khi   giành  được  khóa  hoặc  mở  được  khóa.   •  LockFileEx,  UnlockFileEx:  Khóa  và  mở  khóa  đồng  bộ  hoặc  bất  đồng  bộ.   •  Khóa  }ile  cũng  có  thể  xác  định  lúc  tạo  lập/truy  nhập  }ile  thông  qua  hàm   CreateFile.   •  Đoạn  chương  trình  sau  sẽ  mở  một  }ile  để  đọc  với  chế  độ  Shared  Lock.    char  buff[1024];    DWORD  bytesRead  =  0;    HANDLE  fileHandle  =  NULL;    fileHandle  =  CreateFile(L"C:SecureProgrammingTest.txt",          GENERIC_READ|GENERIC_WRITE,          FILE_SHARE_READ|FILE_SHARE_WRITE,          0,          OPEN_ALWAYS,          FILE_ATTRIBUTE_NORMAL,          0);       2.6  Khóa  qile   41  
  • 42. •  VD  (tiếp)    ReadFile(fileHandle,buff,128,&bytesRead,0);    buff[bytesRead]  =  0;    printf("File  content:%sn",buff);    LockFile(fileHandle,0,0,100,0);  //  Exclusive  Lock    printf("File  is  locked,  press  any  key  to  unlock...n");      getch();    UnlockFile(fileHandle,0,0,100,0);    printf("File  is  unlockedn");    getch();    CloseHandle(fileHandle);       2.6  Khóa  qile   42  
  • 43. •  Ứng  dụng  tạo  }ile  tạm  để  lưu  trữ  thông  tin  tạm  thời  của  chương  trình.   •  File  tạm  nên  được  tạo  lập  một  cách  an  toàn,  và  xóa  khi  kết  thúc  chương   trình.   •  Trên  unix/linux:   •  Hàm  mkstemp()  có  thể  sử  dụng  để  tạo  }ile  tạm  với  tên  ngẫu  nhiên.   •  Ứng  dụng  cần  xóa  }ile  theo  tên,  ngay  sau  lời  gọi  mkstemp  để  đảm  bảo  không  tiến   trình  nào  truy  nhập  được.   •  Sau  khi  tiến  trình  kết  thúc  một  cách  bình  thường/không  bình  thường,  }ile  tạm  sẽ   không  thể  truy  nhập  được  nữa.   •  VD    char    szPath[]  =  “fileXXXXXX";    int  fd;      fd  =  mkstemp(szPath);    unlink(szPath);    printf("Temperary  file  created,  press  any  key  to  continue...");    write(fd,"Hello",5);    close(fd);   2.7  Tạo  qile  tạm   43  
  • 44. •  Trên  Windows:   •  Không  có  hàm  tương  đương  mkstemp()   •  GetTempFileName()  sinh  tên  }ile  ngẫu  nhiên  nhưng  dễ  đoán.   •  GetTempPath()  lấy  đường  dẫn  đến  thư  mục  tạm  của  người  dùng  hiện  tại.   •  Tạo  }ile  bằng  hàm  CreateFile  với  hai  thuộc  tính  FILE_ATTRIBUTE_TEMPORARY  và   FILE_FLAG_DELETE_ON_CLOSE   •  VD   HANDLE  }ileHandle  =  NULL;   }ileHandle  =  CreateFile(L"C:SecureProgrammingTmp.txt",      GENERIC_READ|GENERIC_WRITE,      FILE_SHARE_READ|FILE_SHARE_WRITE,      0,      OPEN_ALWAYS,        FILE_ATTRIBUTE_TEMPORARY|    FILE_FLAG_DELETE_ON_CLOSE,          0);               2.7  Tạo  qile  tạm   44  
  • 45. •  Trên  Unix/Linux,  ứng  dụng  có  thể  tự  giới  hạn  phạm  vi  truy  nhập  hệ   thống  tệp  tin  của  mình  bằng  lệnh  chroot()   •  Sau  khi  gọi  chroot():   •  Tiến  trình  không  thể  mở  rộng  phạm  vi  truy  nhập  bằng  lệnh  chroot  lần  nữa..   •  Tiến  trình  chỉ  có  thể  thu  hẹp  hơn  nữa  phạm  vi  truy  nhập  của  mình.   •  Tiến  trình  phải  chủ  động  gọi  thêm  chdir()  để  lệnh  chroot  có  hiệu  lực.   •  VD:    #include  <unistd.h>    chroot("/new/root/directory");    chdir("/");                 2.8  Hạn  chế  truy  nhập  đến  hệ  thống  qile   45  
  • 46. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  3.  Kiểm  soát  xung  đột   Synchronization  Technique  
  • 47. 3.1  Khái  niệm   3.2  Đoạn  găng  (Critical  Section).   3.3  Đèn  hiệu  (Semaphore)     3.4  Mutex   3.5  Event   3.6  SRW  Lock   Nội  dung   47  
  • 48. §  Xung  đột  là  vấn  đề  phát  sinh  khi  nhiều  luồng  của  chương  trình  chạy   trên  bộ  vi  xử  lý  đa  nhân  cùng  truy  nhập  một  tài  nguyên  hệ  thống.   §  Ví  dụ   3.1  Khái  niệm   48   int  x  =  0;   DWORD  WINAPI  Thread(LPVOID    lpParam)   {    for  (int  i=0;i<2000000;i++)  x++;    return  0;   }   int  _tmain(int  argc,  _TCHAR*  argv[])   {      HANDLE  hThread1  =  CreateThread(NULL,NULL,Thread,NULL,NULL,NULL);    HANDLE  hThread2  =  CreateThread(NULL,NULL,Thread,NULL,NULL,NULL);    WaitForSingleObject(hThread1,INFINITE);    WaitForSingleObject(hThread2,INFINITE);    printf("X=%d",x);    getch();    return  0;   }  
  • 49. §  Đoạn  găng  (Critical  Section)  là  đoạn  chương  trình  được  bảo  vệ  bởi  hệ   điều  hành  sao  cho  tại  mọi  thời  điểm  chỉ  có  một  luồng  được  phép  thực   thi.   §  Sử  dụng   §  Khai  báo:    CRITICAL_SECTION  cs   §  Khởi  tạo:    InitializeCriticalSection(&cs)   §  Sử  dụng    EnterCriticalSection(&cs)    //  Bắt  đầu  đoạn  găng    …    //  Kết  thúc  đoạn  găng    LeaveCriticalSection(&cs)    //      DeleteCriticalSection(&cs)   §  Ví  dụ   §  Đặc  điểm:  chỉ  có  tác  dụng  trong  cùng  một  tiến  trình   3.2  Đoạn  găng   49  
  • 50. §  Đèn  hiệu  (Semaphore)  dùng  để  giới  hạn  số  lượng  luồng  tối  đa  được   phép  thực  thi  cùng  một  đoạn  chương  trình.   §  Sử  dụng   §  Khai  báo:    HANDLE  hSemaphore   §  Khởi  tạo:    hSemaphore  =  CreateSemaphore(NULL,5,5,NULL)   §  Sử  dụng    WaitForSingleObject(hSemaphore,  0L)    //    …    //    ReleaseSemaphore(hSemaphore,1,NULL)    //    CloseHandle(hSemaphore)   §  Ví  dụ   §  Đặc  điểm   §  Dùng  chung  được  giữa  các  tiến  trình   §  Tốc  độ  chậm  hơn  CRITICAL_SECTION   3.3  Đèn  hiệu   50  
  • 51. §  Mutex  dùng  để  bảo  vệ  tài  nguyên  của  chương  trình,  tại  một  thời  điểm   chỉ  cho  phép  một  luồng  của  một  tiến  trình  truy  nhập.   §  Sử  dụng   §  Khai  báo:    HANDLE  hMutex;   §  Khởi  tạo:    hMutex  =  CreateMutex(NULL,  FALSE,  NULL)   §  Sử  dụng    WaitForSingleObject(hMutex,  INFINITE)    //    …    //    ReleaseMutex(hMutex)   §  Ví  dụ   §  Đặc  điểm   §  Chậm  hơn  CRITICAL_SECTION   §  Có  thể  đồng  bộ  giữa  các  tiến  trình   3.4  Mutex   51  
  • 52. §  Event  dùng  đồng  bộ  hoạt  động  của  các  luồng  thông  qua  cơ  chế  báo   hiệu.   §  Sử  dụng   §  Khai  báo:    HANDLE  hEvent;   §  Khởi  tạo:    hMutex  =  CreateEvent(NULL,  TRUE,  FALSE,  “MyEvent”)   §  Sử  dụng    WaitForSingleObject(hEvent,  INFINITE)    //    …    SetEvent(hEvent)    //  Báo  hiệu  các  luồng  khác    ResetEvent(hEvent)  //  Chặn  các  luồng  khác    …    //    CloseHandle(hEvent)   §  Ví  dụ   3.5  Event   52  
  • 53. §  SRW  Lock  (Slim  Reader  Writer  Lock  )dùng  đồng  bộ  hoạt  động  của  các   luồng  thông  tương  tự  như  đoạn  găng   §  Sử  dụng   §  Khai  báo:    SRWLOCK    lock;   §  Khởi  tạo:    InitializeSRWLock(&lock);   §  Sử  dụng    AcquireSRWLockShared(&lock)    AcquireSRWLockExclusive(&lock)    //    …    //    ReleaseSRWLockShared(&lock)    ReleaseSRWLockExclusive(&lock)   §  Ví  dụ   3.5  SRW  Lock   53  
  • 54. 1.  Viết  chương  trình  chat  Client  và  Server  với  kênh  truyền  đã  mã   hóa    bằng  thuật  toán  AES-­‐256,  sử  dụng  thư  viện  OpenSSL  và   CryptoAPI.  Mật  khẩu  mã  hóa  là  :  123456.  Việc  mã  hóa  và  việc   nhận  dữ  liệu  được  thực  hiện  đồng  thời  trên  2  luồng  riêng  biệt,  sử   dụng  cơ  chế  đồng  bộ  CRITICAL_SECTION   2.  Viết  chương  trình  mã  hóa  và  giải  mã  tệp  tin  theo  thuật  toán   AES-­‐256,  với  tên  nhập  từ  bàn  phím,  mật  khẩu  mã  hóa  là  :nopass.   Sử  dụng  thư  viện  OpenSSL  và  CryptoAPI   Bài  tập   54  
  • 55. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  4.  Mã  hóa  đối  xứng   Symmetric  Crytography  
  • 56. 4.1  Biểu  diễn  khóa   4.2  Chuyển  đổi  chuỗi  hexa  và  khóa  nhị  phân.   4.3  Mã  hóa  và  giải  mã  Base64     4.4  Các  phương  pháp  mã  hóa  đối  xứng   4.5  Mã  hóa  đối  xứng  với  OpenSSL   4.6  Mã  hóa  đối  xứng  với  Microsoft  Crypto  API   Nội  dung   56  
  • 57. •  Khóa  đối  xứng:    Một  số  rất  lớn  sử  dụng  để  mã  hóa  và  giải  mã  thông   điệp.   •  Biểu  diễn  khóa:   •  Phân  tách  thành  các  byte  và  lưu  dưới  dạng  một  mảng.   unsigned  char    key[KEYLEN_BYTES]   •  Biểu  diễn  dưới  dạng  số  nguyên  lớn  nếu  khóa  có  chiều  dài  64-­‐bit   long            long              key   •  Biểu  diễn  dưới  dạng  chuỗi  chữ  số  hexa    char  key[]=“AF12B5C7E0…”   •  Biểu  diễn  dưới  dạng  xâu  ASCII  (mật  khẩu).    char  key[]=“secret!!!”   •  Lưu  ý  về  tính  “endian”  của  máy  thực  hiện  mã  hóa.   4.1  Biểu  diễn  khóa   57  
  • 58. •  Chuyển  đổi  khóa  nhị  phân  sang  dạng  chuỗi  chữ  số  hexa    #define  MAX_KEY_LEN  32    unsigned  char  key[MAX_KEY_LEN];    char    result[MAX_KEY_LEN*2+1];    for  (int  i=0;i<MAX_KEY_LEN;i++)      sprintf(result+i*2,"%2X",key[i]);    printf("Key:%s",result);     4.2  Chuyển  đổi  chuỗi  hexa  và  khóa  nhị   phân     58  
  • 59. •  Chuyển  đổi  chuỗi  hexa  sang  khóa   nhị  phân     char  Hex2Dec(char  c)   {            if  (('a'<=c)&&(c<='z'))  return  c  -­‐  'a'+10;            if  (('A'<=c)&&(c<='Z'))  return  c  -­‐  'A'+10;            if  (('0'<=c)&&(c<='9'))  return  c  -­‐  '0';            return  -­‐1;   }   …   #define  MAX_KEY_LENGTH  32     char  hexa[]="AF125C4D8E";   unsigned  char  key[MAX_KEY_LENGTH];   int  keylen  =  strlen(hexa);   char  c1,c2;   if  ((keylen%2!=0)||(keylen/2  >         MAX_KEY_LENGTH))   printf("Invalid  key  length");   keylen  =  keylen/2;   for  (int  i=0;i<keylen;i++)   {    c1  =  Hex2Dec(hexa[i*2]);    c2  =  Hex2Dec(hexa[i*2+1]);    if  ((c1==-­‐1)||(c2==-­‐1))    {                      printf("Invalid  character  !!!");                      break;    };    key[i]  =  (c1<<4)|c2;   };     4.2  Chuyển  đổi  chuỗi  hexa  và  khóa  nhị   phân     59  
  • 60. •  Mã  hóa  Base64       •  Sử  dụng  6-­‐bit  để  mã  hóa  dữ  liệu  và  biểu  diễn  dưới  dạng  các  chữ  cái  ASCII.   •  Cứ  3  byte  dữ  liệu  vào  sẽ  được  biểu  diễn  thành  4  byte  dữ  liệu  ra.   •  Các  ký  tự  ra  nằm  trong  khoảng:     •  ‘A’  –  ‘Z’  tương  đương  các  giá  trị  của  từ  mã  từ  0-­‐25.   •  ‘a’  –  ‘z’  tương  đương  các  giá  trị  của  từ  mã  từ  26-­‐51.   •  ‘0’-­‐  ‘9’  tương  đương  các  giá  trị  từ  mã  từ  52-­‐61.   •  ‘+’  ,  ‘-­‐’  tương  ứng  với  các  giá  trị  mã  62,63.   •  Nếu  dữ  liệu  vào  có  kích  thước  không  chia  hết  cho  3  sẽ  thì  được  thêm  vào  bằng  ký  tự   ‘=‘.   •  VD    Dữ  liệu  gốc:  ‘A’  –  0100.0001    Dữ  liệu  mã  hóa  dạng  Base64:  010000.010000.000000.000000  ~  QQ==    Dữ  liệu  gốc:  ‘AA’  –  0100.0001.0100.0001    Dữ  liệu  mã  hóa  dạng  Base64:  010000.010100.000100.000000  ~  QUE=    Dữ  liệu  gốc:  ‘AAA’  –  0100.0001.0100.0001.0100.0001    Dữ  liệu  dạng  mã  hóa  Base64:  010000.010100.000101.000001  ~  QUFB                         4.3  Mã  hóa  và  giải  mã  Base64   60  
  • 61. •  Mã  hóa  Base64                           4.3  Mã  hóa  và  giải  mã  Base64   61   Value   Char       Value   Char       Value   Char       Value   Char   0   A   16   Q   32   g   48   w   1   B   17   R   33   h   49   x   2   C   18   S   34   i   50   y   3   D   19   T   35   j   51   z   4   E   20   U   36   k   52   0   5   F   21   V   37   l   53   1   6   G   22   W   38   m   54   2   7   H   23   X   39   n   55   3   8   I   24   Y   40   o   56   4   9   J   25   Z   41   p   57   5   10   K   26   a   42   q   58   6   11   L   27   b   43   r   59   7   12   M   28   c   44   s   60   8   13   N   29   d   45   t   61   9   14   O   30   e   46   u   62   +   15   P   31   f   47   v   63   /  
  • 62. •  Đoạn  chương  trình  mã  hóa  Base64:    P4.5  –  Secure  C  Programming   Cookbook   •  Đoạn  chương  trình  giải  mã  Base64:  P4.6  –  Secure  C  Programming   Cookbook   4.3  Mã  hóa  và  giải  mã  Base64   62  
  • 63. •  Mã  hóa  đối  xứng:  Sử  dụng  chung  một  khóa  cho  mã  hóa  và  giải  mã   •  Có  hai  loại:  Mã  khối  và  mã  dòng   •  Có  nhiều  chế  độ  mã  hóa:  ECB,  CBC,  CFB,  OFB,  CTR,  CWC…     •  Có  nhiều  giải  thuật:     4.4  Các  phương  pháp  mã  hóa  đối  xứng   63   Cipher   Key  size   Speed[4]   Implementation   Notes   AES   128  bits[5]   14.1  cpb  in  asm,  22.6  cpb  in   C   Brian  Gladman's[6]   The  assembly  version  currently  works  only   on  Windows.   AES   128  bits   41.3  cpb   OpenSSL   Triple  DES   192  bits[7]   108.2  cpb   OpenSSL   SNOW  2.0   128  or  256  bits   6.4  cpb   Fast  reference   implementation[8]   This  implementation  is  written  in  C.   RC4   Up  to  256  bits   (usually  128  bits)   10.7  cpb   OpenSSL   Serpent   128,  192,  or  256  bits   35.6  cpb   Fast  reference   implementation   It  gets  a  lot  faster  on  64-­‐bit  platforms  and   is  at  least  as  fast  as  AES  in  hardware.   Blowfish   Up  to  256  bits   (usually  128  bits)   23.2  cpb   OpenSSL  
  • 64. •  Thư  viện  OpenSSL:  Thư  viện  mã  nguồn  mở,  mạnh  mẽ  và  dễ  sử  dụng.   •  OpenSSL  hỗ  trợ:   •  Nhiều  thuật  toán  mã  hóa:  AES,  DES  ,  3DES,  Blow}ish,  CAST,  Idea,  RC2,  RC5.   •  Nhiều  chế  độ  mã  hóa:  ECB,  CBC,  CFB,  OFB,  CTR…   •  Mã  hóa  dòng:  RC4.   •  Các  giải  thuật  băm:  MD2,  MD4,  MD5,SHA-­‐1,SHA-­‐224,SHA-­‐256…   •  MAC:  HMAC.  MDC2   •  Các  giải  thuật  mã  hóa  công  khai:  DH,  DSA,  RSA,  ECC   •  Sử  dụng  thư  viện:   •  Trên  Unix/Linux:  Tải  source  về  và  biên  dịch.  Kết  quả  là  }ile    libcrypto.[so/ a],  libssl.[so/a]  và  các  }ile  .h  để  include  vào  chương  trình.   •  Trên  Windows:  Tải  bản  binary  đã  biên  dịch  sẵn:  libeay32.dll,  ssleay32.dll,   tệp  tiêu  đề  (.h)  và  tệp  thư  viện  (.lib).  Link  http://www.ie7pro.com/ openssl.html     4.5  Mã  hóa  đối  xứng  với  OpenSSL   64  
  • 65. •  Giao  diện  OpenSSL  EVP   •  Là  API  mức  cao  của  OpenSSL,  cho  phép  truy  nhập  đến  các  thuật  toán  ở  mức   thấp  một  cách  tập  trung,  dễ  dàng.   •  Tệp  tiêu  đề  <openssl/evp.h>.   •  Tệp  thư  viện:  libeay32.lib,  ssleay32.lib   •  Mã  hóa  AES  với  OpenSSL  EVP.   •  Khởi  tạo  khóa,  vector  khởi  tạo,  salt  với  EVP_BytesToKey  hoặc  tự  chọn  một   bộ  Key,  IV  nào  đó.   •  Khởi  tạo  ngữ  cảnh  mã  hóa  với  hàm  EVP_EncryptInit_ex.   •  Khởi  tạo  ngữ  cảnh  giải  mã  với  hàm  EVP_DecryptInit_ex.   •  Mã  hóa  dữ  liệu  bằng  việc  liên  tục  gọi  hàm  EVP_EncryptUpdate,  kết  thúc   quá  trình  mã  hóa  bằng  hàm  EVP_EncryptFinal_ex.   •  Giải  mã  dữ  liệu  bằng  việc  liên  tục  gọi  hàm  EVP_DecryptUpdate,  kết  thúc   quá  trình  giải  mã  bằng  hàm  EVP_DecryptFinal_ex.   4.5  Mã  hóa  đối  xứng  với  OpenSSL   65  
  • 66. •  VD   •  Sinh  key  và  iv  bằng  hàm  EVP_BytesToKey   char          key[32];   char          iv[32];       char  *  key_data  =  “nopass”;     unsigned  int  salt[]  =  {12345,  54321};   EVP_BytesToKey(EVP_aes_256_cbc(),  EVP_sha1(),  salt,  key_data,  6,  1,  key,   iv);   •  Khởi  tạo  ngữ  cảnh  mã  hóa  với  key  và  iv  đã  chọn   EVP_CIPHER_CTX  e_ctx;   EVP_CIPHER_CTX_init(&e_ctx);   EVP_EncryptInit_ex(&e_ctx,  EVP_aes_256_cbc(),NULL,  key,  iv);   •  Khởi  tạo  ngữ  cảnh  giải  mã  với  key  và  iv  đã  chọn   EVP_CIPHER_CTX  d_ctx;   EVP_CIPHER_CTX_init(&d_ctx);   EVP_DecryptInit_ex(&d_ctx,  EVP_aes_256_cbc(),NULL,  key,  iv);   4.5  Mã  hóa  đối  xứng  với  OpenSSL   66  
  • 67. •  VD  (tiếp)   •  Mã  hóa  với  ngữ  cảnh  đã  được  khởi  tạo   char  *    plaintext=“Hello”;   int  len  =  strlen(plaintext);   char  ciphertext[1024];   int    c_len  =  0,  f_len  =  0;   /*  Gọi  lại  hàm  này  để  cho  phép  OpenSSL  sử  dụng  lại  ngữ  cảnh  phiên  mã     hóa  trước  */   EVP_EncryptInit_ex(e,  NULL,  NULL,  NULL,  NULL);   …   //  Mỗi  chu  kỳ  Update,  c_len  sẽ  chứa  số  byte  của  xâu  mã  được   EVP_EncryptUpdate(e,  ciphertext,  &c_len,  plaintext,  len);   …   //  Cuối  chu  kỳ  Update,  f_len  sẽ  chưa  số  byte  còn  lại  của  xâu  mã   EVP_EncryptFinal_ex(e,  ciphertext+c_len,  &f_len);   …   4.5  Mã  hóa  đối  xứng  với  OpenSSL   67  
  • 68. •  VD  (tiếp)   •  Giải  mã  với  ngữ  cảnh  đã  được  khởi  tạo     char  plaintext[1024];   int  p_len  =  0;   /*  Gọi  lại  hàm  này  để  cho  phép  OpenSSL  sử  dụng  lại  ngữ  cảnh  phiên  giãi   mã    hóa  trước  */   EVP_DecryptInit_ex(e,  NULL,  NULL,  NULL,  NULL);   …   //  Giải  mã  với  ciphertext  và  len  được  cung  cấp  trước   EVP_DecryptUpdate(e,  plaintext,  &p_len,  ciphertext,  *len);   …   //  Kết  thúc  quá  trình  giải  mã,  cập  nhật  dữ  liệu  còn  lại  vào  plaintext.   EVP_DecryptFinal_ex(e,  plaintext+p_len,  &f_len);   4.5  Mã  hóa  đối  xứng  với  OpenSSL   68  
  • 69. •  Thư  viện  CryptoAPI   •  Cung  cấp  các  hàm  mật  mã  học  cơ  bản  thông  qua  các  Cryptographic  Service   Providers  (CSP).     •  Microsoft  Base  Cryptographic  Service  Provider:  RC2,  RC4,  DES   •  Microsoft  Enhanced  Cryptographic  Service  Provider:  Triple-­‐DES   •  Microsoft  AES  Cryptographic  Service  Provider:  AES   •  …   •  Cung  cấp  các  hàm  mã  hóa  và  giải  mã  chứng  thư  số,  và  đồng  thời  bổ  sung   các  hàm  băm.   •  Cung  cấp  các  hàm  quản  lý  và  lưu  trữ  chứng  thư  số.   •  Các  hàm  mã  thông  điệp  hóa  mức  cao  (Simpli}ied  Message  Functions).   •  Các  hàm  mã  hóa  thông  điệp  mức  thấp  (Low-­‐Level  Message  Functions).     4.6  Microsoft  Crypto  API   69  
  • 70. •  Thư  viện  CryptoAPI     4.6  Microsoft  Crypto  API   70  
  • 71. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Tệp  tiêu  đề  wincript.h   •  Thư  viện  Crypt32.lib   •  Trình  tự  sử  dụng           4.6  Microsoft  Crypto  API   71   Khởi  tạo   Provider   Tạo  khóa   • Ngẫu  nhiên   • Từ  mật  khẩu   • Từ  bên  ngoài   Đặt  chế  độ  mã   • CBC   • ECB   • …   Thiết  lập  vector   khởi  tạo   Thực  hiện  Mã   hóa/Giải  mã  
  • 72. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Khởi  tạo  ngữ  cảnh  Provider  thông  qua  hàm  CryptAcquireContext    BOOL  WINAPI  CryptAcquireContext(__out  HCRYPTPROV*  phProv,            __in  LPCTSTR  pszContainer,            __in  LPCTSTR  pszProvider,            __in  DWORD  dwProvType,            __in  DWORD  dwFlags  );   VD:   HCRYPTPROV    hProvider;   if  (!CryptAcquireContext(&hProvider,            0,            MS_ENH_RSA_AES_PROV,            PROV_RSA_AES,                                                        CRYPT_VERIFYCONTEXT))        return  0;       4.6  Microsoft  Crypto  API   72  
  • 73. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Sử  dụng  Key  thông  qua  một  trong  ba  hàm.  Kết  quả  trả  về  là  đối  tượng   HCRYPTKEY   •  CryptGenKey(  ):  Sinh  khóa  ngẫu  nhiên.   •  CryptDeriveKey(  ):  Sinh  khóa  từ  mật  khẩu.   •  CryptImportKey(  )  :  Sinh  khóa  từ  một  đối  tượng  trong  bộ  nhớ.     VD1.  Sinh  khóa  ngẫu  nhiên     DWORD  dwFlags;     HCRYPTKEY  hKey;     DWORD  dwSize  =  256;     dwFlags  =  ((dwSize  <<  16)  &  0xFFFF0000)  |  CRYPT_EXPORTABLE;     if  (!CryptGenKey(hProvider,  CALG_AES_256,  dwFlags,  &hKey))  return  0;         4.6  Microsoft  Crypto  API   73  
  • 74. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   VD2.  Sinh  khóa  từ  mật  khẩu:  Cần  phải  băm  mật  khẩu  và  truyền  vào  hàm  CryptDeriveKey   char    *  password  =  “nopass”;       BOOL  bResult;     DWORD  cbData;     HCRYPTKEY  hKey;      //  Lưu  Key   HCRYPTHASH  hHash;    //  Lưu  giá  trị  băm  của  mật  khẩu   if  (!CryptCreateHash(hProvider,  CALG_SHA1,  0,  0,  &hHash))  //  Khởi  tạo  hàm  băm    return  0;     cbData  =  lstrlen(password)  *  sizeof(TCHAR);     if  (!CryptHashData(hHash,  (BYTE  *)password,  cbData,  0))    //  Băm  mật  khẩu    {        CryptDestroyHash(hHash);        return  0;      }   //  Tạo  key  từ  giá  trị  băm  của  mật  khẩu   bResult  =  CryptDeriveKey(hProvider,  CALG_AES_256,  hHash,  CRYPT_EXPORTABLE,   &hKey);     CryptDestroyHash(hHash);     4.6  Microsoft  Crypto  API   74  
  • 75. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Thiết  lập  chế  độ  mã  hóa  CBC  với  hàm  CryptSetKeyParam    DWORD  dwMode  =  CRYPT_MODE_CBC;    CryptSetKeyParam(hKey,  KP_MODE,  (BYTE  *)&dwMode,  0);   •  Sinh  ngẫu  nhiên  vector  khởi  tạo  (IV)   BOOL  bResult;        //  Lưu  kết  quả   BYTE  *pbTemp;      //  Lưu  vector  khởi  tạo   DWORD  dwBlockLen,  dwDataLen;     dwDataLen  =  sizeof(dwBlockLen);   //  Lấy  kích  thước  block  của  thuật  toán  mã  hóa    if  (!CryptGetKeyParam(hKey,  KP_BLOCKLEN,  (BYTE  *)&dwBlockLen,  &dwDataLen,   0))  return  0;   dwBlockLen  /=  8;     if  (!(pbTemp  =  (BYTE  *)LocalAlloc(LMEM_FIXED,  dwBlockLen)))    return  FALSE;   //  Sinh  ngẫu  nhiên  IV     bResult  =  CryptGenRandom(hProvider,  dwBlockLen,  pbTemp);   //  Thiết  lập  IV   bResult  =  CryptSetKeyParam(hKey,  KP_IV,  pbTemp,  0);     LocalFree(pbTemp);     4.6  Microsoft  Crypto  API   75  
  • 76. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt   •  Với  các  giải  thuật  mã  hóa  dòng  thì  kích  thước  dữ  liệu  ra  =  kích  thước  dữ  liệu  vào.   •  Với  các  giải  thuật  mã  hóa  khối  thì  kích  thước  dữ  liệu  ra  <=    kích  thước  dữ  liệu  vào   +  kích  thước  khối.   •  Hàm  CryptEncrypt  sẽ  ghi  đè  dữ  liệu  mã  hóa  được  vào  bộ  đệm  chứa  dữ  liệu  vào.   •  Đoạn  chương  trình  thực  hiện  mã  hóa  chung  cho  cả  hai  loại.   4.6  Microsoft  Crypto  API   76   ALG_ID  Algid;      //  Giải  thuật  mã   char  *  pbData  =  "Hello  CryptAPI";    //  Xâu  nguồn  cần  mã   char  *  pbResult  =  0;    //  Xâu  kết  quả   DWORD  dwDataLen  =  0,dwBlockLen  =  0;    cbData  =  strlen(pbData);  //  Chiều  dài  xâu  nguồn      dwDataLen  =  sizeof(ALG_ID);   //  Lấy  thông  tin  về  giải  thuật  mã  hóa  với  key  cho  trước      if  (!CryptGetKeyParam(hKey,  KP_ALGID,  (BYTE  *)&Algid,  &dwDataLen,  0))      return  0;    
  • 77. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt     4.6  Microsoft  Crypto  API   77   if  (GET_ALG_TYPE(Algid)  !=  ALG_TYPE_STREAM)    //  Mã  hóa  khối      {            dwDataLen  =  sizeof(DWORD);                ret  =  CryptGetKeyParam(hKey,    KP_BLOCKLEN,  (BYTE*)&dwBlockLen,          &dwDataLen,  0);  //  Lấy  kích  thước  block  theo  bit    dwBlockLen  =  dwBlockLen/8;  //  Đổi  kích  thước  block  ra  đơn  vị  byte      //  Cấp  phát  bộ  nhớ  để  chứa  kết  quả        pbResult  =  (char*)malloc(cbData+dwBlockLen);    memcpy(pbResult,pbData,cbData);    //  Thực  hiện  mã  hóa,  kết  quả  là  dwDataLen  byte  lưu  trong  pbResult    dwDataLen  =  cbData;      CryptEncrypt(hKey,  0,  TRUE,  0,  (BYTE*)pbResult,  &dwDataLen,          cbData+16))  ;   }  
  • 78. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt  (tiếp)     4.6  Microsoft  Crypto  API   78   else  //  Mã  hóa  dòng   {    //  Cấp  phát  bộ  nhớ  lưu  kết  quả    pbResult  =  (char*)malloc(cbData);    //  Bảo  toàn  dữ  liệu  nguồn    memcpy(pbResult,pbData,cbData);    //  Thực  hiện  mã  hóa    CryptEncrypt(hKey,0,TRUE,0,pbResult,&dwDataLen,cbData);     }  
  • 79. •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp   với  thuật  toán  AES.   •  Giải  mã  với  CryptDecrypt   •  Kích  thước  dữ  liệu  đích  <=  kích  thước  dữ  liệu  nguồn   •  Thực  hiện  đơn  giản  hơn  so  với  CryptEncrypt   •  Ví  dụ     4.6  Microsoft  Crypto  API   79   char  *  pbData  ;      //  Dữ  liệu  nguồn   DWORD  cbData;    //  Kích  thước  nguồn   char  *  pbResult;      //  Dữ  liệu  đích   DWORD  dwDataLen;  //  Kích  thước  đích   …   //  Cấp  phát  bộ  nhớ  và  sao  chép  dữ  liệu  nguồn  vào  đích   pbResult  =  (char*)malloc(cbData);   memcpy(pbResult,  pbData,  cbData);   dwDataLen  =  cbDataLen;   //  Giải  mã,  kết  quả  là  dwDataLen  byte  lưu  trong  pbResult   CryptDecrypt(hKey,0,TRUE,0,pbResult,&dwDataLen);  
  • 80. •  Trao  đổi  khóa  với  OpenSSL   •  CryptoAPI  không  cho  phép  nhập  và  xuất  khóa  dạng  thô  như  OpenSSL.   •  Để  trao  đổi  khóa  với  thư  viện  khác,  cần  mã  hóa  khóa  theo  giải  thuật   AT_KEYEXCHANGE,  và  thực  hiện  nhập  xuất  dưới  dạng  cấu  trúc  BLOB.   •  Hàm  CryptImportKeyvà  CryptExportKey  dùng  để  thực  hiện  nhập  xuất   khóa.   •  Xem  thêm  phần  5.26,  5.27  trong  Secure  Programming  Cookbook.     4.6  Microsoft  Crypto  API   80  
  • 81. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  5.  Hàm  băm  và  xác  thực   thông  điệp   Hashes  and  Message  Authentication  
  • 82. 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   Nội  dung   82  
  • 83. •  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   5.1  Các  hàm  băm  và  MAC  thông  dụng   83  
  • 84. •  Hàm  băm  (hashes)   5.1  Các  hàm  băm  và  MAC  thông  dụng   84   Algorithm   Digest  size   Security  conqidence   Small  message   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   as  cipher  block  size)   Good   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  
  • 85. •  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   5.1  Các  hàm  băm  và  MAC  thông  dụng   85  
  • 86. •  Xác  thực  thông  điệp  (Message  Authentication  Code)   5.1  Các  hàm  băm  và  MAC  thông  dụng   86   MAC   Built  upon   Small  message   speed  (64   bytes)[4]   Large  message   speed  (8K)   Appropriate   for  hardware   Patent  restric-­‐ tions   Parallel-­‐izable   CMAC   A  universal  hash   and  AES   ~18  cpb   ~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   162  cpb   29  cpb   Yes   Yes   Yes  
  • 87. •  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:  <openssl/evp.h>   •  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.   5.2  Băm  dữ  liệu  với  OpenSSL   87  
  • 88. •  VD:  Băm  với  SHA1   5.2  Băm  dữ  liệu  với  OpenSSL   88    #include  <openssl/sha.h>    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");  
  • 89. •  VD:  Băm  với  giao  diện  EVP   5.2  Băm  dữ  liệu  với  OpenSSL   89   #include  <openssl/evp.h>   #include  <stdio.h>   #include  <string.h>      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);  
  • 90. •  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   5.3  Băm  dữ  liệu  với  CryptoAPI   90  
  • 91. •  Ví  dụ:  Băm  dữ  liệu  với  thuật  toán  SHA-­‐256   5.3  Băm  dữ  liệu  với  CryptoAPI   91      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…        
  • 92. •  Ví  dụ:  Băm  dữ  liệu  với  thuật  toán  SHA-­‐256  (tiếp)   5.3  Băm  dữ  liệu  với  CryptoAPI   92      //  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);            
  • 93. •  Với  OpenSSL   –  Tệp  tiêu  đều  <openssl/hmac.h>   –  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ả   5.4  Xác  thực  thông  điệp  với  HMAC   93  
  • 94. •  Với  OpenSSL   5.4  Xác  thực  thông  điệp  với  HMAC   94      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");  
  • 95. •  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     5.4  Xác  thực  thông  điệp  với  HMAC   95  
  • 96. •  Với  CryptAPI     5.4  Xác  thực  thông  điệp  với  HMAC   96      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);        
  • 97. •  Với  CryptAPI     5.4  Xác  thực  thông  điệp  với  HMAC   97   //  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);        
  • 98. •  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.     5.5  Sử  dụng  Salt   98  
  • 99. 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:    <Kích  thước><Nội  dung  tệp  tin  đã  mã><Giá  trị  băm  SHA-­‐256>     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     Bài  tập   99  
  • 100. 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.     Bài  tập   100  
  • 101. Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  6.  Mã  hóa  công  khai   Public  Key  Cryptography  
  • 102. 6.1  Mã  hóa  với  OpenSSL  RSA   6.2  Chữ  ký  số   6.3  Biểu  diễn  khóa   6.4  Kết  nối  SSL   6.5  Hạ  tầng  khóa  công  khai     Nội  dung   102  
  • 103. •  Mã  hóa  bất  đối  xứng   •  Là  các  giải  thuật  sử  dụng  một  cặp  khóa  cho  việc  mã  hóa  và  giải  mã   •  Dữ  liệu  được  mã  hóa  bằng  khóa  công  khai  sẽ  được  giải  mã  bằng   khóa  bí  mật  và  ngược  lại.   •  Các  giải  thuật  thông  dụng:  RSA,  DSA,  Dif}ie-­‐Hellman.   •  Không  sử  dụng  trực  tiếp  để  mã  hóa  dữ  liệu  vì  tốc  độ  rất  chậm.   •  Thường  được  sử  dụng  để   •  Trao  đổi  khóa  đối  xứng  trong  phiên  truyền  mật   •  Chữ  ký  số   •  Xác  nhận  danh  tính   •  …   6.1  Mã  hóa  với  OpenSSL  RSA     103  
  • 104. •  OpenSSL  RSA   •  Thường  được  sử  dụng  trao  đổi  khóa   •  Lưu  trữ  tất  cả  thông  tin  về  một  khóa  dưới  cấu  trúc  RSA.   •  Tệp  tiêu  đề  rsa.h   •  Sinh  cặp  khóa  đối  xứng  bằng  hàm       RSA  *RSA_generate_key(int  bits,      //  Kích  thước  khóa:  1024,2048…        unsigned  long  exp,//  Số  mũ:  3,  17,  65537          void  (*cb)(int,  int,  void),    //  Callback        void  *cb_arg);       6.1  Mã  hóa  với  OpenSSL  RSA     104  
  • 105. •  Mã  hóa  với  khóa  công  khai   •  Sử  dụng  hàm  RSA_public_encrypt:    int  RSA_public_encrypt(int  l,  //  Chiều  dài  dữ  liệu          unsigned  char  *pt,  //  Xâu/số  cần  mã        unsigned  char  *ct,  //  Kết  quả        RSA  *r,            //  Cấu  trúc  RSA          int  p);          //  Kiểu  padding    Kết  quả  trả  về:  chiều  dài  xâu  mã  được.     6.1  Mã  hóa  với  OpenSSL  RSA     105  
  • 106. •  Giải  mã  với  khóa  bí  mật   •  Sử  dụng  hàm  RSA_private_decrypt:    int  RSA_private_decrypt(int  l,            unsigned  char  *ct,          unsigned  char  *pt,          RSA  *r,          int  p);    Kết  quả  trả  về:  chiều  dài  xâu  giải  mã  được   6.1  Mã  hóa  với  OpenSSL  RSA     106  
  • 107. •  Bài  tập   –  Viết  chương  trình  chat  console  client-­‐server  sử  dụng  giải  thuật   RSA.  Chỉ  chia  sẻ  public  key  trên  đường  truyền.   6.1  Mã  hóa  với  OpenSSL  RSA     107  
  • 108. •  Chữ  ký  số  dữ  liệu  nhằm  xác  thực  danh  tính  của  người  gửi,  tương  tự   như  HMAC  nhưng  sử  dụng  giải  thuật  RSA   •  Quá  trình  ký  số  dữ  liệu  nhận  đầu  vào  là  giá  trị  băm  của  thông  điệp,   khóa  bí  mật  của  người  gửi,  đầu  ra  là  giá  trị  hàm  băm  đã  được  mã  hóa.   •  Bên  nhận  thực  hiện  quá  trình  ngược  lại:  tính  giá  trị  băm  của  thông   điệp,  giải  mã  giá  trị  băm  đã  mã  hóa  của  bên  gửi  bằng  khóa  công  khai  và   so  sánh  hai  giá  trị  băm  này.   •  Hacker  không  thể  giả  mạo  giá  trị  băm  vì  không  có  khóa  bí  mật  của  bên   gửi.   6.2  Chữ  ký  số     108  
  • 109. •  Sơ  đồ  ký   6.2  Chữ  ký  số     109   Dữ  liệu   Giá  trị  băm   (MD)   Hash   (SHA1)   Chữ  ký   Khóa  bí  mật   Mã  hóa   Dữ  liệu  +  Chữ   ký