Chương trỡnh kex (key exchange) – Version 1

Một phần của tài liệu đề tài phần mềm bảo mật mạng dùng giao thức ip quyển 4a các phần mềm bảo mật gói ip trên hệ điều hành linux (Trang 163 - 167)

D. GIảI PHáP MậT Mã

5. Chương trỡnh kex (key exchange) – Version 1

`kex` là chương trỡnh trao đổi khoỏ cú xỏc thực giữa hai bờn tham gia liờn lạc. Cỏc bước trao đổi khoỏ tuõn theo lược đồ Diffie-Hellman và sử dụng chữ ký số RSA.

`kex` thực hiện trao đổi khoỏ tự động giữa hai mỏy tớnh kết nối với nhau cú sử dụng giao thức TCP/IP. Khi bắt đầu một quỏ trỡnh trao đổi, hai chương trỡnh

`kex` sẽ được chạy trờn hai mỏy, chỳng kết nối với nhau thụng qua giao thức TCP. `kex` ở mỗi bờn sẽ gửi định danh và chữ ký số của mỡnh cho phớa bờn kia. Mỗi bờn sẽ kiểm tra chữ ký số nhận được bằng việc sử dụng khoỏ cụng khai RSA đó được phõn phối trước của phớa bờn kia.

Để thực hiện một quỏ trỡnh trao đổi khoỏ cụng khai RSA, trờn mỗi mỏy phải

cú một cặp khoỏ (cụngkhai/bớmật). Khoỏ bớ mật được lưu trong file

/etc/keyEx/keyEx.priv. Thư mục /etc/keyEx/pk chứa khoỏ cụng khai của phớa bờn kia. Trờn mỗi mỏy phải cú một định danh (chỳng tụi thường sử dụng tờn mỏy) và

nú phải được cho phớa bờn kia biết trước. Khoỏ cụng khai của phớa bờn kia được

lưu trong thư mục /etc/keyEx/pk với tờn file là tờn định danh (tờn mỏy) của phớa bờn kia. File keyEx.priv gồm hai tham số là myModulo và PrivateExponent, file khoỏ cụng khai cũng gồm hai tham số là peerModulo và peerPublicExponent.

Khi kết thỳc quỏ trỡnh trao đổi khoỏ, hai bờn sẽ cú một khoỏ ngẫu nhiờn chung (với độ dài mặc định là 64 byte) để sử dụng cho cỏc thuật toỏn mó hoỏ. Độ dài khoỏ tạo ra cú thể thay đổi sao cho phự hợp với cỏc thuật toỏn mó hoỏ. Ở đõy chỳng tụi tạo ra khoỏ cú độ dài là 64 byte để sử dụng thuật toỏn Mó khối của Phõn viện Khoa học Mật Mó.

Mụ tả chi tiết quỏ trỡnh trao đổi khoỏ: Chỳng tụi sử dụng `kex` ở chế độ client-

server, một bờn luụn luụn đợi bờn kia gửi đến. Đầu tiờn, khi khởi động client sẽ

tạo ra 56 byte dữ liệu ngẫu nhiờn cựng với 8 byte nhón thời gian (gettimeofday) gửi cho server và ngược lại. Hai bờn sử dụng hàm DH_generate_key() của openssl

để tạo ra khoỏ cụng khai Diffie-Hellman của mỡnh. Cuối cựng thỡ hai bờn sẽ nhận được khoỏ cụng khai của phớa bờn kia để tạo khoỏ Diffie-Hellman chung. Khi hai

bờn đó cú một khoỏ Diffie-Hellman chung, chương trỡnh sẽ dựng thuật toỏn SHA1

để tạo ra khúa giả ngẫu nhiờn 64 byte. Kể từ đõy, cỏc gúi tin trao đổi giữa hai mỏy

(trao đổi xỏc thực và cỏc tham số cần thiết khỏc) đó được mó hoỏ bằng thuật toỏn Mó khối (MK1). Hai bờn sẽ trao đổi định danh cho nhau, chữ ký số được ký trờn

định danh của mỗi mỏy. Khoỏ tạo ra được lưu trong thư mục /etc/keyEx/run với

tờn file là định danh của phớa bờn kia.

Các b−ớc trao đổi khố

• B−ớc 1: Client gửi 64 byte dữ liệu NONCES và nhãn thời gian cho Server.

• B−ớc 2: Khi Server đ−ợc kích hoạt nó cũng gửi cho Client 64 byte dữ liệu

NONCES và nhãn thời gian.

• B−ớc 3: Khi Client nhận đ−ợc dữ liệu, nó kiểm tra xem nếu là dữ liệu

NONCES (packet type là PKT_NONCE) thì nó sẽ tạo ra khóa cơng khai Diffie- Hellman (DH) gửi cho Server.

case Snonce:

if (pkttyp!=PKT_NONCE) goto stateerr;

if (len<8)

SendErrorRet("nonce too short"); if (len>NONCESLEN+1)

len=NONCESLEN+1; for (i=0; i<len-1; ++i) nonces[i]^=pkt[i+1]; DH_generate_key(dhp);

packetSendBN(fd, PKT_DHKEY, dhp->pub_key);

• B−ớc 4: Server tạo khố cơng khai DH và gửi cho Client.

• B−ớc 5: Khi Client và Server nhận đ−ợc khố cơng khai DH của nhau, chúng sẽ

