Personal

SP_INS_SINHVIEN

Prototype của procedure:

CREATE PROCEDURE SP_INS_SINHVIEN  
	@MASV NVARCHAR(20),
	@HOTEN NVARCHAR(100),
	@NGAYSINH DATETIME,
	@DIACHI NVARCHAR(200),
	@MALOP VARCHAR (20),
	@TENDN NVARCHAR(100),
	@MATKHAU VARCHAR(100)
AS
	DECLARE @hashedPassword VARBINARY(MAX);
 
	SET @hashedPassword = HASHBYTES('MD5', @MATKHAU);
 
	INSERT INTO SINHVIEN
	VALUES(@MASV, @HOTEN, @NGAYSINH, @DIACHI, @MALOP, @TENDN, @hashedPassword);
GO

Giải thích: tiến hành băm mật khẩu ở trong body của procedure bằng hàm HASHBYTES với tham số đầu tiên là thuật toán băm (MD5) và tham số thứ hai là chuỗi cần băm (@MATKHAU).

Nhận xét: mật khẩu truyền vào procedure là bản rõ, do đó có thể bị lộ trên đường truyền giữa ứng dụng và DB.

Setup AES 256

Kiểm tra nếu không tồn tại master key thì tạo, password là 20120356:

IF NOT EXISTS(
	SELECT*
	FROM sys.symmetric_keys
	WHERE symmetric_key_id = 101
)
CREATE MASTER KEY ENCRYPTION BY
	PASSWORD = '20120356'
GO

Kiểm tra nếu không tồn tại chứng chỉ thì tạo, chứng chỉ có tên là MyCert:

IF NOT EXISTS(
	SELECT *
	FROM sys.certificates
	WHERE name = 'MyCert'
)
CREATE CERTIFICATE MyCert
	WITH SUBJECT = 'MyCert';
GO

Kiểm tra nếu không tồn tại khóa đối xứng thì tạo:

  • Thuật toán mã hóa là AES-256.
  • Khóa được mã hóa bằng chứng chỉ MyCert.
  • Tên của khóa là PriKey.
IF NOT EXISTS(
	SELECT *
	FROM sys.symmetric_keys
	WHERE name ='PriKey'
)
CREATE SYMMETRIC KEY PriKey
	WITH ALGORITHM = AES_256 
	ENCRYPTION BY CERTIFICATE MyCert;
GO

Open khóa để mã hóa:

OPEN SYMMETRIC KEY PriKey
	DECRYPTION BY Certificate MyCert;
GO

SP_INS_NHANVIEN

Prototype của procedure:

CREATE PROCEDURE SP_INS_NHANVIEN
	@MANV VARCHAR (20),
	@HOTEN NVARCHAR(100),
	@EMAIL VARCHAR(20),
	@LUONG VARBINARY(MAX),
	@TENDN NVARCHAR(100),
	@MATKHAU VARCHAR(100)
AS
	DECLARE @hashedPassword VARBINARY(MAX), @encryptedSalary VARBINARY(MAX);
 
	SET @hashedPassword = HASHBYTES('SHA1', @MATKHAU);
	SET @encryptedSalary = ENCRYPTBYKEY(KEY_GUID('PriKey'), @LUONG);
 
	INSERT INTO NHANVIEN
	VALUES(@MANV, @HOTEN, @EMAIL, @encryptedSalary, @TENDN, @hashedPassword);
GO

Giải thích: mã hóa bằng hàm ENCRYPTBYKEY với tham số đầu tiên là ID của khóa PriKey (sử dụng hàm KEY_GUID để lấy ID) và tham số thứ hai là giá trị cần mã hóa (@LUONG). Điều kiện tiên quyết là khóa PriKey phải được open.

Nhận xét: tương tự SP_INS_SINHVIEN, các dữ liệu bản rõ truyền vào procedure có thể bị lộ trên đường truyền.

SP_SEL_NHANVIEN

Prototype của procedure:

CREATE PROCEDURE SP_SEL_NHANVIEN
AS
	SELECT MANV, HOTEN, EMAIL, CONVERT(INT, DECRYPTBYKEY(LUONG)) AS LUONG
	FROM NHANVIEN;
GO

Giải thích: giải mã bằng hàm DECRYPTBYKEY với tham số duy nhất là giá trị cần giải mã. Kết quả trả về có kiểu VARBINARY nên cần chuyển sang INT bằng cách dùng hàm CONVERT.

Nhận xét: dữ liệu trả về của SP_SEL_NHANVIEN có thể bị lộ trên đường truyền.

Summary

Tất cả những thao tác mã hóa/giải mã đều được thực hiện ở DBMS. Vì thế, thông tin bản rõ có thể bị lộ trên đường truyền khi thực hiện insert.

Group

SP_INS_PUBLIC_NHANVIEN

Prototype của procedure:

create proc SP_INS_PUBLIC_NHANVIEN (
            @MANV sysname, @HOTEN nvarchar(100), @EMAIL varchar(20),
            @LUONGCB nvarchar(100), @TENDN nvarchar(100), @MK varchar(20)) as
begin
    ...
end

