您的位置:首页 > 数据库

【叶子函数分享五十二】在SQL SERVER中实现RSA加解密函数(第二版)

2014-11-13 10:30 232 查看
/***************************************************  
    作者:herowang(让你望见影子的墙)
    日期:2010.1.5
    注: 转载请保留此信息
    更多内容,请访问我的博客:blog.csdn.net/herowang
****************************************************/
/*
   本次修改增加了unicode的支持,但是加密后依然显示为进制数据,因为进行RSA加密后所得到的unicode编码是无法显示的,所以密文依然采用进制数据显示。
   需要特别注意:如果要对中文进行加密,那么所选取的两个素数要比较大,两个素数的成绩最好要大于,即大于unicode的最大编码值
   另外修改了第一个版本的部分函数名称
*/
 
在SQL SERVER中实现RSA加密算法
--判断是否为素数
if object_id('f_primeNumTest') is not null
  drop function f_primeNumTest
go
create function [dbo].[f_primeNumTest]
(@p int)
returns bit
begin
  declare @flg bit,@i int
  select @flg=1, @i=2
  while @i<=sqrt(@p)
  begin
     if(@p%@i=0  )
     begin
        set @flg=0
       break
     end 
     set @i=@i+1
  end
  return @flg
end
go
--测试示例:
select [dbo].[f_primeNumTest](23)--1
select [dbo].[f_primeNumTest](24)--0
select [dbo].[f_primeNumTest](25)--0
select [dbo].[f_primeNumTest](26)--0
select [dbo].[f_primeNumTest](27)--0
 
--判断两个数是否互素
if object_id('f_isNumsPrime') is not null
  drop function f_isNumsPrime
go
create function f_isNumsPrime
(@num1 int,@num2 int)
returns bit
begin
  declare @tmp int,@flg bit
  set @flg=1
  while (@num2%@num1<>0)
  begin
    select @tmp=@num1,@num1=@num2%@num1,@num2=@tmp
  end
  if @num1=1
     set @flg=0
  return @flg
end
 
go
--产生密钥对
if object_id('p_createKey') is not null
  drop proc p_createKey
go
create proc p_createKey
@p int,@q int
as
begin
    declare @n bigint,@t bigint,@flag int,@d int
    if dbo.f_primeNumTest(@p)=0
    begin
<
fbbb
p align="left">       print cast(@p as varchar)+'不是素数,请重新选择数据'
       return
    end
    if dbo.f_primeNumTest(@q)=0
    begin
       print cast(@q as varchar)+'不是素数,请重新选择数据'
       return
  end
  print '请从下列数据中选择其中一对,作为密钥'
    select @n=@p*@q,@t=(@p-1)*(@q-1)
    declare @e int
    set @e=2
    while @e<@t
    begin
       if dbo.f_isNumsPrime(@e,@t)=0
       begin
          set @d=2
       while @d<@n
            begin
              if(@e*@d%@t=1)
                 print cast(@e as varchar)+space(5)+cast(@d as varchar)
              set @d=@d+1
            end
    end
       set @e=@e+1       
    end
end
 
/*加密函数说明,@key 为上一个存储过程中选择的密码中的一个,@p ,@q 产生密钥对时选择的两个数。获取每一个字符的unicode值,然后进行加密,产生个字节的位数据*/
if object_id('f_RSAEncry') is not null
  drop function f_RSAEncry
go
create function f_RSAEncry
 (@s varchar(100),@key int ,@p int ,@q int)
returns nvarchar(4000)
as
begin
   declare @crypt varchar(8000)
     set @crypt=''
   while len(@s)>0
   begin
              declare @i bigint,@tmp varchar(10),@k2 int,@leftchar int
              select @leftchar=unicode(left(@s,1)),@k2=@key/2,@i=1
              while @k2>0
              begin
                     set @i=(cast(power(@leftchar,2) as bigint)*@i)%(@p*@q)
                     set @k2=@k2-1
              end 
              set @i=(@leftchar*@i)%(@p*@q)   
              set @tmp=''
              select @tmp=case when @i%16 between 10 and 15 then char( @i%16+55) else cast(@i%16 as varchar) end+@tmp,@i=@i/16
              from (select number from master.dbo.spt_values where type='p'  and number<10 )K
              order by  number desc
              set @crypt=@crypt+right(@tmp,6)
              set @s=stuff(@s,1,1,'')
  end
  return @crypt
end
 
--解密:@key 为一个存储过程中选择的密码对中另一个数字,@p ,@q 产生密钥对时选择的两个数
if object_id('f_RSADecry') is not null
  drop function f_RSADecry
go
create function f_RSADecry
 (@s nvarchar(4000),@key int ,@p int ,@q int)
returns nvarchar(4000)
as
begin
  declare @crypt varchar(8000)
  set @crypt=''
  while len(@s)>0
    begin
       declare @leftchar bigint
       select @leftchar=sum(data1)
       from (select case upper(substring(left(@s,6), number, 1)) when 'A' then 10
                                                    when 'B' then 11
                                                    when 'C' then 12
                                                    when 'D' then 13
                                                    when 'E' then 14
                                                    when 'F' then 15
                else substring(left(@s,6), number, 1)
                end* power(16, len(left(@s,6)) - number) data1
         from (select number from master.dbo.spt_values where type='p')K
         where number <= len(left(@s,6))
     ) L
    declare @k2 int,@j bigint
       select @k2=@key/2,@j=1
    while @k2>0
       begin
      set @j=(cast(power(@leftchar,2)as bigint)*@j)%(@p*@q)
      set @k2=@k2-1
    end
    set @j=(@leftchar*@j)%(@p*@q)
    set @crypt=@crypt+nchar(@j)
    set @s=stuff(@s,1,6,'')
    end
  return @crypt
end
 
使用方法:
1、先使用p_createkey生成一对密钥,参数为两个参数
2、调用相应进行加密、解密
--【测试】
if object_id('tb') is not null
   drop table tb
go
create table tb(id int identity(1,1),col varchar(100))
go
insert into tb values(dbo.f_RSAEncry('中国人',779,1163,59))
insert into tb values(dbo.f_RSAEncry('Chinese',779,1163,59))
select * from tb
 
--运行结果
/*
id          col
----------- ---------------------------------------------
1           00359B00E6E000EAF5
2           01075300931B0010A4007EDC004B340074A6004B34
*/
 
select * ,解密后=dbo.f_RSADecry(col,35039,1163,59)from tb
 
--测试示例
/*
id          col                                         解密后   
----------- ------------------------------------------- -----------
1           00359B00E6E000EAF5                          中国人
2           01075300931B0010A4007EDC004B340074A6004B34  Chinese
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: