博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(转)Oracle、SQL Server下MD5+Base64密码加密实现
阅读量:4982 次
发布时间:2019-06-12

本文共 4850 字,大约阅读时间需要 16 分钟。

转自:

写在前面:

MD5和Base64的函数实现并不是本文的重点,重点是在实现过程中遇到的字符集转换的麻烦

 

最近由于工作需要,要将BIEE与公司现有的ERP系统做集成,使用外部表的方式。

现有系统基于.Net平台,数据库为SQL Server 2008 R2,用户密码采用先算MD5在转Base64的方式存于数据库中。

代码逻辑如下

  1. byte[] byteString = null;  
  2. MD5 md5 = MD5.Create();  
  3. byteString = md5.ComputeHash(Encoding.Unicode.GetBytes(Str));  
  4. md5.Clear();  
  5. string NewStr = Convert.ToBase64String(byteString);  
byte[] byteString = null; MD5 md5 = MD5.Create(); byteString = md5.ComputeHash(Encoding.Unicode.GetBytes(Str)); md5.Clear(); string NewStr = Convert.ToBase64String(byteString);

Encoding.Unicode.GetBytes(Str)这句为最关键的部分,其作用是把Str转换成了Unicode字节数组,正是这里给整个工作带来了困难!因为本人不懂C#,所以不知道C#里的Unicode是使用的UTF16LE(小头),而非常见的UTF16BE(大头)。SQL Server 里的Nvachr应该也是采用的是UTF16LE,而Oracle里的NVarchar2则是采用的UTF16BE,正是因为这点导致MD5出来的值串不一致!

 

对于qaz123三者的输出值分别为:

 

