文章
· 九月 14, 2022 阅读大约需 3 分钟

HEALTHSHARE2018版如何实现AES(CBC)的HEX输出,并可以实现加密和解密

 在AES的加密过程中,存在HEX和Base64的输出,目前在HEALTHSHARE自带有Base64的加解密规则,现在针对HEX的加解密进行对应的处理,实现和网上ASE加解密工具进行互相加解密。
在Ensemble的AES的CBC加密主要用到的是这俩个方法
$system.Encryption.AESCBCManagedKeyEncrypt(Plaintext,KeyID)
Plaintext是需要加密的字符串,需要进行$ZCONVERT(字符串,"O","UTF8")转换
KeyID是密钥的ID。
或者是
$SYSTEM.Encryption.AESCBCEncrypt(text,key,IV)
text是需要加密的字符串,需要进行$ZCONVERT(text,"O","UTF8")转换
Key 是密钥 键的长度必须为16、24或32个字符
IV  是偏移量 如果存在此参数,则必须为16个字符长。

第一个方法是在本地生成对应的密钥,暂时还不能和网站上的进行互相加解密的处理。
目前主要是针对第二个方法
$SYSTEM.Encryption.AESCBCEncrypt(text,key,IV)

下面附上对应代码和说明:
Hex编码      原理就是将原来8位的二进制打断,分成两个4位的,并且在前面加上4个零,
            进行补位这样一个8位二进制字节就变成了2个8位的二进制字节,
            在将新得到的2个二进制字符进行16位进制转换,具体编码规则可以百度。
Set inputString = $SYSTEM.Encryption.AESCBCEncrypt($ZCVT("测试","O","UTF8"),"1234567891234567","1234567891234567")
Set hex = ""
For iStr=1:1:$Length(inputString) {
    Set hex1 = $ZHex($Ascii(inputString,iStr))
    If $Length(hex1)=1 set hex1="0"_hex1
    Set hex = hex _ hex1
}
W $ZCVT(hex,"L")
输出的密文为:47c692a4a51f9dae3f8040c4a1a4899e
代码说明:
$Ascii将字符转成十进制编码 $ZHex转成16进制编码。
If $Length(hex1)=1 set hex1="0"_hex1 含义就是本身Hex的最小单位是一个字节,
一个字节是8位比特显示,高四位和低四位可以对应成16位,并按照规则进行补位,
例如字符DC1 (device control 1),ASCII码对应的是十进制的17,
二进制编码是0001 0001,补位之后就是 00000001 00000001就是对应16进制的11,
高四位是1,低四位是1,如果是0000 0001的话,补位之后是00000000 00000001,
对应的内容位01,代码转出来的时候0会舍弃,所以转出来16进制是一位数的话前面需要补0。

对应的解密为:
Set aa = $ZCVT(hex,"L")
Set test1=""
for i=1:1:$Length(aa)/2{
    Set test = $CHAR($system.Util.HexToDecimal($EXTRACT(aa,2*i-1,2*i)))
    Set test1 = test1_test
}
Set OutputString = $SYSTEM.Encryption.AESCBCDecrypt(test1,"1234567891234567","1234567891234567")
W $ZCVT(OutputString,"I","UTF8")
输出为:测试
解码思路,在AES加密的时候,把中文经过utf-8编码,中文对对应成一个一个的字节显示,
那加过密的密文其实也是以字节为单位。按照上面的解密规则,一个字节对应的8位bit的二进制码
通过补位并转成对应的16进制就是俩位,所以切割hex密文的时候
,按照俩位进行切割,转回到10进制,在进行$char显示为字符,在拼接在一起,在用utf-8解码成对应中文。

在网站上面测试:https://tool.lmeee.com/jiami/aes 调整为CDC加密模式,填充为pkcs5padding 输出为HEX
对应测试的加密密文是:47c692a4a51f9dae3f8040c4a1a4899e
对应密文的解密是:测试

附图说明:

 

讨论 (8)5
登录或注册以继续

十分专业的分享,在此我忍不住分享一下base64的方式:

    s plaintext ="你好,世界!"

    w "加密前:"_plaintext,!

    #; 加密

    Set text=$ZCONVERT(plaintext,"O","UTF8")

    Set text=$SYSTEM.Encryption.AESCBCEncrypt(text,"1234567891234567","1234567891234567")

    Set ciphertext=$SYSTEM.Encryption.Base64Encode(text)

    w "加密后:"_ciphertext,!

    #; 解密

    Set text=$SYSTEM.Encryption.Base64Decode(ciphertext)

    Set text=$SYSTEM.Encryption.AESCBCDecrypt(text,"1234567891234567","1234567891234567")

    Set plaintext=$ZCONVERT(text,"I","UTF8")

    w "解密后:"_plaintext,!

你好,因为AES的加密密钥必须是16,24和32字节的,java在处理这种密钥不足16位的时候,应该是会有补0的操作,可以先确认一下java的这种密钥处理机制,如果是补0的话,平台也做对应的处理,可以试试看效果