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.