Oracle:

  1. SQL> select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5('qaz123'))) from dual;  
  2.    
  3. UTL_RAW.CAST_TO_VARCHAR2(UTL_E  
  4. --------------------------------------------------------------------------------   
  5. NPhcqA7DU9MFK4otOXOgxQ==  
SQL> select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5('qaz123'))) from dual; UTL_RAW.CAST_TO_VARCHAR2(UTL_E -------------------------------------------------------------------------------- NPhcqA7DU9MFK4otOXOgxQ==

SQL Server:

  1. select dbo.f_ToBase64(hashbytes('MD5',convert(NVARCHAR,'qaz123')))   
  2.   
  3. LwUQYUuskyOhnZXD8WUh8Q==  
select dbo.f_ToBase64(hashbytes('MD5',convert(NVARCHAR,'qaz123'))) LwUQYUuskyOhnZXD8WUh8Q==

 

C#:

LwUQYUuskyOhnZXD8WUh8Q==

Oracle的字符集为AL32UTF8、SQL Server的字符集为GBK

由于qaz123在UTF8和UTF16下的编码都一样所以就算我在Oracle下把qaz123转换成UTF16,其最终结果还是不是预期的,如下:

 

  1. select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(N'qaz123'))) from dual;  
  2.    
  3. UTL_RAW.CAST_TO_VARCHAR2(UTL_E  
  4. --------------------------------------------------------------------------------   
  5. NPhcqA7DU9MFK4otOXOgxQ==  
select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(N'qaz123'))) from dual; UTL_RAW.CAST_TO_VARCHAR2(UTL_E -------------------------------------------------------------------------------- NPhcqA7DU9MFK4otOXOgxQ==

直到我把其转为UTF16LE,结果才和C#中的一样

注:Oracle中的UTF16默认为UTF16BE

  1. select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(convert('qaz123','AL16UTF16LE')))) from dual;  
  2.    
  3. UTL_RAW.CAST_TO_VARCHAR2(UTL_E  
  4. --------------------------------------------------------------------------------   
  5. LwUQYUuskyOhnZXD8WUh8Q==  
select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(convert('qaz123','AL16UTF16LE')))) from dual; UTL_RAW.CAST_TO_VARCHAR2(UTL_E -------------------------------------------------------------------------------- LwUQYUuskyOhnZXD8WUh8Q==

 

至此,搞定!

 

为了验证上面我的说法,可以看一下Oracle中,qaz123在不同编码下的代码点

  1. SQL> select 'UTF8',dump('qaz123'from dual  
  2.   2  union all  
  3.   3  select 'UTF16BE',dump(N'qaz123'from dual  
  4.   4  union all  
  5.   5  select 'UTF16LE', dump(convert('qaz123','AL16UTF16LE')) from dual  
  6.   6  ;  
  7.    
  8. 'UTF8'  DUMP('QAZ123')  
  9. ------- ----------------------------------------------   
  10. UTF8    Typ=96 Len=6: 113,97,122,49,50,51  
  11. UTF16BE Typ=96 Len=12: 0,113,0,97,0,122,0,49,0,50,0,51  
  12. UTF16LE Typ=1 Len=12: 113,0,97,0,122,0,49,0,50,0,51,0  
SQL> select 'UTF8',dump('qaz123') from dual 2 union all 3 select 'UTF16BE',dump(N'qaz123') from dual 4 union all 5 select 'UTF16LE', dump(convert('qaz123','AL16UTF16LE')) from dual 6 ; 'UTF8' DUMP('QAZ123') ------- ---------------------------------------------- UTF8 Typ=96 Len=6: 113,97,122,49,50,51 UTF16BE Typ=96 Len=12: 0,113,0,97,0,122,0,49,0,50,0,51 UTF16LE Typ=1 Len=12: 113,0,97,0,122,0,49,0,50,0,51,0
 

 

 

 

下面给出Oracle和SQL Server下的相关函数实现代码

Oracle:

创建MD5函数

  1. CREATE OR REPLACE FUNCTION GET_MD5  
  2. ( p_str in varchar2)  
  3. RETURN varchar2 IS  
  4. BEGIN   
  5. RETURN Utl_Raw.Cast_To_Raw(DBMS_OBFUSCATION_TOOLKIT.MD5(input_string => lower(P_Str)));  
  6. END;  
CREATE OR REPLACE FUNCTION GET_MD5 ( p_str in varchar2) RETURN varchar2 IS BEGIN RETURN Utl_Raw.Cast_To_Raw(DBMS_OBFUSCATION_TOOLKIT.MD5(input_string => lower(P_Str))); END;

调用转换成Base64

  1. select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(convert('qaz123','AL16UTF16LE')))) from dual;  
select utl_raw.cast_to_varchar2(utl_encode.base64_encode(GET_MD5(convert('qaz123','AL16UTF16LE')))) from dual;

 

SQL Server:

从SQL Server 2005开始,其自带了hashbytes函数用于生成字符串的Hash值,所以MD5这一步就可以直接采用现有的函数了。

至于转换成Base64,系统并没有提供相关函数,不过我们有变通的方法,原理是SQL Server使用FOR XML 生成xml 实例时,binary 数据使用base64 编码

函数如下:

  1. create function f_ToBase64  
  2. (@bin varbinary(max))  
  3. returns varchar(max)  
  4. as begin  
  5. return cast(N'' as xml).value('xs:base64Binary(xs:hexBinary(sql:variable("@bin")))''varchar(max)')  
  6. end  
create function f_ToBase64 (@bin varbinary(max)) returns varchar(max) as begin return cast(N'' as xml).value('xs:base64Binary(xs:hexBinary(sql:variable("@bin")))', 'varchar(max)') end

最终调用:

  1. select dbo.f_ToBase64(hashbytes('MD5',convert(NVARCHAR,'qaz123')))   
select dbo.f_ToBase64(hashbytes('MD5',convert(NVARCHAR,'qaz123')))

特别需要注意红色部分,这是为了和C#代码逻辑保持一致。

转载于:https://www.cnblogs.com/spymaster/archive/2011/09/18/2180346.html

你可能感兴趣的文章
炮兵阵地
查看>>
BZOJ 1863: [Zjoi2006]trouble 皇帝的烦恼( 二分答案 )
查看>>
try catch
查看>>
slf4j
查看>>
Orcal 给表增加一个自增的ID
查看>>
C#语言和SQL Server数据库技术_程序数据集散地:数据库
查看>>
ES6学习之变量的解构赋值
查看>>
PHP 生成图片缩略图函数
查看>>
Boost Bimap示例
查看>>
ESLint 使用入门
查看>>
流水作业调度
查看>>
涨姿势系列之——内核环境下内存映射函数
查看>>
遍历数组批量更新数组里元素的某一项属性
查看>>
github 收藏项目的方法
查看>>
九的余数
查看>>
北京师范大学第十五届ACM决赛-重现赛K Keep In Line ( 字符串模拟实现)
查看>>
(转)C# — WinForm 消息框的使用
查看>>
时间管理(转)
查看>>
Future FutrueTask Callable类源码说明以及原理使用
查看>>
flask 外键关系和多对多查询
查看>>