Database 版 (精华区)

发信人: mengy (LEAR DLLS 命令时,将从内存中清除), 信区: Database
标  题: 一 种 基 于VFP5.0 的 数 据 库 加 密 算 法 
发信站: 哈工大紫丁香 (2000年12月13日09:20:01 星期三), 站内信件


曲 景 东 杨 连 启 尹 锐 
一、 前 言
---- 在 应 用 软 件 中, 数 据 库 管 理 软 件 是 应 用 的 最 广 泛 的 软
 件。 数 据 库 管 理 软 件 的 安 全 性、 保 密 性 是 开 发、 应 用 人 员
 较 为 关 心 的。 如 何 防 止 无 关 人 员 浏 览 数 据 库, 如 何 防 止 
数 据 库 被 非 法 修 改、 破 坏 ? 常 用 的 方 法 是 给 数 据 库、 管 理
 程 序 加 上 密 码。 那 么, 加 了 密 码 就 安 全 了 吗 ? 怎 样 才 能 
使 密 码 安 全 呢 ? 

二、 传 统 的 密 码 加 密 方 法
---- 从dBASE 到dBASEIII , 从 FOXBASE 到FOXBASE +, 从FOXPRO 到VISUAL 
FOXPRO, 常 用 加 密 码 的 方 法 给 程 序、 数 据 库 加 密。 常 见 的 密
 码 有 以 下 几 种: 固 定 密 码, 简 单 加 密 的 固 定 密 码, 加 密 变
 化 的 密 码, 具 体 分 析 如 下: 

---- 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)<  >"123456"
   IF I >=3
      @20,32 SAY "口令错误,您不能使用!"
      RETURN
   ENDIF
  @12,30 SAY "第" +STR(I,1)+"次口令错!"
  I =I +1
ELSE
  @20,28 SAY "欢迎使用本系统!"
   EXIT
ENDIF
ENDDO
---- 从 以 上 语 句 不 难 看 出, 其 核 心 是: 变 量PWD 与 输 入 值 的
 比 较。 密 码“1234” 是 程 序 设 计 时 设 定 的, 以 后 应 用 时 是 无
 法 修 改 的, 如 果 修 改, 就 要 改 变 源 程 序。 当 然, 也 可 以 编
 写 一 段 子 程 序 用 来 修 改 密 码, 修 改 前, 其 判 断 旧 密 码 是 
否 正 确, 也 用 IF TRIM(PWD)< >"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 >=3 
 &&操作员姓名输入计数,输入次数超过3次,退出系统;(代码同前)
 …
    ENDIF
ENDDO
IF I< 5  &&姓名正确后,比较输入口令正确否;
  MKL =SPACE(8)
  I=1
  DO WHILE I< 3
  SET CONS OFF
  @12,30 SAY " 口令! !"
  ACCEPT TO MKL
  SET CONS ON 
  IF TRIM(MKL)=TRIM(KL)
     EXIT &&口令正确,向下执行;
  ELSE
     IF I >=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 的 属 性 改 为:“*”, 这 样, 输 入 的 密 码 就 不 会 被
 别 人 发 现。( 在FOXBASE FOXBASE +,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<  >pas) and (password<  >"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() 函 数
 作 为 键 值 的 一 部 分。)。 
 

 




--

       大海无边天做岸
               山登绝顶我为风

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.227.121]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:207.851毫秒