Giải thích: kiểu sysname là kiểu dùng để lưu tên của database object chẳng hạn như tên bảng, tên view, etc. Về bản chất thì nó là nvarchar(128).

Kiểm tra và tạo khóa bất đối xứng của thuật toán RSA 2048:

declare @c nvarchar(MAX)
 
if Asymkey_Id(@MANV) is null
    begin
        set @c = 'CREATE ASYMMETRIC KEY '    + quoteName(@MANV) + ' ' +
                 'WITH ALGORITHM = RSA_2048 ' + 
                 'ENCRYPTION BY PASSWORD = ' + quoteName(@mk , nchar(39))
        exec (@c)
	end
end

Giải thích:

  • Hàm Asymkey_Id giúp trả về ID của khóa bất đối xứng.
  • Hàm quoteName giúp bao bên ngoài đối số một cặp nháy đơn và escape các cặp ngoặc vuông có trong đối số.

Mã hóa đồng thời thêm dữ liệu vào bảng NHANVIEN:

insert into NHANVIEN
values (@MANV, @HOTEN, @EMAIL, cast(EncryptByAsymKey(Asymkey_Id(@MANV), @LUONGCB) as varbinary(max)), 
		@TENDN, hashBytes('SHA1', @MK))

Giải thích:

  • Hàm EncryptByAsymKey giúp mã hóa dữ liệu theo hệ mã bất đối xứng, với tham số đầu tiên là ID của khóa bất đối xứng và tham số thứ hai là dữ liệu cần mã hóa.
  • Hàm hashBytes giúp băm dữ liệu, với tham số thứ nhất là thuật toán băm và tham số thứ hai là dữ liệu cần băm.
  • Hàm cast giúp chuyển đổi kiểu dữ liệu.

SP_SEL_PUBLIC_NHANVIEN

Prototype của procedure:

create proc SP_SEL_PUBLIC_NHANVIEN(@TENDN nvarchar(100), @MK varbinary(max)) as

Nhận xét: tham số thứ hai có dạng varbinary, đồng nghĩa với việc ứng dụng sẽ thực hiện mã hóa rồi mới truyền dữ liệu mã vào lời gọi procedure.

Procedure thực hiện thử truy vấn đến bảng nhân viên để kiểm tra username và password1 :

begin
	begin try 
		select MANV, HOTEN, EMAIL
		from NHANVIEN
		where TENDN = @tenDN and MATKHAU = @MK
	end try  
	begin catch  
		print('Password or username wrong')  
	end catch
end

Lời gọi trong code như sau:

connection.Open();
command.Connection = connection;
command.CommandText = "exec SP_SEL_PUBLIC_NHANVIEN '" + username + "', 0x" + Util.SHA1Util.GetSHA1(password);

Có thể thấy, ứng dụng thực hiện băm chuỗi mật khẩu được nhập vào bằng hàm băm rồi mới gọi truy vấn đến procedure SP_SEL_PUBLIC_NHANVIEN.

SP_SEL_CLASS_STUDENT

Prototype của procedure:

create proc SP_SEL_CLASS_STUDENT(@malop varchar(20), @MK varbinary(max)) as

Nhận xét: có prototype tương tự như SP_SEL_PUBLIC_NHANVIEN, mật khẩu cũng cần phải được mã hóa từ phía ứng dụng.

Truy vấn dữ liệu sinh viên:

begin
	if exists (select * from LOP lop join NHANVIEN nv on lop.MANV = nv.MANV where lop.MALOP = @malop and @MK = nv.MATKHAU)
		select sv.MASV, sv.HOTEN, sv.NGAYSINH, sv.DIACHI, sv.MALOP, sv.TENDN, lop.TENLOP, nv.MANV, nv.HOTEN as 'NguoiQuanLy'
		from SINHVIEN sv 
		join LOP lop on sv.MALOP = lop.MALOP
		join NHANVIEN nv on nv.MANV = lop.MANV
		where SV.MALOP = @malop
	else
		print('Password or @MALOP is not under your management')
end

Giải thích:

  • Đầu tiên kiểm tra xem có tồn tại một lớp có mã lớp @malop mà được nhân viên có mật khẩu @MK quản lý hay không. Nói cách khác, kiểm tra xem nhân viên đang đăng nhập có quyền xem thông tin của lớp mà họ muốn xem hay không. Bởi vì nhân viên chỉ được xem thông tin của lớp mà họ quản lý.
  • Nếu thỏa điều kiện trên thì tiến hành truy vấn đến lớp có mã lớp là @malop để lấy thông tin.

SP_INS_PUBLIC_BANGDIEM

Trước tiên cần tạo khóa đối xứng của thuật toán AES 2562 :

create proc create_key as
begin
	create symmetric key PK_6
    with algorithm = AES_256
    encryption by password = 'PK_6'
end
 
exec create_key;

Prototype của procedure:

create proc SP_INS_PUBLIC_BANGDIEM (@MASV varchar(20), @MaHP varchar(20), @DiemThi nvarchar(100), @MK varchar(20)) as
begin
	...
end

