一、背景

因为历史原因,手里有很多ASP写的程序需要维护,而微软已经从2000年左右的时候就停止了ASP相关的技术支持,遗留下来的ASP项目无法使用更加先进的技术而处境尴尬:放弃重写成本太大,继续使用又因为对新技术不支持而面临困境。比如最近,因为项目需要对客户手机号进行脱敏处理,计划使用AES算法对用户手机号进行加密存储,使用的时候取出并对其解密,但是ASP自身并不支持AES算法。

二、解决

我们知道在.net中有非常丰富的库可以使用,比如加密算法相关的 System.Security.Cryptography 库,在这里,我们就可以使用.net提供的这些丰富的库来解决这个问题,下面的是在github上发现的一个ASP中使用.net类库来实现AES-256-CBC加密解密的方法,下面是我整理出来的步骤:

1.实例化相关的库

Set utf8 = CreateObject("System.Text.UTF8Encoding")
Set b64Enc = CreateObject("System.Security.Cryptography.ToBase64Transform")
Set b64Dec = CreateObject("System.Security.Cryptography.FromBase64Transform")
Set mac = CreateObject("System.Security.Cryptography.HMACSHA256")
Set aes = CreateObject("System.Security.Cryptography.RijndaelManaged")
Set mem = CreateObject("System.IO.MemoryStream")

2.核心方法

'加密方法
Function Encrypt(plaintext, aesKey, macKey)
    aes.GenerateIV()
    aesKeyBytes = B64Decode(aesKey)
    macKeyBytes = B64Decode(macKey)
    Set aesEnc = aes.CreateEncryptor_2((aesKeyBytes), aes.IV)
    plainBytes = utf8.GetBytes_4(plaintext)
    cipherBytes = aesEnc.TransformFinalBlock((plainBytes), 0, LenB(plainBytes))
    macBytes = ComputeMAC(ConcatBytes(aes.IV, cipherBytes), macKeyBytes)
    Encrypt = B64Encode(macBytes) & ":" & B64Encode(aes.IV) & ":" & _
              B64Encode(cipherBytes)
End Function

'解密方法
Function Decrypt(macIVCiphertext, aesKey, macKey)
    aesKeyBytes = B64Decode(aesKey)
    macKeyBytes = B64Decode(macKey)
    tokens = Split(macIVCiphertext, ":")
    macBytes = B64Decode(tokens(0))
    ivBytes = B64Decode(tokens(1))
    cipherBytes = B64Decode(tokens(2))
    macActual = ComputeMAC(ConcatBytes(ivBytes, cipherBytes), macKeyBytes)
    If Not EqualBytes(macBytes, macActual) Then
        Err.Raise vbObjectError + 1000, "Decrypt()", "Bad MAC"
    End If
    Set aesDec = aes.CreateDecryptor_2((aesKeyBytes), (ivBytes))
    plainBytes = aesDec.TransformFinalBlock((cipherBytes), 0, LenB(cipherBytes))
    Decrypt = utf8.GetString((plainBytes))
End Function

3.辅助方法

'取两个数字中最小的
Function Min(a, b)
    Min = a
    If b < a Then Min = b
End Function

'byte转base64
Function B64Encode(bytes)
    blockSize = b64Enc.InputBlockSize
    For offset = 0 To LenB(bytes) - 1 Step blockSize
        length = Min(blockSize, LenB(bytes) - offset)
        b64Block = b64Enc.TransformFinalBlock((bytes), offset, length)
        result = result & utf8.GetString((b64Block))
    Next
    B64Encode = result
End Function

'base64转byte
Function B64Decode(b64Str)
    bytes = utf8.GetBytes_4(b64Str)
    B64Decode = b64Dec.TransformFinalBlock((bytes), 0, LenB(bytes))
End Function

'连接两个byte数组
Function ConcatBytes(a, b)
    mem.SetLength(0)
    mem.Write (a), 0, LenB(a)
    mem.Write (b), 0, LenB(b)
    ConcatBytes = mem.ToArray()
End Function

'比较两个byte数组是否相等
Function EqualBytes(a, b)
    EqualBytes = False
    If LenB(a) <> LenB(b) Then Exit Function
    diff = 0
    For i = 1 to LenB(a)
        diff = diff Or (AscB(MidB(a, i, 1)) Xor AscB(MidB(b, i, 1)))
    Next
    EqualBytes = Not diff
End Function

'使用HMAC-SHA-256计算消息身份验证代码
Function ComputeMAC(msgBytes, keyBytes)
    mac.Key = keyBytes
    ComputeMAC = mac.ComputeHash_2((msgBytes))
End Function

4.使用方法

Dim plaintext, aesKey, macKey,encrypt_res
plaintext="bigger.ee"  '加密原文
aesKey="12345678901234567890123456789012"  key1
macKey="aaaaaaaaaabbbbbbbbbbccccccccccdd"  key2
encrypt_res=Encrypt(plaintext, aesKey, macKey)  '加密

decrypt_res=Decrypt(encrypt_res,aesKey, macKey)  '解密

三、修改使用ECB模式

1.设置ECB模式

在实例化用到的几个库之后,设置加密的模式:

aes.Mode=2

2.修改加密和解密的方法

把向量相关的方法去掉

'加密
Function Encrypt(plaintext, aesKey)
    aesKeyBytes = utf8.GetBytes_4(aesKey)
    aes.Key = aesKeyBytes
    
    Set aesEnc = aes.CreateEncryptor()
    
    plainBytes = utf8.GetBytes_4(plaintext)
    cipherBytes = aesEnc.TransformFinalBlock((plainBytes), 0, LenB(plainBytes))
    
    Encrypt = B64Encode(cipherBytes)    
End Function

'解密
Function Decrypt(macIVCiphertext, aesKey)
    aesKeyBytes = B64Decode(aesKey)
    ivBytes = B64Decode(aesKey)
    cipherBytes = B64Decode(macIVCiphertext)    
    If Not EqualBytes(macBytes, macActual) Then
        Err.Raise vbObjectError + 1000, "Decrypt()", "Bad MAC"
    End If
    Set aesDec = aes.CreateDecryptor()
    plainBytes = aesDec.TransformFinalBlock((cipherBytes), 0, LenB(cipherBytes))
    Decrypt = utf8.GetString((plainBytes))
End Function

四、源码

下面给出未修改版本的源码,可供下载

1.原作者github

下载地址:https://github.com/susam/aes.vbs

2.本站下载

下载地址:aes.vbs-master.zip

感谢 @Susam 提供的方法。

以上。

Last modification:April 6, 2020
如果觉得我的文章对你有用,请随意赞赏