就业数据资源平台
当前位置:首页 > 数据库技术
在SQLSERVER中实现RSA加密算法

/*本次修改增加了unicode的支持,但是加密后依然显示为16进制数据,因为进行RSA加密后所得到的unicode编码是无法显示的,所以密文依然采用16进制数据显示。
  需要特别注意:如果要对中文进行加密,那么所选取的两个素数要比较大,两个素数的成绩最好要大于65536,即大于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
  --判断两个数是否互素
  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
  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值,然后进行加密,产生3个字节的16位数据*/
  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
  【测试】
  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

就业数据资源平台