VFP的数据库加密算法
曲景东·VFP网络工作室 出处:网络
前言
在应用软件中,数据库管理软件是应用的最广泛的软件。数据库管理软件的安全性、保密性是开发、应用人员较为关心的。如何防止无关人员浏览数据库,如何防止数据库被非法修改、破坏?常用的方法是给数据库、管理程序加上密码。那么,加了密码就安全了吗?怎样才能使密码安全呢?
二、传统的密码加密方法
从dBASE到dBASEIII,从FOXBASE到FOXBASE+,从FOXPRO到VISUALFOXPRO,常用加密码的方法给程序、数据库加密。常见的密码有以下几种:固定密码,简单加密的固定密码,加密变化的密码,具体分析如下:
1、固定密码
固定密码,就是系统只有一个密码,而且是固定的,不可变的。常见于用Dbase、FOXBASE、FOXBASE+、FOXPRO2.X开发的数据库管理系统。常用如下语句:
I=1
DO WHILE .T.
PWD=SPACE(8)
SET CONS OFF
@12,35 SAY " 口 令!!!"
ACCEPT TO PWD
IF TRIM(PWD)$#@60; $#@62;"123456"
IF I $#@62;=3
@20,32 SAY "口令错误,您不能使用!"
RETURN
ENDIF
@12,30 SAY "第" +STR(I,1)+"次口令错!"
I =I +1
ELSE
@20,28 SAY "欢迎使用本系统!"
EXIT
ENDIF
ENDDO
从以上语句不难看出,其核心是:变量PWD与输入值的比较。密码“1234”是程序设计时设定的,以后应用时是无法修改的,如果修改,就要改变源程序。当然,也可以编写一段子程序用来修改密码,修改前,其判断旧密码是否正确,也用IFTRIM (PWD)$#@60;$#@62;"123456"语句。其灵活性很差,在pctool等工具出现后,保密性就显得差了。
2、简单加密的固定密码
简单加密的固定密码,是指把密码进行简单的加密,但密码仍然是固定的,不变的。简单加密一般有两种:“钥匙盘”法和“变换法”。“钥匙盘”法,就是把密码存放在一张软盘上,使用时将“钥匙盘”插入计算机,系统程序读取软盘中的密码。或把密码和操作员姓名存到数据库中,此数据库存放于软盘内,使用时把“钥匙盘”插入计算机,系统读取软盘中的密码和操作员姓名,下面是此法的主要语句:
USE A:KLK &&到KLK数据库内查找输入的操作员的姓名;
I=1
DO WHILE .T.
STORE SAPCE(8) TO XM
@ 10,26 SAY "请输入操作员姓名:" GET XM
READ
LOCATE ALL FOR LTRIM(TRIM(XM))=LTRIM(TRIM(NAME))
IF .NOT. EOF()
EXIT &&操作员姓名输入正确,向下执行;
ENDIF
IF I $#@62;=3
&&操作员姓名输入计数,输入次数超过3次,退出系统;(代码同前)
…
ENDIF
ENDDO
IF I$#@60; 5 &&姓名正确后,比较输入口令正确否;
MKL =SPACE(8)
I=1
DO WHILE I$#@60; 3
SET CONS OFF
@12,30 SAY " 口令! !"
ACCEPT TO MKL
SET CONS ON
IF TRIM(MKL)=TRIM(KL)
EXIT &&口令正确,向下执行;
ELSE
IF I $#@62;=3
I=5
EXIT
ENDIF
@12,30 SAY "第" +STR(I,1)+"次口令错!"
I =I +1
ENDIF
ENDDO
ENDIF
IF I=5
@20,32 SAY "口令错误,您不能使用!"
ELSE
@20,32 SAY "欢迎使用!"
ENDIF
RETURN
这种加密方法保密性要好一些,但每次使用都要用“钥匙盘”进入系统,很繁琐。
变换法,就是通过对密码的运算,使密码发生变化的方法,一般采用换算法,常用的加密语句如下:
PSD=CHR(65)+CHR(66)+CHR(67)+"9"
函数CHR(),是用来换算ASCII码的,换算后的PSD是ABC9。用这种简单的换算,可以避免密码被直接发现,如果和上述方法混合应用,保密性就加强了。
3、简单加密变化的密码
以上密码都是固定的,下面介绍一种经简单加密变换的密码。这是利用时间函数来加密的算法,密码每天都不同。密码由变化的时间和固定字符构成。其核心语句为:
kl=DATE()
PWD=SUBSTR(CDOW(kl),1,3)+"1234"
CDOW()函数,输入年月日,返回星期几(字符型)。操作者根据今天是星期几,将星期的前3个英文字母和固定的“1234”输入,与变量PWD比较。程序会把今天的日期换算成星期数,然后取前3位,并加上“1234”,合成今天的密码变量PWD。这样就实现了每天有不同的密码。保密性加强了。
以上几种加密方法都是传统的简单的加密方法,其特点是简单、保密性差,密码单一,保护能力较低,主要用于Dbase、FOXBASE、FOXBASE+、FOXPRO2.x中,由于上述软件的编译不是真正的编译,其密码容易被发现。
三、一种新型密码加密方法
以上介绍的是几种固定的密码加密方法,下面介绍一下可变密码。“可变密码”指其密码值可由设置自行改变,这种方法一般由文件保存密码,且密码经过加密运算。密码的加密算运算方法很多,常用的有:转换法、位移法、时间法、随机法等。转换法,就是把输入的密码经过转换计算,转换成保存密码,取密码时,再经过逆运算,把密码还原。
不定时密码也时可变密码的一种,是指密码的出现是以随机方式来询问用户。如:用户在执行两个功能后必须输入密码,下一次检查密码可能在执行三个功能后检查密码。这种密码较为隐蔽。其方法如下:首先声明一个变量,用来计数,是1-5的随机数;在每一个过程、函数、或命令执行前,累加该变量值;当该变量值等于其随机值时,调用密码查询程序。
下面具体介绍一种基于VFP5.0的密码设定方法。其特点是:具有使用登记功能;每人一个密码,并可随时更换;密码经加密运算,不易被破解。
基本思路如下:首先建立两个数据库(table),一个用来存放口令及对应的用户(称为“口令库”),另一个存放用户登录使用情况(称为“登录库”)。在再建立两个窗口(form),一个用来检查口令,另一个用来修改口令。接下来定义两个过程(procedure),一个用来给口令加密(“加密过程”),另一个用给口令解密(“解密过程”)。这个“加密过程”,是把密码经加密运算后存入口令库,而“解密过程”实际上是把输入的密码经加密运算后与口令库内的密码进行比较,并不是解密。为了使密码输入时不被人看见,要对密码输入的文字框的属性作如下工作:进入DATA属性栏,把InputMask属性改为:XXXXXX,进入LAYOUT属性栏,把PassWordChar的属性改为:“*”,这样,输入的密码就不会被别人发现。(在FOXBASEFOXBASE+,FOXPRO2.X中,常用设置背景颜色与输入密码字符颜色相同的办法来防止别人看见。)
“解密过程”代码如下:
parameter password
pas=""
n1=asc(substr(name,1,1))
&&取姓名的第一个拼音字母,换算成ASCII码
n2= asc(substr(name,2,1)) &&作为加密的键值
n3= asc(substr(name,3,1))
n=int((n1+n2+n3)/3)
for i=1 to len(trim(password))
&&使用BITXOR()函数对密码进行解密
tempchr=bitxor(asc(substr(password,i,1)),n)
pas=pas+chr(tempchr)
endfor
locate for klk.user_id=name
&&与口令库内的与姓名相对应的口令进行比较
if (klk.key$#@60; $#@62;pas) and (password$#@60; $#@62;"hg")
result=.f.
else
result=.t.
endif
return result
BITXOR()函数是vfp特有的函数,它将函数的两个参数转换成二进制数,并且执行“与”操作,返回一个十进制的结果。用它来进行加密运算,保密性强。加上密码键值n(取姓名的第一个拼音字母,经求和,再取平均值,再取整运算,换算成ASCII码),得到每人一个的密码。
该“过程”的定义方法如下:在定义检查密码的窗口(form)的编辑状态下,用鼠标点菜单form,选“new method”,键入“过程”名。然后双击正在编辑的窗口(form),然后进入"过程"的编辑状态,写入如上代码。加密过程是解密过程的逆运算,代码如下:
parameter password
pas=""
for i=1 to len(trim(password))
n1=asc(substr(name,1,1))
n2= asc(substr(name,2,1))
n3= asc(substr(name,3,1))
n=int((n1+n2+n3)/3)
tempchr=bitxor(asc(substr(password,i,1)),n)
pas=pas+chr(tempchr)
endfor
replace key with pas
检查密码的思路是:先到输入姓名的文字框内取姓名,再到口令库内查找姓名,如果找不到姓名,返回消息窗口“您不是指定用户,请与系统管理员联系!”,系统退出;如果找到了用户姓名,则继续进行,把输入的口令和姓名送到解密“过程”中进行运算,解密“过程”将其解密,并与口令库内的数据进行比较,如果不正确,开始计数,要求重新输入密码,三次不正确,退出系统。如果正确,释放当前窗口,进入系统。
主要代码如下:
name=trim(ThisForm.Text1.value)
if empty(name)
a=messagebox
("请输入用户名!",0+48,"信息窗口")
ThisForm.Text1.setfocus
return
endif
pass=trim(ThisForm.Text2.value)
if empty(pass)
a=messagebox
("请输入口令!",0+48,"信息窗口")
ThisForm.Text2.setfocus
return
endif
use klk
locate for klk.user_id=name
if found()=.f.
=messagebox
("你不是指定用户,请与系统管理员联系!",64,"提示信息")
thisform.release
else
ok =Thisform.decode(pass)
if ok=.t.
ThisForm.Label3.caption="欢迎使用!"
wait window
欢迎使用!按任意键进入“系统维护模块。”
release thisform
do form wh_wh
else
if m=3
m=m+1
ThisForm.Label3.caption="口令错,您无权使用"
a=messagebox
("对不起,您无权使用!",0+48,"信息窗口")
release thisform
else
a=messagebox
("口令错,请重新输入!",0+48,"信息窗口")
ThisForm.Text2.value=""
ThisForm.Text2.setfocus
m=m+1
endif
endif
endif
改变密码的思路是:首先读取用户姓名,如果是新用户则请用户输入新密码,并记录下获得新密码的时间;如果是老用户,则读取用户旧密码,将旧密码进行解密运算并和口令库内容比较,如果正确,请用户输入新密码,并将新密码通过解密运算存入口令库,并记录修改时间。
主要代码如下:
name=ThisForm.Text3.value
oldpass=ThisForm.Text1.value
newpass=ThisForm.Text2.value
if isblank(newpass)
= messagebox("请重新输入新密码!",64,"信息提示")
ThisForm.Text1.setfocus()
return
endif
success=thisform.decode(oldpass)
if not success
= messagebox
("旧密码不正确,重新输入密码!",64,"信息提示")
ThisForm.Text1.setfocus()
return
endif
locate for klk.user_id =name &&new user logo
if found()=.f.
=messagebox("您是新用户!",64,"信息提示")
append blank
replace klk.user_id with name,klk.logo_ddate with date()
thisform.text3.setfocus
endif
thisform.Encode(newpass)
= messagebox
("旧密码已经修改完成,下次请使用新密码!",64,"信息提示")
ThisForm.Command2.setfocus
return
注意,在改变密码的窗口(form)中,要定义“加密过程”和“解密过程”,方法如上所述。
以上是一个加密算法的主要思路和关键代码,其它部分读者可自行设计。这个加密算法还可以进一步完善。如采用不同的函数进行运算,加入日期,使每个人每天的密码都不一样(加入时间的算法如前所述,利用CDOW()函数作为键值的一部分。)。
[返回] |