tạo khố DH chung, từ đó sử dụng thuật tốn SHA1 để tạo khố giả ngẫu nhiên 64 byte. Khố này chính là khố trao đổi đ−ợc. Kể từ đây tất cả các gói tin trao đổi giữa hai bên đều đ−ợc mã hoá với thuật toán MK1. Lúc này, Client sẽ gửi định danh của mình (hostname) cho Server.

case Sdhkey:

if (pkttyp!=PKT_DHKEY) goto stateerr;

if (mlock(buf, sizeof(buf))<0)

Log(LOG_ERR, "handlePacket: mlock: %m"); {

BIGNUM *a=packetExtrBN(pkt, len); i=BN_cmp(a, dhp->pub_key);

if (!i) {

Log(LOG_ALERT, "handlePacket: Two equal DH pubkeys???");

abort(); /* something is VERY wrong */ } if (DH_compute_key(buf, a, dhp)<0) { SSLprinterror(LOG_ERR); BN_free(a); SendErrorRet("internal bad DH"); } BN_free(a); }

/* Get all keys, switch to encrypted */ i=getKeys(buf, DH_size(dhp), i);

memset(buf, 0, sizeof(buf)); if (i<0)

SendErrorRet("handlePacket: getKeys failed"); /* Send out identity next. */

i=snprintf(buf, sizeof(buf), "%c%08x %s", PKT_IDENT, PKfingerprint(myKey), myIdentity);

packetSend(fd, buf, i);

• B−ớc 6: Server nhận đ−ợc định danh của Client gửi sang, nó sẽ gửi trả lại định

danh của mình cho Client.

• B−ớc 7: Khi Client nhận đ−ợc định danh của Server, nó sẽ tạo chữ ký số bằng

cách ký lên định danh của Server rồi gửi cho Server.

/* Sign our sent stuff. */ buf[0]=PKT_SIGN;

i=strlen(s)/2;

pvkh_RSA_sign(buf+1, i); packetSend(fd, buf, strlen(buf));

• B−ớc 8: Server kiểm tra chữ ký số nhận đ−ợc, nếu thành cơng, nó sẽ gửi chữ ký

số của mình lên định danh của Client và gửi cho Client.

if (pkttyp!=PKT_SIGN) goto stateerr;

/* Verify the peer's signature. */

if ((i=pvkh_RSA_vrfy(pkt+1, len-1, myKey))==1)

{

struct sockaddr_in sa;

debug((DEB_PROTO, "Good signature")); if ((KEXsocket=getMySocket(&sa))<0)

SendErrorRet("Could not obtain UDP socket"); i=snprintf(buf, sizeof(buf), "%cme=%s:%d", PKT_OPT_REQ,inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));

setOption("me", buf+4, OF_DEFAULT); /* later? */

return Sopt; }

debug((DEB_PROTO, "Bad signature")); SSLprinterror(LOG_ERR);

SendErrorRet("Signature check failed");

• B−ớc 9: T−ơng tự, Client kiểm tra chữ ký số của nhận đ−ợc, nếu thành cơng, nó

sẽ gửi gói tin chứa địa chỉ IP của mình cho Server. Việc các bên tham gia quá trình trao đổi khố trao đổi thêm gói tin chứa địa chỉ IP của mình là rất quan trọng, làm tăng tính an tồn của thủ tục.

• B−ớc 10: Server gửi địa chỉ IP của mình cho Client. Khi Client nhận đ−ợc địa

chỉ IP của Server cũng là lúc hai bên thoả thuận xong khoá.

Nhận xét:

Việc hai bên trao đổi riêng biệt các gói tin chứa định danh, chữ ký số lên định danh của bên kia và gói tin chứa địa chỉ IP là khơng cần thiết. Chúng ta có thể gộp các tham số này lại và trao đổi một lần để giảm bớt số lần trao đổi. Công việc này chúng tôi sẽ thực hiện ở phiên bản sau. Client NONCES Server MK1(srvAddr:port) MK1(cliAddr:port) MK1(SIG(cliID)) MK1(SIG(srvID)) MK1(srvID) MK1(cliID) gy gx NONCES

Chữ ký số mà chúng tôi sử dụng đ−ợc thực hiện đúng theo sơ đồ chữ ký số RSA. Giả sử cli_sig là chữ ký số đ−ợc tạo ra bên Client, cli_sig sẽ đ−ợc tính nh− sau:

cli_sig = (srvID)srvPublicExponent mod (srvModulo)

cli_sig sẽ đ−ợc mã hoá với thuật toán MK1, rồi gửi cho Server. Server sẽ giải

mã và có đ−ợc cli_sig. Server kiểm tra chữ ký số nh− sau:

Tính: chk_sig = (srvID)srvPrivateExponet

mod (srvModulo). So

sánh chk_sig xem có bằng với cli_sig hay không.

Qua sơ đồ trên chúng ta thấy rằng quá trình trao đổi cần rất nhiều b−ớc, ta có thể thu gọn lại chỉ cịn 3 hoặc 4 b−ớc nh− thủ tục STS đ−ợc trình bày ở trên. Tuy vậy, do thời gian có hạn nên chúng tơi ch−a thực hiện đ−ợc.

Một phần của tài liệu đề tài phần mềm bảo mật mạng dùng giao thức ip quyển 4a các phần mềm bảo mật gói ip trên hệ điều hành linux (Trang 163 - 167)