Nhận xét: thông tin của bảng điểm sẽ bao gồm mã sinh viên (@MASV), mã học phần (@MaHP) và điểm thi (@DiemThi). Ngoài ra khi thêm còn cần phải truyền vào mật khẩu của nhân viên quản lý (@MK).

Truy vấn lấy mã nhân viên mà đang quản lý sinh viên có mã là @MASV:

declare @manv varchar(20);
set @manv = (select nv.MANV 
			from NHANVIEN nv join LOP lop on nv.MANV = lop.MANV 
			join SINHVIEN sv on sv.malop = lop.malop 
			where @MASV = sv.MASV);

Thực hiện mã hóa và thêm vào một entry ở trong bảng điểm:

open symmetric key PK_6
decryption by password = 'PK_6'
 
if @MK = (select nv.MATKHAU from NHANVIEN nv where nv.MANV = @manv)
	insert into BANGDIEM values (@MASV, @MaHP, cast(encryptbykey(key_guid('PK_6'), @DiemThi) as varbinary(max)));
else 
	print('BAN KHONG CO QUYEN NHAP DIEM CHO SV NAY')
 
close symmetric key PK_6

Giải thích:

  • Trước tiên cần enable khóa PK_6.
  • Sau đó kiểm tra xem mật khẩu có khớp với nhân viên có mã là @manv tìm được ban đầu hay không. Nếu khớp thì mã hóa điểm thi và thêm vào bảng điểm kèm theo các thông tin khác.
  • Cuối cùng disable khóa PK_6.

SP_GET_PUBLIC_BANGDIEM

create proc SP_GET_PUBLIC_BANGDIEM (@MASV varchar(20), @MK varchar(20)) as
begin
	declare @manv varchar(20);
	set @manv = (select nv.MANV 
				from NHANVIEN nv join LOP lop on nv.MANV = lop.MANV 
				join sinhvien sv on sv.malop = lop.malop 
				where @MASV = sv.MASV);

Nhận xét: tương tự với các procedures trên, tham số cần phải có mật khẩu của nhân viên quản lý và cũng cần phải truy vấn lấy mã của nhân viên đang quản lý sinh viên có mã là @MASV.

Thực hiện giải mã và truy vấn:

	open symmetric key PK_6
    decryption by password = 'PK_6'
 
    if @MK = (select nv.MATKHAU from NHANVIEN nv where nv.MANV = @manv)
		select bd.MASV, bd.MAHP, cast(Decryptbykey(DIEMTHI) as varchar(max)) as DIEMTHI
		from BANGDIEM bd 
		where @MASV = bd.MASV;
	else 
		print('BAN KHONG CO QUYEN XEM DIEM CHO SV NAY')
		
	close symmetric key PK_6
end

Nhận xét: cách hoạt động tương tự như SP_INS_PUBLIC_BANGDIEM. Khóa được sử dụng để giải mã là khóa đối xứng PK_6.

SP_DEL_PUBLIC_BANGDIEM

Prototype của procedure:

create proc SP_DEL_PUBLIC_BANGDIEM (@MASV nvarchar(20), @MAHP varchar(20), @MK varchar(20)) as

Để xóa điểm thì cần phải biết được điểm đó của sinh viên nào (@MASV) và điểm đó thuộc học phần gì (@MAHP).

Cơ chế xóa điểm cũng tương tự như hai procedure trên, chỉ thay câu truy vấn sau câu lệnh kiểm tra mật khẩu thành:

delete from BANGDIEM where @MASV = MASV and @MAHP = MAHP

Đồng thời, do không liên quan đến mã hóa nên không cần open và close khóa.

SP_UPDATE_PUBLIC_BANGDIEM

Prototype của procedure:

create proc SP_UPDATE_PUBLIC_BANGDIEM (@MASV nvarchar(20), @MAHP varchar(20), @score varchar(20), @MK varchar(20)) as

Tương tự với thêm điểm, chỉ khác ở câu truy vấn sau câu lệnh kiểm tra mật khẩu:

update BANGDIEM 
set DIEMTHI = cast(encryptbykey(key_guid('PK_6'), @score) as varbinary(max))

Summary

Các procedures có một số điểm chung như sau:

  • Đều chứa tham số mật khẩu có kiểu là varbinary (cần phải được mã hóa ở phía ứng dụng).
  • Đều kiểm tra xem mật khẩu có khớp với mật khẩu của nhân viên quản lý lớp hoặc sinh viên rồi mới thực hiện truy vấn.

Các bảng chứa dữ liệu cần mã hóa: NHANVIEN (LUONG) và BANGDIEM (DIEMTHI).

  • Đối với LUONG: mã hóa và giải mã bằng thuật toán RSA 2048, khởi tạo khóa bất đối xứng lúc thêm nhân viên.
  • Đối với DIEMTHI: mã hóa và giải mã bằng thuật toán AES 256, khởi tạo khóa đối xứng lúc chạy script SQL và open/close khóa trong body của procedure.

Footnotes

  1. Đề yêu cầu mã hóa bằng public key của nhân viên quản lý (thuật toán RSA 512).

  2. Theo đề thì procedure này dùng để truy vấn toàn bộ dữ liệu của nhân viên chứ không phải để xác thực đăng nhập.