首先说明 MS并不建议私钥加密,而且.net 于安全的考虑,RSACryptoServiceProvider类解密时只有同时拥有公钥和私钥才可以,原因是公钥是公开的,会被多人持有,这样的数据传输是不安全的。但是架不住有BouncyCastle这个第三方组件,也是可以实现的。只不过在.net core 2.2 下,没有了 RSACryptoServiceProvider,只好改用 System.Security.Cryptography.RSA 来实现 RSA 私钥加密

  1. #Const SUPPORT_PRIVATE_ENCRYPT = True
  2. Imports System.IO
  3. Imports System.Text
  4. Imports System.Security.Cryptography
  5.  
  6. #If SUPPORT_PRIVATE_ENCRYPT Then
  7. Imports Org.BouncyCastle.Math
  8. Imports Org.BouncyCastle.Crypto
  9. Imports Org.BouncyCastle.Security
  10. Imports Org.BouncyCastle.Crypto.Parameters
  11. #End If
  12.  
  13. ''' <summary>
  14. ''' RSA 加密解密辅助类
  15. ''' </summary>
  16. ''' <remarks></remarks>
  17. Public Class RSAHelper
  18.  
  19. Private Shared _privateKey As String
  20.  
  21. ''' <summary>
  22. ''' RSA私钥,包含公钥和私钥
  23. ''' </summary>
  24. ''' <value></value>
  25. ''' <returns></returns>
  26. ''' <remarks></remarks>
  27. Public Shared ReadOnly Property PrivateKey As String
  28. Get
  29. Return _privateKey
  30. End Get
  31. End Property
  32.  
  33. Private Shared _publicKey As String
  34.  
  35. ''' <summary>
  36. ''' RSA公钥,只包含公钥
  37. ''' </summary>
  38. ''' <value></value>
  39. ''' <returns></returns>
  40. ''' <remarks></remarks>
  41. Public Shared ReadOnly Property PublicKey As String
  42. Get
  43. Return _publicKey
  44. End Get
  45. End Property
  46.  
  47. ''' <summary>
  48. ''' 创建RSA密钥对
  49. ''' </summary>
  50. ''' <param name="keySize">512,1024 ...</param>
  51. ''' <returns></returns>
  52. ''' <remarks></remarks>
  53. Public Shared Function CreateRSAKey(Optional ByVal keySize As Int32 = ) As Boolean
  54. _privateKey = Nothing
  55. _publicKey = Nothing
  56. Try
  57. 'Dim provider As New RSACryptoServiceProvider(keySize)
  58. Dim provider = RSA.Create()
  59. provider.KeySize = keySize
  60. _privateKey = provider.ToXml(True)
  61. _publicKey = provider.ToXml(False)
  62.  
  63. Console.WriteLine("max encrypt buffer size:{0}", (keySize / ) - )
  64. Console.WriteLine("max decrypt buffer size:{0}", keySize / )
  65.  
  66. Console.WriteLine(provider.ToPem(True))
  67. Console.WriteLine()
  68. Console.WriteLine(provider.ToPem(False))
  69.  
  70. Console.WriteLine(provider.ToXml(True))
  71. Console.WriteLine()
  72. Console.WriteLine(provider.ToXml(False))
  73.  
  74. #If SUPPORT_PRIVATE_ENCRYPT Then
  75. '验证秘钥对
  76. provider.FromXml(_privateKey)
  77. Dim p = provider.ExportParameters(True)
  78. Dim rkpPrivate As New RsaKeyParameters(True, New BigInteger(, p.Modulus), New BigInteger(p.D))
  79. Dim rkpPublic As New RsaKeyParameters(False, New BigInteger(, p.Modulus), New BigInteger(p.Exponent))
  80. '密钥对有无效的概率,不报错的才可用
  81. #End If
  82. Return True
  83. Catch ex As Exception
  84. Debug.Print("CreateRSAKey({0}) failed, err:{1}", keySize, ex.Message)
  85. Return False
  86. End Try
  87. End Function
  88.  
  89. Private Shared Function isKeyValid(ByVal key As String) As Boolean
  90. If String.IsNullOrEmpty(key) Then
  91. Return False
  92. End If
  93. If key.Trim().Length = Then
  94. Return False
  95. End If
  96.  
  97. Return True
  98. End Function
  99.  
  100. ''' <summary>
  101. ''' 公钥加密
  102. ''' </summary>
  103. ''' <param name="publicKey" >公钥(XML格式字符串)</param>
  104. ''' <param name="plaintext">待加密字符串,明文</param>
  105. ''' <returns></returns>
  106. Public Shared Function PublicKeyEncrypt(ByVal publicKey As String, plaintext As String) As String
  107. '默认只能使用[公钥]进行加密(想使用[公钥解密]可使用第三方组件BouncyCastle来实现)
  108. If String.IsNullOrEmpty(plaintext) Then
  109. Return String.Empty
  110. End If
  111.  
  112. If Not isKeyValid(publicKey) Then
  113. Throw New ArgumentException("Invalid Public Key")
  114. End If
  115.  
  116. '创建RSA对象并载入[公钥]
  117. Dim provider = RSA.Create
  118. provider.FromXml(publicKey)
  119.  
  120. If (provider.KeySize / - ) <= plaintext.Length Then
  121. Throw New ArgumentException("plaintext is too long, try PublicKeyEncryptEx please")
  122. End If
  123.  
  124. '对数据进行加密
  125. Dim publicValue() As Byte = provider.Encrypt(Encoding.UTF8.GetBytes(plaintext), RSAEncryptionPadding.Pkcs1)
  126. Dim ciphertext As String = Convert.ToBase64String(publicValue) '使用Base64将byte转换为string
  127. Return ciphertext
  128. End Function
  129.  
  130. ''' <summary>
  131. ''' 私钥解密
  132. ''' </summary>
  133. ''' <param name="privateKey" >私钥(XML格式字符串)</param>
  134. ''' <param name="ciphertext">待解密字符串,密文</param>
  135. ''' <returns></returns>
  136. Public Shared Function PrivateKeyDecrypt(ByVal privateKey As String, ByVal ciphertext As String) As String
  137. '默认只能使用[私钥]进行解密(想使用[私钥加密]可使用第三方组件BouncyCastle来实现)
  138. If String.IsNullOrEmpty(ciphertext) Then
  139. Return String.Empty
  140. End If
  141.  
  142. If Not isKeyValid(privateKey) Then
  143. Throw New ArgumentException("Invalid Private Key")
  144. End If
  145.  
  146. '创建RSA对象并载入[私钥]
  147. Dim provider = RSA.Create
  148. provider.FromXml(privateKey)
  149.  
  150. If (provider.KeySize / / ) <= ciphertext.Length / Then
  151. Throw New ArgumentException("ciphertext is too long, try PrivateKeyDecryptEx please")
  152. End If
  153.  
  154. '对数据进行解密
  155. Dim privateValue() As Byte = provider.Decrypt(Convert.FromBase64String(ciphertext), RSAEncryptionPadding.Pkcs1) '使用Base64将string转换为byte
  156. Dim plaintext As String = Encoding.UTF8.GetString(privateValue)
  157. Return plaintext
  158. End Function
  159.  
  160. ''' <summary>
  161. ''' 公钥加密
  162. ''' </summary>
  163. ''' <param name="publicKey">公钥(XML格式字符串)</param>
  164. ''' <param name="plaintext">待加密字符串,明文,长度不限</param>
  165. ''' <returns></returns>
  166. ''' <remarks></remarks>
  167. Public Shared Function PublicKeyEncryptEx(ByVal publicKey As String, ByVal plaintext As String) As String
  168. If String.IsNullOrEmpty(plaintext) Then
  169. Return String.Empty
  170. End If
  171.  
  172. If Not isKeyValid(publicKey) Then
  173. Throw New ArgumentException("Invalid Public Key")
  174. End If
  175.  
  176. '载入公钥
  177. Dim provider = RSA.Create
  178. provider.FromXml(publicKey)
  179.  
  180. Dim inputBytes = Encoding.UTF8.GetBytes(plaintext) '有含义的字符串转化为字节流
  181. Dim bufferSize As Integer = (provider.KeySize / ) - '单块最大长度
  182. Dim buffer = New Byte(bufferSize - ) {}
  183. Using inputStream As New MemoryStream(inputBytes), outputStream As New MemoryStream()
  184. Do
  185. Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
  186. If readSize <= Then
  187. Exit Do
  188. End If
  189.  
  190. Dim temp = New Byte(readSize - ) {}
  191. Array.Copy(buffer, , temp, , readSize)
  192. Dim encryptedBytes = provider.Encrypt(temp, RSAEncryptionPadding.Pkcs1) 'False)
  193. outputStream.Write(encryptedBytes, , encryptedBytes.Length)
  194. Loop
  195. Return Convert.ToBase64String(outputStream.ToArray()) '转化为字节流方便传输
  196. End Using
  197.  
  198. End Function
  199.  
  200. ''' <summary>
  201. ''' 私钥解密
  202. ''' </summary>
  203. ''' <param name="privateKey">私钥(XML格式字符串)</param>
  204. ''' <param name="ciphertext">待解密字符串,密文,长度不限</param>
  205. ''' <returns></returns>
  206. ''' <remarks></remarks>
  207. Public Shared Function PrivateKeyDecryptEx(ByVal privateKey As String, ByVal ciphertext As String) As String
  208. If String.IsNullOrEmpty(ciphertext) Then
  209. Return String.Empty
  210. End If
  211.  
  212. If Not isKeyValid(privateKey) Then
  213. Throw New ArgumentException("Invalid Private Key")
  214. End If
  215.  
  216. '载入私钥
  217. Dim provider = RSA.Create
  218. provider.FromXml(privateKey)
  219.  
  220. Dim inputBytes = Convert.FromBase64String(ciphertext)
  221. Dim bufferSize As Integer = provider.KeySize /
  222. Dim buffer = New Byte(bufferSize - ) {}
  223. Using inputStream As New MemoryStream(inputBytes), outputStream As New MemoryStream()
  224. Do
  225. Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
  226. If readSize <= Then
  227. Exit Do
  228. End If
  229.  
  230. Dim temp = New Byte(readSize - ) {}
  231. Array.Copy(buffer, , temp, , readSize)
  232. Dim rawBytes = provider.Decrypt(temp, RSAEncryptionPadding.Pkcs1)
  233. outputStream.Write(rawBytes, , rawBytes.Length)
  234. Loop
  235. Return Encoding.UTF8.GetString(outputStream.ToArray())
  236. End Using
  237. End Function
  238.  
  239. #Region " 依赖 BouncyCastle 实现私钥加密,公钥解密"
  240. #If SUPPORT_PRIVATE_ENCRYPT Then
  241.  
  242. ''' <summary>
  243. ''' 私钥加密
  244. ''' </summary>
  245. ''' <param name="privateKey"> 私钥(XML格式字符串)</param>
  246. ''' <param name="plaintext"> 要加密的数据 </param>
  247. ''' <returns> 加密后的数据 </returns>
  248. Public Shared Function PrivateKeyEncrypt(ByVal privateKey As String, ByVal plaintext As String) As String
  249. If String.IsNullOrEmpty(plaintext) Then
  250. Return String.Empty
  251. End If
  252.  
  253. If Not isKeyValid(privateKey) Then
  254. Throw New ArgumentException("Invalid Private Key")
  255. End If
  256.  
  257. '加载私钥
  258. Dim provider = RSA.Create
  259. provider.FromXml(privateKey)
  260. Dim keyPair = DotNetCoreUtilities.GetKeyPair(provider)
  261.  
  262. Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding") '使用RSA/ECB/PKCS1Padding格式
  263. '第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
  264. c.Init(True, keyPair.Private)
  265.  
  266. Dim DataToEncrypt() As Byte = Encoding.UTF8.GetBytes(plaintext)
  267. Dim outBytes() As Byte = c.DoFinal(DataToEncrypt) '加密
  268. Dim strBase64 As String = Convert.ToBase64String(outBytes)
  269.  
  270. Return strBase64
  271.  
  272. End Function
  273.  
  274. ''' <summary>
  275. ''' 私钥加密
  276. ''' </summary>
  277. ''' <param name="privateKey"> 私钥(XML格式字符串)</param>
  278. ''' <param name="plaintext"> 要加密的数据,长度不限 </param>
  279. ''' <returns> 加密后的数据 </returns>
  280. Public Shared Function PrivateKeyEncryptEx(ByVal privateKey As String, ByVal plaintext As String) As String
  281. If String.IsNullOrEmpty(plaintext) Then
  282. Return String.Empty
  283. End If
  284.  
  285. If Not isKeyValid(privateKey) Then
  286. Throw New ArgumentException("Invalid Private Key")
  287. End If
  288.  
  289. '加载私钥
  290. Dim provider = RSA.Create 'As New RSACryptoServiceProvider()
  291. provider.FromXml(privateKey)
  292. Dim keyPair = DotNetCoreUtilities.GetKeyPair(provider)
  293.  
  294. Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding") '使用RSA/ECB/PKCS1Padding格式
  295. ''第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
  296. c.Init(True, keyPair.Private) ' keyPair.Private)
  297.  
  298. Dim inputBytes = Encoding.UTF8.GetBytes(plaintext)
  299. Dim bufferSize As Integer = provider.KeySize / -
  300. Dim buffer = New Byte(bufferSize - ) {}
  301. Dim outputStream As New MemoryStream()
  302. Using inputStream As New MemoryStream(inputBytes)
  303. Do
  304. Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
  305. If readSize <= Then
  306. Exit Do
  307. End If
  308.  
  309. Dim temp = New Byte(readSize - ) {}
  310. Array.Copy(buffer, , temp, , readSize)
  311. Dim rawBytes = c.DoFinal(temp)
  312. outputStream.Write(rawBytes, , rawBytes.Length)
  313. Loop
  314. End Using
  315. Return Convert.ToBase64String(outputStream.ToArray())
  316. End Function
  317.  
  318. ''' <summary>
  319. ''' 公钥解密
  320. ''' </summary>
  321. ''' <param name="publicKey"> 公钥(XML格式字符串) </param>
  322. ''' <param name="ciphertext"> 要解密数据 </param>
  323. ''' <returns> 解密后的数据 </returns>
  324. Public Shared Function PublicKeyDecrypt(ByVal publicKey As String, ByVal ciphertext As String) As String
  325. If String.IsNullOrEmpty(ciphertext) Then
  326. Return String.Empty
  327. End If
  328.  
  329. If Not isKeyValid(publicKey) Then
  330. Throw New ArgumentException("Invalid Public Key")
  331. End If
  332.  
  333. '加载公钥
  334. Dim provider = RSA.Create
  335. provider.FromXml(publicKey)
  336. Dim keyParameter = DotNetCoreUtilities.GetKeyParmeter(provider.ToPem(False))
  337.  
  338. Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding")
  339. '第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
  340. c.Init(False, keyParameter)
  341.  
  342. Dim DataToDecrypt() As Byte = Convert.FromBase64String(ciphertext)
  343. Dim outBytes() As Byte = c.DoFinal(DataToDecrypt) '解密
  344.  
  345. Dim strDec As String = Encoding.UTF8.GetString(outBytes)
  346. Return strDec
  347. End Function
  348.  
  349. ''' <summary>
  350. ''' 公钥解密
  351. ''' </summary>
  352. ''' <param name="publicKey"> 公钥(XML格式字符串) </param>
  353. ''' <param name="ciphertext"> 要解密数据,长度不限 </param>
  354. ''' <returns> 解密后的数据 </returns>
  355. Public Shared Function PublicKeyDecryptEx(ByVal publicKey As String, ByVal ciphertext As String) As String
  356. If String.IsNullOrEmpty(ciphertext) Then
  357. Return String.Empty
  358. End If
  359.  
  360. If Not isKeyValid(publicKey) Then
  361. Throw New ArgumentException("Invalid Public Key")
  362. End If
  363.  
  364. '加载公钥
  365. Dim provider = RSA.Create
  366. provider.FromXml(publicKey)
  367. Dim keyParameter = DotNetCoreUtilities.GetKeyParmeter(provider.ToPem(False))
  368.  
  369. Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding")
  370. '第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
  371. c.Init(False, keyParameter)
  372.  
  373. Dim inputBytes = Convert.FromBase64String(ciphertext)
  374. Dim bufferSize As Integer = provider.KeySize /
  375. Dim buffer = New Byte(bufferSize - ) {}
  376. Dim outputStream As New MemoryStream()
  377. Using inputStream As New MemoryStream(inputBytes)
  378. Do
  379. Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
  380. If readSize <= Then
  381. Exit Do
  382. End If
  383.  
  384. Dim temp = New Byte(readSize - ) {}
  385. Array.Copy(buffer, , temp, , readSize)
  386. Dim rawBytes = c.DoFinal(temp)
  387. outputStream.Write(rawBytes, , rawBytes.Length)
  388. Loop
  389. End Using
  390. Return Encoding.UTF8.GetString(outputStream.ToArray())
  391. End Function
  392. #End If
  393. #End Region
  394. End Class

