HISUI
Cache中常用方法
2021年05月19日 12时58分

BCrypt代码约定

代码 算法 类型
0a SHA256 哈希
0b AES 对称加密
1a SM3 哈希
1b SM4 对称加密

一. 32位MD5加密方法

 // @param {String|Stream} Val 需要加密的内容
 // Stream入参在Cache2016下支持
 // @param {String} CharSet 编码 如:"UTF8"|"GB18030"
 // ##class(web.Util.Encryption).MD5HexStr(Val,CharSet)
 >W ##class(web.Util.Encryption).MD5HexStr("1")
 C4CA4238A0B923820DCC509A6F75849B
 >W ##class(web.Util.Encryption).MD5HexStr("我","UTF8")
 16815254531798DC21EE979D1D9C6675

二. 汉字转Uncode

Set Val = "我"
Set Val = $zcvt(Val,"O","URL")  // %u6211
Set Val = $zcvt(Val,"I","URL")  // 我
//或
Set Val = $A(Val)    //得到十进制数值 25105
Set Val = $zhex(Val) //转成十六进制 6211

等价于javascript中的

escape("我"); //%u6211
unescape("%u6211") //我

三. URLEncode办法。可以使用%CSP.Page类中EscapeURL/UnescapeURL,

Set Val = "A?=#%& 我"
Set Val = $zcvt($zcvt(Val,"O","UTF8"),"O","URL")  // A%3F%3D%23%25%26%20%E6%88%91
Set Val = $zcvt($zcvt(Val,"I","URL"),"I","UTF8")

等价于javascripts中的

encodeURIComponent("A?=#%& 我");    // A%3F%3D%23%25%26%20%E6%88%91
decodeURIComponent("A%3F%3D%23%25%26%20%E6%88%91");

四. BASE64方法

// @param {String|Stream} Val 需要加密的内容
// @param {String} CharSet 编码默认UTF8。 如:"UTF8"|"GB18030"
// ##class(web.Util.Encryption).Base64Encode(Val,CharSet)
Set Val = ##class(web.Util.Encryption).Base64Encode("A我") //QeaIkQ==
Set Val = ##class(web.Util.Encryption).Base64Decode("QeaIkQ==","UTF8")
// -----------
// 如果入参或返回可能超过32000字符,可使用流作为入参
Set inStream = ##class(%GlobalCharacterStream).%New()
Set inStream.Write("abcd123456789......xxxxxxxxxxx")
// 入参是流时,返回也是流
Set outStream = ##class(web.Util.Encryption).Base64Encode(inStream,"UTF8")
do outStream.Rewind()   //指向流开头位置
while('outStream.AtEnd){ // 流未读完
    Set line = outStream.Read(12288)   // 读12288个字符
    Write line,!
}

五. 转码

A界面编码为GB2312,使用window.open(“b.csp?name=”+encodeURIComponent(‘AG009中国’)),b界面使用utf8编码,此时在b界面接收%request会乱码,需要转换

Set val = %request.Data("name",1)
Set val = $zcvt($zcvt(val,"O","GB18030"),"I","UTF8")

六. 国密(ligao实现)

1.有密钥的SM3方法

/// @Param {String} SrcStr  原消息字符串
/// @Param {String} Key  加密钥
/// @Param {String} OutType HEX|BASE64   转出成HEX或BASE64 默认HEX
W "hmacSM3 = ",##class(web.Util.Encryption).HmacSM3("myname我", "1234567887654321","HEX")
//输出 hmacSM3 = 4AE585EF3CF4CF298151835C6CFC587D272580D9EB0644A6CD6294060D6896A2

等价于java如下方法

public static String hmacHex(String sm3Key,String msg){
    if ("".equals(msg)) return "";
    if ("".equals(sm3Key)){return sm3Hex(msg);}  //调用sm3方法
    SM3Digest sm3Digest = new SM3Digest();
    KeyParameter keyParameter = new KeyParameter(sm3Key.getBytes(StandardCharsets.UTF_8));
    HMac hmac = new HMac(sm3Digest);
    hmac.init(keyParameter);
    hmac.update(msg.getBytes(StandardCharsets.UTF_8),0,msg.getBytes(StandardCharsets.UTF_8).length);
    byte[] result = new byte[hmac.getMacSize()];
    hmac.doFinal(result,0);
    return Convert.byteToHex(result);
}

2.无密钥的SM3方法

/// @Param {String} SrcStr  原消息字符串
/// @Param {String} Key  加密钥 传空时使用SM3加密
/// @Param {String} OutType HEX|BASE64   转出成HEX或BASE64 默认HEX
W "SM3 = ",##class(web.Util.Encryption).HmacSM3("123456789我是")
//输出 SM3 = B276BF7E2666AA571AA0C38B6C97FE586B5C4CCFE12E84170481DF447040D331
//等价于##class(web.Util.Encryption).SM3("123456789我是")

等价于以下java方法

public static String sm3Hex(byte[] srcData) {
    SM3Digest digest = new SM3Digest();
    digest.update(srcData, 0, srcData.length);
    byte[] hash = new byte[digest.getDigestSize()];
    digest.doFinal(hash, 0);
    return Convert.byteToHex(hash).toUpperCase();
}

3.使用SM4密钥加密

/// @Param {String} SrcStr  原消息字符串
/// @Param {String} Key  加密钥(长度16)
/// @Param {String} OutType HEX|BASE64   转出成HEX或BASE64 默认BASE64
W ##class(web.Util.Encryption).SM4Encode("myname我","1234567887654321","HEX")
//输出 50B3EBF9E5A6E1512B2EBF1EB130D844
// 或使用
w ##class(web.Util.SM4).Encrypt("d0702de652da45a9ae6086774c7659e4","abc","HEX","HEX")
// 输出D52CA2687BAFC57B6C75E5BFBA1B58E3
w ##class(web.Util.SM4).Encrypt("d0702de652da45a9ae6086774c7659e4","原文","HEX","HEX")
// 输出724A6C93385EF1097838681CFC12777F

4.使用SM4密钥解密

/// @Param {String} EncStr  密文串
/// @Param {String} Key  加密钥(长度16)
/// @Param {String} OutType HEX|BASE64   密文串格式是HEX或BASE64 默认BASE64
W ##class(web.Util.Encryption).SM4Decode("50B3EBF9E5A6E1512B2EBF1EB130D844","1234567887654321","HEX")
//输出 myname我

可以通过此网站对比加密结果
sm4encode

六. AES加密

1. AES/CBC/PKCS7Padding加密
/// @Param {String} SrcStr  原文
/// @Param {String} Key  加密钥(长度16)
/// @Param {String} VI  偏移量
/// @Param {String} 默认"ORIGIN/BASE64/UTF8" "key值类型ORIGIN|HEX|BASE64 / 返回值类型HEX|BASE64 / 原文的编码UTF8"
w ##class(web.Util.Encryption).AESCBCPKCS7Encode("myname我","1234567887654321","1234567890654321")
// 输出 0oyo6n7skwMmaqys7/dN+g==
2. AES/CBC/PKCS7Padding解密
/// @Param {String} EncStr  密文
/// @Param {String} Key  加密钥(长度16)
/// @Param {String} VI  偏移量
/// @Param {String} 默认"ORIGIN/BASE64/UTF8" "key值类型ORIGIN|HEX|BASE64  /  加密串类型HEX|BASE64 /  原文编码UTF8"
w ##class(web.Util.Encryption).AESCBCPKCS7Decode("0oyo6n7skwMmaqys7/dN+g==","1234567887654321","1234567890654321")
// 输出 myname我

可以通过此网站对比加密结果
aescbc

3. AES/CBC/ZEROPadding加密
/// @Param {String} EncStr  密文
/// @Param {String} Key  加密钥(长度16)
/// @Param {String} VI  偏移量
/// @Param {String} 默认"ORIGIN/BASE64/UTF8" "key值类型ORIGIN|HEX|BASE64  /  加密串类型HEX|BASE64 /  原文编码UTF8"
w ##class(web.Util.Encryption).AESCBCZeroEncode("汉字","1234567887654321","1234567890123456")
// 输出mKD4kHVZa36eSK7uZ+2hkhEy9SgH5ZOfmLAaB8aVJ4k=
// 得到的结果会比网上长,解密发现多出16个$chat(16)。不影响三方使用

七. 关于RSA

关于RSA可以参考zhangxiang写的这篇文章,讲解了如何生成证书与加解密

八. 敏感数据加密与解密

1. 加密敏感数据方法

Set EncPatTel = ##class(websys.SensitiveProps).Encrypt("18366666666")
// 返回 $1b$$C8A05C2C8CAA7EF97CB26D4D8A390603

2. 解密数据

/// 对加密数据进行对应算法解密,如果没有加密则原样还回
Set PatTel = ##class(websys.SensitiveProps).Decrypt("$1b$$C8A05C2C8CAA7EF97CB26D4D8A390603")
// 返回 18366666666

3. 加星方法

/// @param  SPCode    敏感字段维护界面的代码 必填
/// @param  PatientID 病人id  必填
/// @param  EpisodeID 就诊id 可选
Set Rtn = ##class(websys.SensitiveProps).GetFormatValue("PatTel",1)  // 按格式得到ID为1的患者加星电话
// 返回 183****6666

九. 代码标签内容传到后台

html,sql或js类敏感注入语句会被系统过滤掉,可以前台先转base64字符串,传到后台后,再转回的方式处理。
前台

var orderXmlBase = btoa(escape(orderXml))
// ajax发送到后台

后台

Set orderXml = ##class(web.Util.Encryption).Base64Decode(orderXmlBase)
Set srcOrderXml = $zcvt(orderXml,"I","URL")
// 继续处理
上一篇: 下一篇:

3条评论

  1. changhs说道:

    能把源码发出来吗,好多老项目没有你们这个基础类的更新

    1. Jack说道:

      发布类的代码是为了保证类的产品化,标准化,如果类方法有问题可以联系我。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

访问量: 379533