打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
asp版 vbscript RSA公钥加密 / 私钥解密 / 私钥签名 / 公钥验签(支持中文)分段加密解密
userphoto

2022.10.18 北京

关注

最近有空在把自己的asp站点后端函数全部整理了下,在弄RSA的时候遇到了坑了,然后找到下面这位兄弟刚好发布的文章:

https://blog.csdn.net/todaygods/article/details/109383438

用了他的demo在本机win7,IIS环境测试,一切正常,然后传到服务器windows server 2008 R2 IIS环境下测试,IIS站点的应用程序池用的默认.net 2.0的,上demo,直接提示 mscorlib 错误,估计是没有调起.net的类,在服务器的安装程序里面看到有装.net 4.6,然后把IIS对应的应用程序池设为.NET 4.0,重启IIS,前面这个错误没有了,但提示 .encrypt 参数错误(就这个坑搞了1天多),检查代码,找微软的官方文档接口说明,也没发现问题,官方是c#演示,勉强看懂一点原理,测试其他的API接口,以前没有看过微软这些文档,就感觉里面的接口说明绕来绕去的。

研究了大半天没结果,后面想着还是从服务器上检查原因吧,再次检查系统的应用程序列表,卸掉4.6重新安装4.8的,IIS应用程序池再设置一遍,按照网上的资料又是设置程序池的权限,C盘里面相关读写权限试过,还是不行啊。

后面偶然间在系统的 服务器管理 里面 功能 模块里面有个 .NET3.5.1 ,好家伙,我记得我安装4.8新版之前4.6版都卸掉了,怎么还有3.5.1呢,然后进【删除功能】删掉之后重启,结果这里进去用【添加功能】准备把新版的添加进去,发现但添加的时候仍然只有 3.5.1的选项。【图中箭头位置之前是显示的.NET3.5.1】

估计就是这里的问题了,在系统程序管理把后面装的.NET全部删掉,重新装4.8试试,结果这里还是显示只有3.5.1,后来查询资料才知道这个是系统内置的.NET3.5.1,最终按下方法操作:

 1、下载一个工具:.NET Framework cleanup_tool 清空系统全部的.net安装缓存
 2、运行services.msc或者再计算机上点右键,选择管理,找到服务 Windows update 停止它的运行;
 3、删除C:\Windows\SoftwareDistribution这个目录;
 4、把第一步中停止的服务重新启动;
 5、重新安装新版;

经过上面步骤操作,再开demo,一下就通过了,加密解密全部ok。

这里要注意:经过上面的操作后,我就 没有在 服务器管理 里面 添加功能 这个操作了,进去添加的话还会显示是内置的3.5.1版,当时应该直接在这里把3.5.1的这个功能移除,然后下载.NET4+的版本安装好应该也就可以了。 

