您的位置:首页 > 数据库

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

2014-11-13 10:31 239 查看
/***************************************************  
    作者:herowang(让你望见影子的墙)
    日期:2010.1.1
    注:   转载请保留此信息
    更多内容,请访问我的博客:blog.csdn.net/herowang
****************************************************/
一、RSA算法原理
 
RSA算法非常简单,概述如下:
找两素数p和q
取n=p*q
取t=(p-1)*(q-1)
取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为)
取d*e%t==1
这样最终得到三个数:n   d   e
 
设消息为数M (M <n)
设c=(M**d)%n就得到了加密后的消息c
设m=(c**e)%n则m == M,从而完成对c的解密。
注:**表示次方,上面两式中的d和e可以互换。
 
在对称加密中:
n d两个数构成公钥,可以告诉别人;
n e两个数构成私钥,e自己保留,不让任何人知道。
给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。
别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。
 
rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法求得d。
 
以上内容出自原文出处http://www.xfocus.net/articles/200503/778.html
 
二、使用T-SQL实现RSA算法
 
--判断是否为素数
if object_id('f_pnumtest') is not null
  drop function f_isPrimeNum
go
create function [dbo].[f_isPrimeNum]
(@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
 
--判断两个数是否互素,首先要选取两个互素的数
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
4000

  if @num1=1
     set @flg=0
  return @flg
end
 
--产生密钥对
if object_id('p_createKey1') is not null
  drop proc p_createKey1
go
create proc p_createKey1
@p int,@q int
as
begin
       declare @n bigint,@t bigint,@flag int,@d int
       if dbo.f_pnumtest(@p)=0
       begin
              print cast(@p as varchar)+'不是素数,请重新选择数据'
              return
       end
       if dbo.f_pnumtest(@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 产生密钥对时选择的两个数。获取每一个字符的ascii值,然后进行加密,产生个字节的位数据*/
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 varchar(8000)
as
begin
  declare @crypt varchar(8000)
       set @crypt=''
  while len(@s)>0
  begin
              declare @i int,@tmp varchar(10),@k2 int,@leftchar int
              select @leftchar=ascii(left(@s,1)),@k2=@key,@i=1
    while @k2>0
    begin
      set @i=(@leftchar*@i)%(@p*@q)
      set @k2=@k2-1
    end     
              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,4)
              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 varchar(100),@key int ,@p int ,@q int)
returns varchar(8000)
as
begin
  declare @crypt varchar(8000)
       set @crypt=''
  while len(@s)>0
       begin
              declare @i int
              select @i=sum(data1)
              from (   select case upper(substring(left(@s,4), 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,4), number, 1)
                end* power(16, len(left(@s,4)) - number) data1
         from (select number from master.dbo.spt_values where type='p')K
         where number <= len(left(@s,4))
     ) L
    declare @k2 int,@j int
              select @k2=@key,@j=1
    while @k2>0
              begin
      set @j=(@i*@j)%(@p*@q)
      set @k2=@k2-1
    end
    set @crypt=@crypt+char(@j)
    set @s=stuff(@s,1,4,'')
       end
  return @crypt
end
 
三、在SQL SERVER中的使用
--【测试】
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('RSA',63,47,59))
select * from tb
--运行结果:
/*
id          col
----------- ------------
1           069505EE02F3
*/
select id,col=dbo.f_RSADecry(col,847,47,59) from tb
--运行结果:
/*
id          col
----------- -----------
1           RSA
*/
 
四、目前版本函数的缺点
1、目前只能对ascii符号进行加密,对unicode尚不支持。
2、在选取的素数都比较小,所以密钥空间比较小,而实际应用中选取的素数都会非常的大,不容易破解。但是对于一些基础的加密还能够使用。
3、如果一次加密觉得安全性不够的话,可以进行重复加密(即进行多次加密),两次的密钥最好不相同。
例如:insert into tb values(dbo.f_RSAEncry(dbo.f_RSAEncry('RSA',63,47,59),23,11,17))
那么解密的时候,按照加密的逆序进行解密:
select id,col=dbo.f_RSADecry(dbo.f_RSADecry(col,7,11,17),847,47,59)
from tb
4、如果选取的数字比较大,那么在进行加密的时候,生成的进制密文最好使用个字节或者更多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: