• 在SQL SERVER中实现RSA加解密函数(第一版)


    /***************************************************  

        作者: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

      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、如果选取的数字比较大,那么在进行加密的时候,生成的进制密文最好使用个字节或者更多。

  • 相关阅读:
    基于发布/订阅模型的应用程序的主循环设计
    C++使用继承时子对象的内存布局
    安装 CentOS 后的系统配置及软件安装备忘
    环形无锁队列
    并发编程基础
    线程池实现
    Git远程操作
    Unix权限管理
    jquery中,某些写法后来更新导致版本不支持的替代方法
    js相关
  • 原文地址:https://www.cnblogs.com/accumulater/p/6244729.html
Copyright © 2020-2023  润新知