这个是被系统内置的.NET3.5.1坑的,因为看表面系统应用程序里面和IIS的应用程序池都是NET 4+新版,但实际上通过 server.createobject("system. 这类还是优先通过内置的3.5功能调用的。

好了,下面上demo代码:

  1. <%
  2. '@ ---------------------------------------------------------------
  3. '@ title: xmasp_rsa
  4. '@ author: ekede.com
  5. '@ date: 2020-10-28
  6. '@ description: RSA 公钥加密->私钥解密 , 私钥签名->公钥验签
  7. '@ 支持 MD5withRSA,SHA1withRSA,SHA256withRSA,SHA384withRSA 和 SHA512withRSA
  8. '@ ---------------------------------------------------------------
  9. class xmasp_rsa
  10. private utf8,enc
  11. private privatekey_,publickey_
  12. '@ privatekey: your personal private key. keep this hidden. need c# format.
  13. public property get privatekey
  14. privatekey = privatekey_
  15. end property
  16. public property let privatekey(value)
  17. privatekey_ = value
  18. enc.fromxmlstring(privatekey_)
  19. publickey_ = enc.toxmlstring(false)
  20. end property
  21. '@publickey: key for others to encrypt data with.
  22. public property get publickey
  23. publickey = publickey_
  24. end property
  25. public property let publickey(value)
  26. publickey_ = value
  27. enc.fromxmlstring(publickey_)
  28. end property
  29. private sub class_initialize()
  30. dim xmasp_rsa
  31. xmasp_rsa = "xmasp应用框架 - 扩展包"
  32. set utf8 = server.createobject("system.text.utf8encoding")
  33. set enc = server.createobject("system.security.cryptography.rsacryptoserviceprovider")
  34. createkey()
  35. end sub
  36. private sub class_terminate()
  37. set enc = nothing
  38. set utf8 = nothing
  39. end sub
  40. '返回包含当前 RSA 对象的密钥的 XML 字符串
  41. public sub createkey()
  42. privatekey_ = enc.toxmlstring(true) '表示同时包含 RSA 公钥和私钥[Modulus Exponent P Q DP DQ D InverseQ]
  43. publickey_ = enc.toxmlstring(false) '表示仅包含公钥[ Modulus Exponent]
  44. end sub
  45. '@encrypt(byref str): 公钥加密
  46. public function encrypt(byref str)
  47. 'dim bytes
  48. 'bytes = utf8.getbytes_4(str)
  49. 'encrypt = bytes2base64(rsaencrypt((bytes)))
  50. '【分块加密】
  51. '.NET Framework 中提供的 RSA 算法规定:
  52. '待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:RSACryptoServiceProvider.KeySize / 8 - 11),
  53. '而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)。
  54. '所以,如果要加密较长的数据,则可以采用分段加解密的方式。
  55. if str="" then encrypt="" : exit function
  56. dim blocksize:blocksize = enc.keysize / 8 - 11 '分块的最大字节数,如:2048/8-11=245
  57. '得到字节数
  58. 'dim na
  59. 'na = ubound(bytes) + 1
  60. 'na = lenb(bytes)
  61. dim i,s,sk,bytes
  62. dim k:k = 0
  63. dim n:n = len(str) - 1
  64. for i=0 to n
  65. dim a0:a0 = mid(str,i+1,1)
  66. dim a1:a1 = utf8.getbytes_4(a0)
  67. dim a2:a2 = lenb(a1)
  68. dim bk
  69. if (k + a2) < blocksize then
  70. s = s & a0
  71. k = k + a2
  72. if i = n then
  73. bytes = utf8.getbytes_4(s)
  74. bk = rsaencrypt((bytes))
  75. sk = sk & bytes2base64(bk)
  76. end if
  77. else
  78. bytes = utf8.getbytes_4(s)
  79. bk = rsaencrypt((bytes))
  80. sk = sk & bytes2base64(bk)
  81. k = 0
  82. s = a0
  83. end if
  84. next
  85. encrypt = sk
  86. end function
  87. private function rsaencrypt(byref bytes)
  88. rsaencrypt = enc.encrypt((bytes),false)
  89. end function
  90. '@decrypt(byref bytes): 私钥解密
  91. public function decrypt(byref str)
  92. 'dim bytes
  93. 'bytes = rsadecrypt(base642bytes(str))
  94. 'decrypt = utf8.getstring((bytes))
  95. '对分块进行解密
  96. decrypt = ""
  97. if str="" then exit function
  98. dim i,a,na,s
  99. a = split(str,"==")
  100. na = ubound(a)
  101. for i=0 to na - 1
  102. dim a0:a0 = a(i) & "=="
  103. dim a1:a1 = rsadecrypt(base642bytes(a0))
  104. s = s & utf8.getstring((a1))
  105. next
  106. decrypt = s
  107. end function
  108. private function rsadecrypt(byref bytes)
  109. rsadecrypt = enc.decrypt((bytes), false)
  110. end function
  111. '@sign(byref str,byref hash): 私钥签名 hash(MD5 SHA1 SHA256)
  112. public function sign(byref str,byref hash)
  113. dim bytes
  114. bytes = utf8.getbytes_4(str)
  115. sign = bytes2base64(signhash(bytes, hash))
  116. end function
  117. private function signhash(byref bytes,byref hash)
  118. dim mapnametooid
  119. hash = lcase(hash)
  120. if hash="md5" then
  121. mapnametooid = "1.2.840.113549.2.5"
  122. bytes = md5(bytes)
  123. signhash = enc.signhash((bytes),mapnametooid)
  124. end if
  125. if hash="sha1" then
  126. mapnametooid = "1.3.14.3.2.26"
  127. bytes = sha1(bytes)
  128. signhash = enc.signhash((bytes),mapnametooid)
  129. end if
  130. if hash="sha256" then
  131. mapnametooid = "2.16.840.1.101.3.4.2.1"
  132. bytes = sha256(bytes)
  133. signhash = enc.signhash((bytes),mapnametooid)
  134. end if
  135. if hash="sha384" then
  136. mapnametooid = "2.16.840.1.101.3.4.2.2"
  137. bytes = sha384(bytes)
  138. signhash = enc.signhash((bytes),mapnametooid)
  139. end if
  140. if hash="sha512" then
  141. mapnametooid = "2.16.840.1.101.3.4.2.3"
  142. bytes = sha512(bytes)
  143. signhash = enc.signhash((bytes),mapnametooid)
  144. end if
  145. end function
  146. '@verify(byref str,byref hash,byref strsign): 公钥验签
  147. public function verify(byref str,byref hash,byref strsign)
  148. dim bytes,bytessign
  149. bytes = utf8.getbytes_4(str)
  150. bytessign = base642bytes(strsign)
  151. verify = enc.verifydata((bytes),hash,(bytessign))
  152. end function
  153. 'hash
  154. public function md5(byref bytes)
  155. dim en
  156. set en = server.createobject("system.security.cryptography.md5cryptoserviceprovider")
  157. md5 = en.computehash_2((bytes))
  158. set en = nothing
  159. end function
  160. public function sha1(byref bytes)
  161. dim en
  162. set en = server.createobject("system.security.cryptography.sha1cryptoserviceprovider")
  163. sha1 = en.computehash_2((bytes))
  164. set en = nothing
  165. end function
  166. public function sha256(byref bytes)
  167. dim en
  168. 'set en = server.createobject("system.security.cryptography.sha1cryptoserviceprovider")
  169. set en = server.createobject("system.security.cryptography.sha256managed")
  170. sha256 = en.computehash_2((bytes))
  171. set en = nothing
  172. end function
  173. public function sha384(byref bytes)
  174. dim en
  175. set en = server.createobject("system.security.cryptography.sha384managed")
  176. sha384 = en.computehash_2((bytes))
  177. set en = nothing
  178. end function
  179. public function sha512(byref bytes)
  180. dim en
  181. set en = server.createobject("system.security.cryptography.sha512managed")
  182. sha512 = en.computehash_2((bytes))
  183. set en = nothing
  184. end function
  185. 'base64
  186. public function base642bytes(str)
  187. dim xml,node
  188. set xml = server.createobject("msxml2.domdocument")
  189. set node = xml.createelement("b64")
  190. node.datatype = "bin.base64"
  191. node.text = str
  192. base642bytes = node.nodetypedvalue
  193. set node = nothing
  194. set xml = nothing
  195. end function
  196. public function bytes2base64(bytes)
  197. dim xml,node
  198. set xml = server.createobject("msxml2.domdocument")
  199. set node = xml.createelement("b64")
  200. node.datatype = "bin.base64"
  201. node.nodetypedvalue = bytes
  202. bytes2base64 = node.text
  203. set node = nothing
  204. set xml = nothing
  205. end function
  206. end class
  207. %>

1、在原作的基础上修正了一处【注释掉的那句是原作的,我这测试的时候要用下面这句才能调起】:

  1. public function sha256(byref bytes)
  2. dim en
  3. 'set en = server.createobject("system.security.cryptography.sha1cryptoserviceprovider")
  4. set en = server.createobject("system.security.cryptography.sha256managed")
  5. sha256 = en.computehash_2((bytes))
  6. set en = nothing
  7. end function

2、增加了 SHA384withRSA 和 SHA512withRSA 的支持。

3、增加了分块加密解密功能,原因:

        .NET Framework 中提供的 RSA 算法规定:
        待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:RSACryptoServiceProvider.KeySize / 8 - 11),
        而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)。
        所以,如果要加密较长的数据,则可以采用分段加解密的方式。

