Bài giảng Lập trình an toàn - Chương 4: Mã hóa đối xứng - Lương Ánh Hoàng

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

 

pdf 26 trang yennguyen 1380
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình an toàn - Chương 4: Mã hóa đối xứng - Lương Ánh Hoàng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Lập trình an toàn - Chương 4: Mã hóa đối xứng - Lương Ánh Hoàng

Bài giảng Lập trình an toàn - Chương 4: Mã hóa đối xứng - Lương Ánh Hoàng
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	
  
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	
  đề	
  .	
  
•  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	
  

File đính kèm:

  • pdfbai_giang_lap_trinhantoan_chuong_4_ma_hoa_doi_xung_luong_anh.pdf