扩展方法

  1. Imports System.Security.Cryptography
  2. Imports System.Xml
  3. Imports Org.BouncyCastle.Crypto.Parameters
  4. Imports Org.BouncyCastle.Crypto
  5. Imports Org.BouncyCastle.Math
  6. Imports System.IO
  7. Imports Org.BouncyCastle.OpenSsl
  8. Imports Org.BouncyCastle.Security
  9. Imports System.Text
  10.  
  11. Friend Module RsaExtention
  12.  
  13. <System.Runtime.CompilerServices.Extension>
  14. Public Sub FromXml(ByVal rsa As RSA, ByVal xmlString As String)
  15. Dim parameters As New RSAParameters()
  16. Dim xmlDoc As New XmlDocument()
  17. xmlDoc.LoadXml(xmlString)
  18. If xmlDoc.DocumentElement.Name.Equals("RSAKeyValue") Then
  19. For Each node As XmlNode In xmlDoc.DocumentElement.ChildNodes
  20. Select Case node.Name
  21. Case "Modulus"
  22. parameters.Modulus = Convert.FromBase64String(node.InnerText)
  23. Case "Exponent"
  24. parameters.Exponent = Convert.FromBase64String(node.InnerText)
  25. Case "P"
  26. parameters.P = Convert.FromBase64String(node.InnerText)
  27. Case "Q"
  28. parameters.Q = Convert.FromBase64String(node.InnerText)
  29. Case "DP"
  30. parameters.DP = Convert.FromBase64String(node.InnerText)
  31. Case "DQ"
  32. parameters.DQ = Convert.FromBase64String(node.InnerText)
  33. Case "InverseQ"
  34. parameters.InverseQ = Convert.FromBase64String(node.InnerText)
  35. Case "D"
  36. parameters.D = Convert.FromBase64String(node.InnerText)
  37. End Select
  38. Next node
  39. Else
  40. Throw New Exception("Invalid XML RSA key.")
  41. End If
  42.  
  43. rsa.ImportParameters(parameters)
  44. End Sub
  45.  
  46. <System.Runtime.CompilerServices.Extension>
  47. Public Function ToXml(ByVal rsa As RSA, ByVal includePrivateParameters As Boolean) As String
  48. Dim parameters As RSAParameters = rsa.ExportParameters(includePrivateParameters)
  49.  
  50. Dim ret As String
  51. If includePrivateParameters Then
  52. ret = String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
  53. Convert.ToBase64String(parameters.Modulus),
  54. Convert.ToBase64String(parameters.Exponent),
  55. Convert.ToBase64String(parameters.P),
  56. Convert.ToBase64String(parameters.Q),
  57. Convert.ToBase64String(parameters.DP),
  58. Convert.ToBase64String(parameters.DQ),
  59. Convert.ToBase64String(parameters.InverseQ),
  60. Convert.ToBase64String(parameters.D))
  61. Else
  62. ret = String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
  63. Convert.ToBase64String(parameters.Modulus),
  64. Convert.ToBase64String(parameters.Exponent))
  65. End If
  66. Return formatXml(ret)
  67. End Function
  68.  
  69. Private Function formatXml(ByVal sUnformattedXml As String) As String
  70. Dim xd As New XmlDocument()
  71. xd.LoadXml(sUnformattedXml)
  72. Dim sb As New StringBuilder()
  73. Dim sw As New StringWriter(sb)
  74. Dim xtw As XmlTextWriter = Nothing
  75. Try
  76. xtw = New XmlTextWriter(sw)
  77. xtw.Formatting = Formatting.Indented
  78. xtw.Indentation =
  79. xtw.IndentChar = Char.Parse(vbTab)
  80. xd.WriteTo(xtw)
  81. Finally
  82. If xtw IsNot Nothing Then
  83. xtw.Close()
  84. End If
  85. End Try
  86. Return sb.ToString()
  87. End Function
  88.  
  89. <System.Runtime.CompilerServices.Extension>
  90. Public Sub FromPem(ByVal rsa As RSA, pemString As String)
  91. Const FLAG_PUBLIC As String = "-----BEGIN PUBLIC KEY-----"
  92. Const FLAG_PRIVATE As String = "-----BEGIN PRIVATE KEY-----"
  93.  
  94. Dim content As String = pemString
  95.  
  96. If pemString.StartsWith(FLAG_PUBLIC) Then
  97. content = content.Replace(FLAG_PUBLIC, "").Replace("-----END PUBLIC KEY-----", "").Replace(vbCrLf, "")
  98. Dim publicKeyParam As RsaKeyParameters = PublicKeyFactory.CreateKey(Convert.FromBase64String(content))
  99. Dim xml As String = String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
  100. Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned),
  101. Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned))
  102. rsa.FromXml(xml)
  103. ElseIf pemString.StartsWith(FLAG_PRIVATE) Then
  104. content = content.Replace(FLAG_PRIVATE, "").Replace("-----END PRIVATE KEY-----", "").Replace(vbCrLf, "")
  105. Dim privateKeyParam As RsaPrivateCrtKeyParameters = PrivateKeyFactory.CreateKey(Convert.FromBase64String(content))
  106. Dim parameters As New RSAParameters() With
  107. {
  108. .Modulus = privateKeyParam.Modulus.ToByteArrayUnsigned(),
  109. .Exponent = privateKeyParam.PublicExponent.ToByteArrayUnsigned(),
  110. .P = privateKeyParam.P.ToByteArrayUnsigned(),
  111. .Q = privateKeyParam.Q.ToByteArrayUnsigned(),
  112. .DP = privateKeyParam.DP.ToByteArrayUnsigned(),
  113. .DQ = privateKeyParam.DQ.ToByteArrayUnsigned(),
  114. .InverseQ = privateKeyParam.QInv.ToByteArrayUnsigned(),
  115. .D = privateKeyParam.Exponent.ToByteArrayUnsigned()
  116. }
  117. rsa.ImportParameters(parameters)
  118. Else
  119. Throw New ArgumentException("pemString is not validate")
  120. End If
  121. End Sub
  122.  
  123. <System.Runtime.CompilerServices.Extension>
  124. Public Function ToPem(ByVal rsa As RSA, ByVal includePrivateParameters As Boolean) As String
  125. Dim ret As String = String.Empty
  126. If includePrivateParameters Then
  127. Return exportPrivateKey(rsa)
  128. Else
  129. Return exportPublicKey(rsa)
  130. End If
  131. End Function
  132.  
  133. ''' <summary>
  134. ''' 输出PEM格式公钥
  135. ''' </summary>
  136. ''' <param name="rsa"></param>
  137. ''' <returns></returns>
  138. Private Function exportPublicKey(ByVal rsa As RSA) As String
  139. Dim outputStream As TextWriter = New StringWriter()
  140.  
  141. Dim parameters = rsa.ExportParameters(False)
  142. Using stream = New MemoryStream()
  143. Dim writer = New BinaryWriter(stream)
  144. writer.Write(CByte(&H30)) ' SEQUENCE
  145. Using innerStream = New MemoryStream()
  146. Dim innerWriter = New BinaryWriter(innerStream)
  147. innerWriter.Write(CByte(&H30)) ' SEQUENCE
  148. encodeLength(innerWriter, )
  149. innerWriter.Write(CByte(&H6)) ' OBJECT IDENTIFIER
  150. Dim rsaEncryptionOid = New Byte() {&H2A, &H86, &H48, &H86, &HF7, &HD, &H1, &H1, &H1}
  151. encodeLength(innerWriter, rsaEncryptionOid.Length)
  152. innerWriter.Write(rsaEncryptionOid)
  153. innerWriter.Write(CByte(&H5)) ' NULL
  154. encodeLength(innerWriter, )
  155. innerWriter.Write(CByte(&H3)) ' BIT STRING
  156. Using bitStringStream = New MemoryStream()
  157. Dim bitStringWriter = New BinaryWriter(bitStringStream)
  158. bitStringWriter.Write(CByte(&H0)) ' # of unused bits
  159. bitStringWriter.Write(CByte(&H30)) ' SEQUENCE
  160. Using paramsStream = New MemoryStream()
  161. Dim paramsWriter = New BinaryWriter(paramsStream)
  162. encodeIntegerBigEndian(paramsWriter, parameters.Modulus) ' Modulus
  163. encodeIntegerBigEndian(paramsWriter, parameters.Exponent) ' Exponent
  164. Dim paramsLength = CInt(paramsStream.Length)
  165. encodeLength(bitStringWriter, paramsLength)
  166. bitStringWriter.Write(paramsStream.GetBuffer(), , paramsLength)
  167. End Using
  168. Dim bitStringLength = CInt(bitStringStream.Length)
  169. encodeLength(innerWriter, bitStringLength)
  170. innerWriter.Write(bitStringStream.GetBuffer(), , bitStringLength)
  171. End Using
  172. Dim length = CInt(innerStream.Length)
  173. encodeLength(writer, length)
  174. writer.Write(innerStream.GetBuffer(), , length)
  175. End Using
  176.  
  177. Dim base64 = Convert.ToBase64String(stream.GetBuffer(), , CInt(stream.Length)).ToCharArray()
  178. outputStream.WriteLine("-----BEGIN PUBLIC KEY-----")
  179. For i = To base64.Length - Step
  180. outputStream.WriteLine(base64, i, Math.Min(, base64.Length - i))
  181. Next i
  182. outputStream.WriteLine("-----END PUBLIC KEY-----")
  183. End Using
  184.  
  185. Return outputStream.ToString
  186. End Function
  187.  
  188. ''' <summary>
  189. ''' 输出PEM格式私钥
  190. ''' </summary>
  191. ''' <param name="rsa"></param>
  192. Private Function exportPrivateKey(ByVal rsa As RSA) As String
  193. 'If csp.PublicOnly Then
  194. ' Throw New ArgumentException("CSP does not contain a private key", "csp")
  195. 'End If
  196.  
  197. Dim outputStream As TextWriter = New StringWriter()
  198. Dim parameters = rsa.ExportParameters(True)
  199. If parameters.D Is Nothing Then
  200. Throw New ArgumentException("object does not contain a private key", "csp")
  201. End If
  202. Using stream = New MemoryStream()
  203. Dim writer = New BinaryWriter(stream)
  204. writer.Write(CByte(&H30)) ' SEQUENCE
  205. Using innerStream = New MemoryStream()
  206. Dim innerWriter = New BinaryWriter(innerStream)
  207. encodeIntegerBigEndian(innerWriter, New Byte() {&H0}) ' Version
  208. encodeIntegerBigEndian(innerWriter, parameters.Modulus)
  209. encodeIntegerBigEndian(innerWriter, parameters.Exponent)
  210. encodeIntegerBigEndian(innerWriter, parameters.D)
  211. encodeIntegerBigEndian(innerWriter, parameters.P)
  212. encodeIntegerBigEndian(innerWriter, parameters.Q)
  213. encodeIntegerBigEndian(innerWriter, parameters.DP)
  214. encodeIntegerBigEndian(innerWriter, parameters.DQ)
  215. encodeIntegerBigEndian(innerWriter, parameters.InverseQ)
  216. Dim length = CInt(innerStream.Length)
  217. encodeLength(writer, length)
  218. writer.Write(innerStream.GetBuffer(), , length)
  219. End Using
  220.  
  221. Dim base64 = Convert.ToBase64String(stream.GetBuffer(), , CInt(stream.Length)).ToCharArray()
  222.  
  223. outputStream.WriteLine("-----BEGIN RSA PRIVATE KEY-----")
  224. ' Output as Base64 with lines chopped at 64 characters
  225. For i = To base64.Length - Step
  226. outputStream.WriteLine(base64, i, Math.Min(, base64.Length - i))
  227. Next i
  228. outputStream.WriteLine("-----END RSA PRIVATE KEY-----")
  229. End Using
  230.  
  231. Return outputStream.ToString
  232. End Function
  233.  
  234. Private Sub encodeLength(ByVal stream As BinaryWriter, ByVal length As Integer)
  235. If length < Then
  236. Throw New ArgumentOutOfRangeException("length", "Length must be non-negative")
  237. End If
  238. If length < &H80 Then
  239. ' Short form
  240. stream.Write(CByte(length))
  241. Else
  242. ' Long form
  243. Dim temp = length
  244. Dim bytesRequired =
  245. Do While temp >
  246. temp >>=
  247. bytesRequired +=
  248. Loop
  249. stream.Write(CByte(bytesRequired Or &H80))
  250. For i = bytesRequired - To Step -
  251. stream.Write(CByte(length >> ( * i) And &HFF))
  252. Next i
  253. End If
  254. End Sub
  255.  
  256. Private Sub encodeIntegerBigEndian(ByVal stream As BinaryWriter, ByVal value() As Byte, Optional ByVal forceUnsigned As Boolean = True)
  257. stream.Write(CByte(&H2)) ' INTEGER
  258. Dim prefixZeros =
  259. For i = To value.Length -
  260. If value(i) <> Then
  261. Exit For
  262. End If
  263. prefixZeros +=
  264. Next i
  265. If value.Length - prefixZeros = Then
  266. encodeLength(stream, )
  267. stream.Write(CByte())
  268. Else
  269. If forceUnsigned AndAlso value(prefixZeros) > &H7F Then
  270. ' Add a prefix zero to force unsigned if the MSB is 1
  271. encodeLength(stream, value.Length - prefixZeros + )
  272. stream.Write(CByte())
  273. Else
  274. encodeLength(stream, value.Length - prefixZeros)
  275. End If
  276. For i = prefixZeros To value.Length -
  277. stream.Write(value(i))
  278. Next i
  279. End If
  280. End Sub
  281.  
  282. End Module
  283.  
  284. Friend Module DotNetCoreUtilities
  285. ''' <summary>
  286. ''' 返回 RSA 对象的 密钥对参数对象
  287. ''' </summary>
  288. ''' <param name="provider"></param>
  289. ''' <returns>
  290. ''' 用私钥初始化的 RSA 对象 - 返回有效的公钥和私钥密钥对
  291. ''' 用公钥初始化的 RSA 对象 - 返回 有效的公钥 和 无效的私钥组成的密钥对
  292. ''' </returns>
  293. Public Function GetKeyPair(ByVal provider As RSA) As AsymmetricCipherKeyPair
  294. Dim p As RSAParameters
  295. Dim rkpPrivate As RsaKeyParameters
  296.  
  297. Try
  298. p = provider.ExportParameters(True)
  299. rkpPrivate = New RsaKeyParameters(True, New BigInteger(, p.Modulus), New BigInteger(p.D)) '//PrivateKey 实际使用
  300. Catch ex As Exception
  301. p = provider.ExportParameters(False)
  302. rkpPrivate = New RsaKeyParameters(True, BigInteger.One, BigInteger.One) '//PrivateKey 实际不使用
  303. End Try
  304.  
  305. Dim rpkPublic As New RsaKeyParameters(False, New BigInteger(, p.Modulus), New BigInteger(p.Exponent))
  306. Dim keyPair As New AsymmetricCipherKeyPair(rpkPublic, rkpPrivate)
  307. Return keyPair
  308. End Function
  309.  
  310. ''' <summary>
  311. ''' 通过 PEM 格式的私钥返回 密钥对参数对象
  312. ''' </summary>
  313. ''' <param name="privateKey">PEM 格式的私钥</param>
  314. ''' <returns></returns>
  315. Public Function GetKeyPair(ByVal privateKey As String) As AsymmetricCipherKeyPair
  316. Dim keyPair As AsymmetricCipherKeyPair
  317. Using StringReader As New StringReader(privateKey)
  318. Dim pemReader = New PemReader(StringReader)
  319. keyPair = CType(pemReader.ReadObject, AsymmetricCipherKeyPair)
  320. End Using
  321. Return keyPair
  322. End Function
  323.  
  324. ''' <summary>
  325. ''' 通过 PEM 格式的公钥返回 密钥参数对象
  326. ''' </summary>
  327. ''' <param name="publicKey">PEM 格式的公钥</param>
  328. ''' <returns></returns>
  329. Public Function GetKeyParmeter(ByVal publicKey As String) As AsymmetricKeyParameter
  330. Dim ret As AsymmetricKeyParameter
  331. Using StringReader As New StringReader(publicKey)
  332. Dim pemReader = New PemReader(StringReader)
  333. ret = CType(pemReader.ReadObject, AsymmetricKeyParameter)
  334. End Using
  335. Return ret
  336. End Function
  337. End Module

最后是调用代码示例:

  1. Dim ciphertext As String = RSAHelper.PublicKeyEncryptEx(RSAHelper.PublicKey, plaintext)
  2. Console.WriteLine("===== ciphertext.Length={0}, PublicKeyEncypt Result:", ciphertext.Length)
  3. Console.WriteLine(ciphertext)
  4. Dim newData As String = RSAHelper.PrivateKeyDecryptEx(RSAHelper.PrivateKey, ciphertext)
  5. Console.WriteLine("===== PrivateKeyDecrypt Result:")
  6. Console.WriteLine(newData.Equals(plaintext))
  7. Console.WriteLine("==============================================")
  8. Console.WriteLine()
  9. ciphertext = RSAHelper.PrivateKeyEncryptEx(RSAHelper.PrivateKey, plaintext)
  10. Console.WriteLine("ciphertext.Length={0}, PrivateKeyEncypt Result:", ciphertext.Length)
  11. Console.WriteLine(ciphertext)
  12. newData = RSAHelper.PublicKeyDecryptEx(RSAHelper.PublicKey, ciphertext)
  13. Console.WriteLine("===== PublicKeyDecrypt {0}", newData.Equals(plaintext))

PS:如果需要与Java交换密钥文件,可参考 https://www.cnblogs.com/wuweimin/p/7839335.html

参考文档:

https://blog.csdn.net/u010792238/article/details/79471406

https://www.cnblogs.com/taiyonghai/p/6150353.html

https://stackoverflow.com/questions/23734792/c-sharp-export-private-public-rsa-key-from-rsacryptoserviceprovider-to-pem-strin/25591659#25591659

可用的 .net core 支持 RSA 私钥加密工具类的更多相关文章

  1. Delphi RSA加解密【 (RSA公钥加密,私钥解密)、(RSA私钥加密,公钥解密)、MD5加密、SHA加密】

    作者QQ:(648437169) 点击下载➨delphi RSA加解密 [Delphi RSA加解密]支持 (RSA公钥加密,私钥解密).(RSA私钥加密,公钥解密).MD5加密.SHA1加密.SHA ...

  2. 求求你们不要再用 RSA 私钥加密公钥解密了,这非常不安全!

    最近经常在网上看到有人说巨硬的 CNG(Cryptography Next Generation 即下一代加密技术) 只提供 RSA 公钥加密私钥解密,没有提供 RSA 私钥加密公钥解密,他们要自己封 ...

  3. java 加密工具类(MD5、RSA、AES等加密方式)

    1.加密工具类encryption MD5加密 import org.apache.commons.codec.digest.DigestUtils; /** * MD5加密组件 * * @autho ...

  4. RSA加解密工具类RSAUtils.java,实现公钥加密私钥解密和私钥解密公钥解密

    package com.geostar.gfstack.cas.util; import org.apache.commons.codec.binary.Base64; import javax.cr ...

  5. 关于RSA加密算法的工具类

    关于RSA加密算法的工具类 最近在捣鼓SSO(单点登录),就是一个在应用(系统)登录之后,当切换其他应用(系统)的时候,可以省去登录,提高用户的使用的便捷.(具体有时间在写) 期间涉及的安全问题,发送 ...

  6. java MD5Utils 加密工具类

    package com.sicdt.library.core.utils; import java.io.File; import java.io.FileInputStream; import ja ...

  7. App开发流程之加密工具类

    科技优家 2016-09-08 18:10 从这篇记录开始,记录的都算是干货了,都是一些编程日常的积累. 我建议先将基础的工具加入项目,后续的开发效率会呈指数增长.如果在专注功能开发过程中,才发现缺少 ...

  8. 加密工具类 - CryptoUtils.java

    加密工具类,包含MD5,BASE64,SHA,CRC32的加密与解密方法. 源码如下:(点击下载  - CryptoUtils.java.commons-io-2.4.jar.commons-code ...

  9. android开发MD5加密工具类(一)

    MD5加密工具类整理: package com.gzcivil.utils; import java.io.UnsupportedEncodingException; import java.secu ...

随机推荐

  1. python 的第一个界面程序(PyQt5)

    这里用到了python的一个第三qt库PyQt5,API与qt几乎完全一样(科学严谨下...) from PyQt5.QtWidgets import QApplication, QMainWindo ...

  2. PAT Advanced 1111 Online Map (30) [Dijkstra算法 + DFS]

    题目 Input our current position and a destination, an online map can recommend several paths. Now your ...

  3. 常用sql语句(mysql测试)

    DB数据库,DatabaseDBMS数据库管理系统,DatabaMemanagmentSystemSQL结构化查询语言,structure Query Language 开启服务net start m ...

  4. JS-语句二

    for循环的4个要素: 1.初始值        2.条件判断        3.状态改变        4.循环体 for循环的写法: for(var i=0;i>10;i++)        ...

  5. 期末项目之 Json文件

    Github上的json文件: https://raw.githubusercontent.com/color-me/first/master/b

  6. (转)jpbc的基本函数介绍

    双线性群简介 质数阶双线性群(Prime-Order Bilinear Groups) 质数双线性群可以由五元组(p,G1,G2,GT,e)来描述.五元组中p是一个与给定安全常数λ相关的大质数,G1, ...

  7. GBDT入门

    GBDT(MART)迭代决策树入门教程 GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree) ...

  8. 201771010123汪慧和《面向对象程序设计JAVA》第七周实验总结

    一.理论部分 1.继承 如果两个类存在继承关系,则子类会自动继承父类的方法和变量,在子类中可以调用父类的方法和变量,如果想要在子类里面做一系列事情,应该放在父类无参构造器里面,在java中,只允许单继 ...

  9. css块级元素

    <CSS权威指南>中文字显示:任何不是块级元素的可见元素都是内联元素.其表现的特性是“行布局”形式,这里的“行布局”的意思就是说其表现形式始终以行进行显示.比如,我们设定一个内联元素bor ...

  10. 程序Dog的大梦想

    一.我是程序狗 "怎么又是任宏啊,每天都起这么早,要命啊--" "人家任宏可是要成为学霸的男人,咱们这些凡夫俗子啊,理解不了这么伟大的理想--"----微电影& ...