其他:对于分块加密解密可功能处理过程可能还有更好的优化方案,还望大师们给指定。

在使用的时候,要先想办法把 pem证书转成xml格式,

可参考第三方在线转换:https://superdry.apphb.com/tools/online-rsa-key-converter

原作者刚也出了一个tools工具,可以看文首的链接。

下面是使用方法:

  1. dim s0
  2. s0 = "<RSAKeyValue>"
  3. s0 = s0 & "<Modulus>u8CS+voY3IVwm2QjJFg4uyU4TX/H/cCuG+8UgGr0qsvX6OUnxKu8YG18hKGB/7y/nBwlc0mYH8PSkDmT2SGR50LMz2e/r7yBkvazlykul0zqVTwJHAOrtXDVK8QZMH/vFzRPZrvr1SbwCMPrJ5ZGRtffPmT/7MVk8yWQo9XlAq2ABz62axwO1FC6TZc3PpmE+8pr18+AnzEai0TCjq3NaC28QWr3LGJDO/fGtT/bWz0uBrYPhCAxeYyWsDokiX0NU0ixUB2PulGqvsztjrxZYQPsZIIgZ1lMz/43rrfHGkrtmOeCS25+U/blzfZSRF6WDVIhTwBK1cFRb4tVgd107w==</Modulus>"
  4. s0 = s0 & "<Exponent>AQAB</Exponent>"
  5. s0 = s0 & "<P>9C9bAbM87egP+dLaA8IQA2lJEBG6b5pJidw40lm0E2Ey1v2NMCEhd3stEUSrS0QfVN9S0N0aPZmsBNkbm7P7nSviq53n2Qo/mEP06dhx7+MI1nKlmTrgqH0HvCYK7+55vxojZsuvj9E9Q7tE5KXJsKZ8syLrWbLPvrPPF4TVwjc=</P>"
  6. s0 = s0 & "<Q>xNY0H25RbMJGFUaZ/a4b6/yPXECdFX7LeFxFAiJ4ds+zavenRMacm4MNjY91m90t7p0UZYvytk39YeX2/J6x0C2U/gQE3VS5ER+NAOqrl9UgBxZeb0e5Cz3TcU4w/zT+sQedYqG4p/ldT4UnBKXleI/+l6H86Qnix1O9Xae25wk=</Q>"
  7. s0 = s0 & "<DP>d46YKITx2Co/aDpstFpYLNNoCo4jknEggHdq+tMg8DwvAES01FPkZvPQZRwSIpAAJzYQ/mLDblXHe7gxZFMDZzkNiqmN0x7JdGwRhk2Lu8CVmyoXGqdRSC2vk9eskz1YLtFFdBdWpjv0my0d1jW2Qt/BPpRiV1DNlrnDM+i+IJE=</DP>"
  8. s0 = s0 & "<DQ>muDs7FpSaWBH4s/FtSz9PWdhqjYRI+u7z/3SMsbKwLnXM/Cfxeb9LQQmct+Rq82SKbGhbfF7TeT53cEj4UxBH0vucxzYcwsJ/6Yyvajo0bRZ2hnIvojR2j2QlRPwS674RHV4ajZT5J+6wypDNE4QzBeJPOix5u/nZ+3FD986dHk=</DQ>"
  9. s0 = s0 & "<InverseQ>KPlNyd7bdTwL3eJ9MzSbOXHdUSKUvjWVtLekiIAGJX4KOT971ipiYR2TDAKTyDaYuYFibNEKcJMIlsQ5ou7hg8ja/WpuCjdZxOmh23bHteyQA8LyLgpvsj1vWQy8VdCXEyUsZji7PskpLOnnyNrl0VXZvivUqUR3rHggsX05PgQ=</InverseQ>"
  10. s0 = s0 & "<D>sRhXS2bGNpOjgN82ipywfk4ASpGiGcc6M10S8IJyX/xAnwwvs8HtwOLlFdGl5oyqC908sf8T/7pdDe9RdvjEP+fxeh05YNElQ3NyOL3+lXZWfqlPSl5oA4/3cv3YaLfz1OZhktzk+TxuI0Zxs/h6N259w8PO5w3WR8cCJJeoGRngb8WnwiZob0RjYp1nrlwNQc9vHvzqgjhT9RhxDYFh3m2MfQDZZVedrU6TpDPnWBLmHyl6faBrbgVmfki4aCb1ldVGMlcfXpuYvP0HGPuodWaTIBRTA1B6W8aeakXQkp8++znKHJq8w+oScDHDC/ekaQ1idgVu9fvPfzuZbL/2MQ==</D>"
  11. s0 = s0 & "</RSAKeyValue>"
  12. dim RSA
  13. dim a0,a1,a2,a3,a4,a5
  14. a0 = "Hello World!"
  15. a0 = a0 & "RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)"
  16. a0 = a0 & "一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。"
  17. set RSA= new xmasp_rsa
  18. RSA.privatekey = s0 '设置私钥
  19. 'RSA.publickey = "xxxx" '设置公钥
  20. 'publickey = RSA.publickey '也可通过私钥获得公钥
  21. a1 = RSA.encrypt(a0) '加密
  22. a2 = RSA.decrypt(a1) '解密
  23. a3 = RSA.sign(a1,"SHA512") '签名支持SHA1 SHA256 SHA512 MD5
  24. a4 = RSA.verify(a1,"SHA512",a3) '验签
  25. set RSA = nothing
  26. response.write "字符串:" & a0 & "</br>"
  27. response.write "加密后:" & a1 & "</br>"
  28. response.write "加密后字符长:" & len(a1) & "</br>"
  29. response.write "解密后:" & a2 & "</br>"
  30. response.write "签名后:" & a3 & "</br>"
  31. response.write "验签后:" & a4 & "</br>"

运行结果:

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
用delphi开发支付宝支付和微信支付
OpenSSL使用指南
第十一节 过程和函数
openssl使用手册 - Linux - 系统网络运维
带有TLSv1.2和转发保密性的Python粘贴SSL服务器
各种各样加密算法的js库,安全加密不再愁——crypto
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服