ASP/VBScript巧用CAPICOM实现随机数、Hash(MD5/SHA1)和Base64编解码
提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!
其实很早就想介绍这个Windows内置的ActiveX/COM组件,我 前面有一篇文章 介绍如何借用.NET Framework实现类似于SHA1和MD5哈希算法,如果大家对此感兴趣也可以看一下。
好,言归正传,今天我要介绍的是如何让VBScript利用Windows原生自带的CAPICOM组件来实现随机数、Hash(MD5/SHA1)以及Base64算法,当然在VBScript的世界里,这些算法都有免组件的纯代码实现,当然使用组件的好处就是代码简洁和运行效率的提高,所以我们不妨尝试一下。 既然今天介绍的主角是CAPICOM,当然我们要推荐参考 微软的MSDN文档 ,大家不妨先大致浏览一番,可能大家很快发现下面这段提示:
CAPICOM is a 32-bit only component that is available for use in the following operating systems: Windows Server 2008, Windows Vista and Windows XP. Instead, use the .NET Framework to implement security features.
由此可见非常遗憾的是CAPICOM仅仅是32位Windows XP、Windows Vista以及Windows 2008系统上才自带(对于64位系统可以参考文章 在64位系统中使用CAPICOM ),所以在包含CAPICOM特性代码部署到服务器上之前需要测试一下当前系统是否支持,如果不支持只有考虑.NET或者原生代码的实现了。
CAPICOM有很多对象(Objects),这里我也不一一介绍,主要关注的是
CAPICOM.Utilities
和
CAPICOM.HashedData
。本文也是通过这两个对象实现所需要的算法功能的。
CAPICOM.Utilities
实现随机数
Function GetRandom()
Dim objCapiCom
Set objCapiCom = CreateObject("CAPICOM.Utilities.1")
GetRandom = objCapiCom.GetRandom(32, -1)
Set objCapiCom = Nothing
End Function
可能大家要问为什么VBScript语言自带随机数功能,我们还需要使用CAPICOM来生成随机数,实际上我们通过脚本语言生成的随机数是伪随机数,当然这些伪随机数可以应用于一些要求不高的场合,伪随机数是通过算法和数学运算生成的模拟随机数,对于加密这类应用来说这种随机数是不安全的,而真正的随机数是通过硬件噪音生成的,比如在Linux及其他类Unix系统下,可以通过
/dev/random
或者
/dev/urandom
获得,因为这里我们实现的系统是Windows,所以可以变通的通过CAPICOM获取。
大家可能注意到上述代码
objCapiCom.GetRandom(32, -1)
中的第二个参数
-1
,微软给出的定义如下:
Const CAPICOM_ENCODE_ANY = -1
Const CAPICOM_ENCODE_BASE64 = 0
Const CAPICOM_ENCODE_BINARY = 1
关于这些常量定义的实际含义可以 参考MSDN文档 。
实现Base64编码和解码
在文章 《Base64 の処理》 有很好的例子。我简写如下:
Class Base64
Private objCapiCom
Private Sub Class_Initialize()
Set objCapiCom = CreateObject("CAPICOM.Utilities")
End Sub
Private Sub Class_Terminate()
Set objCapiCom = Nothing
End Sub
Public Function encode(str)
encode = objCapiCom.Base64Encode(str)
End Function
Public Function decode(str)
decode = objCapiCom.Base64Decode(str)
End Function
End Class
' Set objBase64 = New Base64
' MsgBox objBase64.decode(objBase64.encode("Hello World"))
' Set objBase64 = Nothing
原文还介绍了如何对而进制文件进行Base64编解码,用到了
ByteArrayToBinaryString
和
BinaryStringToByteArray
方法:
<!--METADATA TYPE="TypeLib" UUID="{EF53050B-882E-4776-B643-EDA472E8E3F2}" -->
<%
Call Response.AddHeader( "Content-Type", "text/html; Charset=shift_jis" )
Set Stream = Server.CreateObject("ADODB.Stream")
Set CAPIUtil = Server.CreateObject( "CAPICOM.Utilities" )
Stream.Open
Stream.Type = adTypeBinary
Stream.LoadFromFile Server.MapPath( "sample.jpg" )
strFile = CAPIUtil.ByteArrayToBinaryString( Stream.Read )
Stream.Close
strEncoded = CAPIUtil.Base64Encode( strFile )
' バイナリデータを通常文字列として処理
strDecoded = CAPIUtil.Base64Decode( strEncoded )
strFile2 = CAPIUtil.BinaryStringToByteArray( strDecoded )
Stream.Open
Stream.Type = adTypeBinary
Stream.Write strFile2
Stream.SaveToFile Server.MapPath("sample2.jpg"), _
adSaveCreateOverWrite
Stream.Close
%>
关于Base64的其他实现办法,可以参考我前面的一篇文章 《Base24、Base64编码的几种程序实现》 。
CAPICOM.HashedData
实现常用的哈希函数
这里主要参考了
《CAPICOM.dll을 이용한 Classic ASP(VBScript)에서 MD5 암호화 적용하기》
,用到了一个Unicode字符串转换为Byte字符串的函数
UStr2Bstr
,当然为了便于理解,我还
找到了
逆函数
BStr2UStr
:
Function BStr2UStr(BStr)
'Byte string to Unicode string conversion
Dim lngLoop
BStr2UStr = ""
For lngLoop = 1 to LenB(BStr)
BStr2UStr = BStr2UStr & Chr(AscB(MidB(BStr,lngLoop,1)))
Next
End Function
Function UStr2Bstr(UStr)
'Unicode string to Byte string conversion
Dim lngLoop
Dim strChar
UStr2Bstr = ""
For lngLoop = 1 to Len(UStr)
strChar = Mid(UStr, lngLoop, 1)
UStr2Bstr = UStr2Bstr & ChrB(AscB(strChar))
Next
End Function
比如常见的MD5实现代码如下:
Function MD5(str)
Dim objCapiCom
Set objCapiCom = CreateObject("CAPICOM.HashedData")
objCapiCom.Algorithm = 3
objCapiCom.Hash UStr2Bstr(str)
MD5 = objCapiCom.Value
Set objCapiCom = Nothing
End Function
' MsgBox MD5("123456")
同样的大家也许注意到了
objCapiCom.Algorithm
,属性3指明了所使用的哈西算法,主要的算法定义有以下列表,这些同样可以
从MSDN中找到
:
Const CAPICOM_HASH_ALGORITHM_SHA1 = 0
Const CAPICOM_HASH_ALGORITHM_MD2 = 1
Const CAPICOM_HASH_ALGORITHM_MD4 = 2
Const CAPICOM_HASH_ALGORITHM_MD5 = 3
Const CAPICOM_HASH_ALGORITHM_SHA256 = 4
Const CAPICOM_HASH_ALGORITHM_SHA384 = 5
Const CAPICOM_HASH_ALGORITHM_SHA512 = 6
同Base64编码解码一样,哈希函数也可以对二进制数据进行操作,具体做法是直接使用
Hash
方法分块哈希二进制数据,具体可以参考
Demon为我们提供的代码
:
Function md5_file(filename, raw_output)
Dim HashedData, Utility, Stream
Set HashedData = CreateObject("CAPICOM.HashedData")
Set Utility = CreateObject("CAPICOM.Utilities")
Set Stream = CreateObject("ADODB.Stream")
HashedData.Algorithm = 3
Stream.Type = 1
Stream.Open
Stream.LoadFromFile filename
Do Until Stream.EOS
HashedData.Hash Stream.Read(1024)
Loop
If raw_output Then
md5_file = Utility.HexToBinary(HashedData.Value)
Else
md5_file = HashedData.Value
End If
End Function