一、简介
1、AES(Advanced Encryption Standard,高级加密标准)
功能
AES 是一种对称加密算法,用于对数据进行加密和解密(加密和解密使用相同密钥)。它是目前全球广泛采用的标准加密算法,替代了安全性不足的 DES 算法。
核心特点
分组加密:AES 处理固定长度的 “数据块”(分组大小),标准分组大小为 128 位(16 字节),密钥长度可选择 128 位、192 位或 256 位(密钥越长,安全性越高,但加密速度略慢)。
安全性高:至今未被发现有效的攻击方法,能抵抗绝大多数常见密码分析。
效率高:适合硬件和软件实现,在各种设备(从嵌入式系统到大型服务器)上都能高效运行。
作用
AES 是加密的 “核心引擎”,定义了如何对单个 128 位数据块进行混淆、置换和迭代运算,生成加密后的密文块。
2、ECB(Electronic Codebook,电子密码本模式)
功能
ECB 是 AES 等分组加密算法的工作模式,定义了如何处理超过单个分组长度的数据(即多块数据的加密方式)。
核心特点
独立加密:将明文分成多个 128 位的块,每个块独立用 AES 加密,互不影响。
确定性:相同的明文块会生成相同的密文块(因为加密方式完全独立)。
缺点(安全性问题)
由于相同明文块加密后结果相同,攻击者可通过分析密文块的重复模式,推测明文结构(例如图片加密后,轮廓可能依然可见)。
不提供完整性校验,无法检测数据是否被篡改。
适用场景
仅适用于加密极短的数据(如单个密钥),不适合加密长文本、文件等,实际应用中很少使用(推荐使用 CBC、GCM 等更安全的模式)。
3、加密方法
/// 加密方法:AES-ECB模式(零填充)
/// @param plaintext 明文(字符串)
/// @param key 密钥(16/24/32字节字符串,对应128/192/256位)
/// @return 加密后十六进制字符串
/// w ##class(NTSC.Test.Test1).Encrypt("<REQ><DEPT_ID>-1</DEPT_ID><HOS_ID>12622800439051277W</HOS_ID></REQ>","zmd_scan_pay_+++")
ClassMethod Encrypt(plaintext As %String, key As %String) As %String [ Language = objectscript ]
{
// 检查密钥长度
Set keyLen = $Length(key)
If (keyLen '= 16) && (keyLen '= 24) && (keyLen '= 32) {
Return "密钥长度必须为16、24或32字节"
}
// 明文转UTF-8二进制
Set plainBin = $ZCONVERT(plaintext, "O", "UTF8")
// 零填充(拆分循环为多行,避免紧凑语法)
Set padLen = (16 - ($Length(plainBin) # 16)) # 16
If padLen > 0 {
Set i = 1
For {
If i > padLen { Quit }
Set plainBin = plainBin _ $Char(0)
Set i = i + 1
}
}
// AES-ECB加密
Set keyBits = keyLen * 8
Set cipherBin = ##class(%SYSTEM.Encryption).AESEncode(plainBin, key)
q:(cipherBin="") "加密失败:未生成密文"
// 二进制转十六进制(拆分循环为多行)
Set hexStr = ""
Set cipherLen = $Length(cipherBin)
Set i = 1
For {
If i > cipherLen { Quit }
Set byte = $Ascii($Extract(cipherBin, i))
If byte < 16 {
Set hex = "0" _ $ZHEX(byte)
} Else {
Set hex = $ZHEX(byte)
}
Set hexStr = hexStr _ hex
Set i = i + 1
}
q hexStr
}运行效果:

4、对应解密方法
/// 解密方法:AES-ECB模式(零填充)
/// @param cipherHex 加密后的十六进制字符串
/// @param key 密钥(同加密密钥)
/// @return 解密后的明文(去除末尾零填充)
/// w ##class(NTSC.Test.Test1).Decrypt("8291FFCFBFE05D267C3BB6D5E92A6AE10B1364D30E7744FCC3C7F914F676A8D84F84A34831DC8AC4FD002945E7AFC7B4EB33EE24CB407D42E799366AF9BE70F624D7EA9743724D6875944EAC9E362E4C","zmd_scan_pay_++/")
ClassMethod Decrypt(cipherHex As %String, key As %String) As %String [ Language = objectscript ]
{
// 检查密钥长度
Set keyLen = $Length(key)
If (keyLen '= 16) && (keyLen '= 24) && (keyLen '= 32) q "密钥长度必须为16、24或32字节"
// 检查密文长度为偶数
If ($Length(cipherHex) # 2) q "密文格式错误:长度必须为偶数"
// 手动十六进制转二进制
Set cipherBin = "", i = 1, hexMap = "0123456789ABCDEF"
For {
If i > $Length(cipherHex) Quit
Set c1 = $Extract(cipherHex, i)
Set p1 = $Locate(hexMap, $ZCONVERT(c1, "U"))
If p1 = 0 Return "密文错误:非法字符 '"_c1_"'"
Set val = (p1 - 1) * 16
Set c2 = $Extract(cipherHex, i + 1)
Set p2 = $Locate(hexMap, $ZCONVERT(c2, "U"))
If p2 = 0 Return "密文错误:非法字符 '"_c2_"'"
Set val = val + (p2 - 1)
// 拼接二进制字符
Set cipherBin = cipherBin _ $Char(val)
Set i = i + 2
}
// 解密并处理填充
Set plainBin = ##class(%SYSTEM.Encryption).AESDecode(cipherBin, key)
If plainBin = "" q "解密失败"
// 去除尾部零填充
Set i = $Length(plainBin)
// 替换不兼容的 For 循环写法
For {
If i < 1 {
Quit
}
If $Ascii($Extract(plainBin, i)) '= 0 {
Quit
}
Set i = i - 1
}
i plainBin'["REQ" q "解密失败!key不合法"
Set str = $ZCONVERT($Extract(plainBin, 1, i), "I", "UTF8")
q str
}运行效果:

5,、无填充补零方式解密
/// 解密方法:AES-ECB模式(PKCS#7填充)
/// 用于解析密文 JYNO1FsGBWO2ULrhbDcZ8iQpecoWuWl5P23VR+GwyA++/ciomaRogQJt6QDYk+D9bagIjtPh4ajAZmXCVmH6tufw3SNMp6LK1lGgVLiZjxc=
/// @param cipherBase64 加密后的Base64字符串
/// @param key 密钥(2fMVbe6Nvtyy6CsV)
/// @return 解密后的明文XML
/// w ##class(NTSC.Test.Test1).DecryptAES("JYNO1FsGBWO2ULrhbDcZ8iQpecoWuWl5P23VR+GwyA++/ciomaRogQJt6QDYk+D9bagIjtPh4ajAZmXCVmH6tufw3SNMp6LK1lGgVLiZjxc=","2fMVbe6Nvtyy6CsV")
ClassMethod DecryptAES(cipherBase64 As %String, key As %String) As %String [ Language = objectscript ]
{
// 检查密钥长度(AES-128需要16字节密钥)
Set keyLen = $Length(key)
If keyLen '= 16 d q "密钥长度错误,需要16字节"
// 1. Base64解码密文
Set cipherBin = ##class(%SYSTEM.Encryption).Base64Decode(cipherBase64)
If cipherBin = "" d q "Base64解码失败,密文格式错误"
// 2. 使用AES-ECB模式解密(IRIS默认使用PKCS#7填充)
Set plainBin = ##class(%SYSTEM.Encryption).AESDecode(cipherBin, key)
If plainBin = "" d q "AES解密失败,密钥或密文错误"
// 3. 将二进制转换为UTF-8字符串
Set plainText = $ZCONVERT(plainBin, "I", "UTF8")
If plainText = "" d q "字符串编码转换失败"
q plainText
}
评论