可用的 .net core 支持 RSA 私钥加密工具类

2023-06-15,,

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

 #Const SUPPORT_PRIVATE_ENCRYPT = True
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography #If SUPPORT_PRIVATE_ENCRYPT Then
Imports Org.BouncyCastle.Math
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Security
Imports Org.BouncyCastle.Crypto.Parameters
#End If ''' <summary>
''' RSA 加密解密辅助类
''' </summary>
''' <remarks></remarks>
Public Class RSAHelper Private Shared _privateKey As String ''' <summary>
''' RSA私钥,包含公钥和私钥
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property PrivateKey As String
Get
Return _privateKey
End Get
End Property Private Shared _publicKey As String ''' <summary>
''' RSA公钥,只包含公钥
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property PublicKey As String
Get
Return _publicKey
End Get
End Property ''' <summary>
''' 创建RSA密钥对
''' </summary>
''' <param name="keySize">512,1024 ...</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function CreateRSAKey(Optional ByVal keySize As Int32 = ) As Boolean
_privateKey = Nothing
_publicKey = Nothing
Try
'Dim provider As New RSACryptoServiceProvider(keySize)
Dim provider = RSA.Create()
provider.KeySize = keySize
_privateKey = provider.ToXml(True)
_publicKey = provider.ToXml(False) Console.WriteLine("max encrypt buffer size:{0}", (keySize / ) - )
Console.WriteLine("max decrypt buffer size:{0}", keySize / ) Console.WriteLine(provider.ToPem(True))
Console.WriteLine()
Console.WriteLine(provider.ToPem(False)) Console.WriteLine(provider.ToXml(True))
Console.WriteLine()
Console.WriteLine(provider.ToXml(False)) #If SUPPORT_PRIVATE_ENCRYPT Then
'验证秘钥对
provider.FromXml(_privateKey)
Dim p = provider.ExportParameters(True)
Dim rkpPrivate As New RsaKeyParameters(True, New BigInteger(, p.Modulus), New BigInteger(p.D))
Dim rkpPublic As New RsaKeyParameters(False, New BigInteger(, p.Modulus), New BigInteger(p.Exponent))
'密钥对有无效的概率,不报错的才可用
#End If
Return True
Catch ex As Exception
Debug.Print("CreateRSAKey({0}) failed, err:{1}", keySize, ex.Message)
Return False
End Try
End Function Private Shared Function isKeyValid(ByVal key As String) As Boolean
If String.IsNullOrEmpty(key) Then
Return False
End If
If key.Trim().Length = Then
Return False
End If Return True
End Function ''' <summary>
''' 公钥加密
''' </summary>
''' <param name="publicKey" >公钥(XML格式字符串)</param>
''' <param name="plaintext">待加密字符串,明文</param>
''' <returns></returns>
Public Shared Function PublicKeyEncrypt(ByVal publicKey As String, plaintext As String) As String
'默认只能使用[公钥]进行加密(想使用[公钥解密]可使用第三方组件BouncyCastle来实现)
If String.IsNullOrEmpty(plaintext) Then
Return String.Empty
End If If Not isKeyValid(publicKey) Then
Throw New ArgumentException("Invalid Public Key")
End If '创建RSA对象并载入[公钥]
Dim provider = RSA.Create
provider.FromXml(publicKey) If (provider.KeySize / - ) <= plaintext.Length Then
Throw New ArgumentException("plaintext is too long, try PublicKeyEncryptEx please")
End If '对数据进行加密
Dim publicValue() As Byte = provider.Encrypt(Encoding.UTF8.GetBytes(plaintext), RSAEncryptionPadding.Pkcs1)
Dim ciphertext As String = Convert.ToBase64String(publicValue) '使用Base64将byte转换为string
Return ciphertext
End Function ''' <summary>
''' 私钥解密
''' </summary>
''' <param name="privateKey" >私钥(XML格式字符串)</param>
''' <param name="ciphertext">待解密字符串,密文</param>
''' <returns></returns>
Public Shared Function PrivateKeyDecrypt(ByVal privateKey As String, ByVal ciphertext As String) As String
'默认只能使用[私钥]进行解密(想使用[私钥加密]可使用第三方组件BouncyCastle来实现)
If String.IsNullOrEmpty(ciphertext) Then
Return String.Empty
End If If Not isKeyValid(privateKey) Then
Throw New ArgumentException("Invalid Private Key")
End If '创建RSA对象并载入[私钥]
Dim provider = RSA.Create
provider.FromXml(privateKey) If (provider.KeySize / / ) <= ciphertext.Length / Then
Throw New ArgumentException("ciphertext is too long, try PrivateKeyDecryptEx please")
End If '对数据进行解密
Dim privateValue() As Byte = provider.Decrypt(Convert.FromBase64String(ciphertext), RSAEncryptionPadding.Pkcs1) '使用Base64将string转换为byte
Dim plaintext As String = Encoding.UTF8.GetString(privateValue)
Return plaintext
End Function ''' <summary>
''' 公钥加密
''' </summary>
''' <param name="publicKey">公钥(XML格式字符串)</param>
''' <param name="plaintext">待加密字符串,明文,长度不限</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function PublicKeyEncryptEx(ByVal publicKey As String, ByVal plaintext As String) As String
If String.IsNullOrEmpty(plaintext) Then
Return String.Empty
End If If Not isKeyValid(publicKey) Then
Throw New ArgumentException("Invalid Public Key")
End If '载入公钥
Dim provider = RSA.Create
provider.FromXml(publicKey) Dim inputBytes = Encoding.UTF8.GetBytes(plaintext) '有含义的字符串转化为字节流
Dim bufferSize As Integer = (provider.KeySize / ) - '单块最大长度
Dim buffer = New Byte(bufferSize - ) {}
Using inputStream As New MemoryStream(inputBytes), outputStream As New MemoryStream()
Do
Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
If readSize <= Then
Exit Do
End If Dim temp = New Byte(readSize - ) {}
Array.Copy(buffer, , temp, , readSize)
Dim encryptedBytes = provider.Encrypt(temp, RSAEncryptionPadding.Pkcs1) 'False)
outputStream.Write(encryptedBytes, , encryptedBytes.Length)
Loop
Return Convert.ToBase64String(outputStream.ToArray()) '转化为字节流方便传输
End Using End Function ''' <summary>
''' 私钥解密
''' </summary>
''' <param name="privateKey">私钥(XML格式字符串)</param>
''' <param name="ciphertext">待解密字符串,密文,长度不限</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function PrivateKeyDecryptEx(ByVal privateKey As String, ByVal ciphertext As String) As String
If String.IsNullOrEmpty(ciphertext) Then
Return String.Empty
End If If Not isKeyValid(privateKey) Then
Throw New ArgumentException("Invalid Private Key")
End If '载入私钥
Dim provider = RSA.Create
provider.FromXml(privateKey) Dim inputBytes = Convert.FromBase64String(ciphertext)
Dim bufferSize As Integer = provider.KeySize /
Dim buffer = New Byte(bufferSize - ) {}
Using inputStream As New MemoryStream(inputBytes), outputStream As New MemoryStream()
Do
Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
If readSize <= Then
Exit Do
End If Dim temp = New Byte(readSize - ) {}
Array.Copy(buffer, , temp, , readSize)
Dim rawBytes = provider.Decrypt(temp, RSAEncryptionPadding.Pkcs1)
outputStream.Write(rawBytes, , rawBytes.Length)
Loop
Return Encoding.UTF8.GetString(outputStream.ToArray())
End Using
End Function #Region " 依赖 BouncyCastle 实现私钥加密,公钥解密"
#If SUPPORT_PRIVATE_ENCRYPT Then ''' <summary>
''' 私钥加密
''' </summary>
''' <param name="privateKey"> 私钥(XML格式字符串)</param>
''' <param name="plaintext"> 要加密的数据 </param>
''' <returns> 加密后的数据 </returns>
Public Shared Function PrivateKeyEncrypt(ByVal privateKey As String, ByVal plaintext As String) As String
If String.IsNullOrEmpty(plaintext) Then
Return String.Empty
End If If Not isKeyValid(privateKey) Then
Throw New ArgumentException("Invalid Private Key")
End If '加载私钥
Dim provider = RSA.Create
provider.FromXml(privateKey)
Dim keyPair = DotNetCoreUtilities.GetKeyPair(provider) Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding") '使用RSA/ECB/PKCS1Padding格式
'第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
c.Init(True, keyPair.Private) Dim DataToEncrypt() As Byte = Encoding.UTF8.GetBytes(plaintext)
Dim outBytes() As Byte = c.DoFinal(DataToEncrypt) '加密
Dim strBase64 As String = Convert.ToBase64String(outBytes) Return strBase64 End Function ''' <summary>
''' 私钥加密
''' </summary>
''' <param name="privateKey"> 私钥(XML格式字符串)</param>
''' <param name="plaintext"> 要加密的数据,长度不限 </param>
''' <returns> 加密后的数据 </returns>
Public Shared Function PrivateKeyEncryptEx(ByVal privateKey As String, ByVal plaintext As String) As String
If String.IsNullOrEmpty(plaintext) Then
Return String.Empty
End If If Not isKeyValid(privateKey) Then
Throw New ArgumentException("Invalid Private Key")
End If '加载私钥
Dim provider = RSA.Create 'As New RSACryptoServiceProvider()
provider.FromXml(privateKey)
Dim keyPair = DotNetCoreUtilities.GetKeyPair(provider) Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding") '使用RSA/ECB/PKCS1Padding格式
''第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
c.Init(True, keyPair.Private) ' keyPair.Private) Dim inputBytes = Encoding.UTF8.GetBytes(plaintext)
Dim bufferSize As Integer = provider.KeySize / -
Dim buffer = New Byte(bufferSize - ) {}
Dim outputStream As New MemoryStream()
Using inputStream As New MemoryStream(inputBytes)
Do
Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
If readSize <= Then
Exit Do
End If Dim temp = New Byte(readSize - ) {}
Array.Copy(buffer, , temp, , readSize)
Dim rawBytes = c.DoFinal(temp)
outputStream.Write(rawBytes, , rawBytes.Length)
Loop
End Using
Return Convert.ToBase64String(outputStream.ToArray())
End Function ''' <summary>
''' 公钥解密
''' </summary>
''' <param name="publicKey"> 公钥(XML格式字符串) </param>
''' <param name="ciphertext"> 要解密数据 </param>
''' <returns> 解密后的数据 </returns>
Public Shared Function PublicKeyDecrypt(ByVal publicKey As String, ByVal ciphertext As String) As String
If String.IsNullOrEmpty(ciphertext) Then
Return String.Empty
End If If Not isKeyValid(publicKey) Then
Throw New ArgumentException("Invalid Public Key")
End If '加载公钥
Dim provider = RSA.Create
provider.FromXml(publicKey)
Dim keyParameter = DotNetCoreUtilities.GetKeyParmeter(provider.ToPem(False)) Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding")
'第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
c.Init(False, keyParameter) Dim DataToDecrypt() As Byte = Convert.FromBase64String(ciphertext)
Dim outBytes() As Byte = c.DoFinal(DataToDecrypt) '解密 Dim strDec As String = Encoding.UTF8.GetString(outBytes)
Return strDec
End Function ''' <summary>
''' 公钥解密
''' </summary>
''' <param name="publicKey"> 公钥(XML格式字符串) </param>
''' <param name="ciphertext"> 要解密数据,长度不限 </param>
''' <returns> 解密后的数据 </returns>
Public Shared Function PublicKeyDecryptEx(ByVal publicKey As String, ByVal ciphertext As String) As String
If String.IsNullOrEmpty(ciphertext) Then
Return String.Empty
End If If Not isKeyValid(publicKey) Then
Throw New ArgumentException("Invalid Public Key")
End If '加载公钥
Dim provider = RSA.Create
provider.FromXml(publicKey)
Dim keyParameter = DotNetCoreUtilities.GetKeyParmeter(provider.ToPem(False)) Dim c As IBufferedCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding")
'第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
c.Init(False, keyParameter) Dim inputBytes = Convert.FromBase64String(ciphertext)
Dim bufferSize As Integer = provider.KeySize /
Dim buffer = New Byte(bufferSize - ) {}
Dim outputStream As New MemoryStream()
Using inputStream As New MemoryStream(inputBytes)
Do
Dim readSize As Integer = inputStream.Read(buffer, , bufferSize)
If readSize <= Then
Exit Do
End If Dim temp = New Byte(readSize - ) {}
Array.Copy(buffer, , temp, , readSize)
Dim rawBytes = c.DoFinal(temp)
outputStream.Write(rawBytes, , rawBytes.Length)
Loop
End Using
Return Encoding.UTF8.GetString(outputStream.ToArray())
End Function
#End If
#End Region
End Class

扩展方法

 Imports System.Security.Cryptography
Imports System.Xml
Imports Org.BouncyCastle.Crypto.Parameters
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Math
Imports System.IO
Imports Org.BouncyCastle.OpenSsl
Imports Org.BouncyCastle.Security
Imports System.Text Friend Module RsaExtention <System.Runtime.CompilerServices.Extension>
Public Sub FromXml(ByVal rsa As RSA, ByVal xmlString As String)
Dim parameters As New RSAParameters()
Dim xmlDoc As New XmlDocument()
xmlDoc.LoadXml(xmlString)
If xmlDoc.DocumentElement.Name.Equals("RSAKeyValue") Then
For Each node As XmlNode In xmlDoc.DocumentElement.ChildNodes
Select Case node.Name
Case "Modulus"
parameters.Modulus = Convert.FromBase64String(node.InnerText)
Case "Exponent"
parameters.Exponent = Convert.FromBase64String(node.InnerText)
Case "P"
parameters.P = Convert.FromBase64String(node.InnerText)
Case "Q"
parameters.Q = Convert.FromBase64String(node.InnerText)
Case "DP"
parameters.DP = Convert.FromBase64String(node.InnerText)
Case "DQ"
parameters.DQ = Convert.FromBase64String(node.InnerText)
Case "InverseQ"
parameters.InverseQ = Convert.FromBase64String(node.InnerText)
Case "D"
parameters.D = Convert.FromBase64String(node.InnerText)
End Select
Next node
Else
Throw New Exception("Invalid XML RSA key.")
End If rsa.ImportParameters(parameters)
End Sub <System.Runtime.CompilerServices.Extension>
Public Function ToXml(ByVal rsa As RSA, ByVal includePrivateParameters As Boolean) As String
Dim parameters As RSAParameters = rsa.ExportParameters(includePrivateParameters) Dim ret As String
If includePrivateParameters Then
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>",
Convert.ToBase64String(parameters.Modulus),
Convert.ToBase64String(parameters.Exponent),
Convert.ToBase64String(parameters.P),
Convert.ToBase64String(parameters.Q),
Convert.ToBase64String(parameters.DP),
Convert.ToBase64String(parameters.DQ),
Convert.ToBase64String(parameters.InverseQ),
Convert.ToBase64String(parameters.D))
Else
ret = String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(parameters.Modulus),
Convert.ToBase64String(parameters.Exponent))
End If
Return formatXml(ret)
End Function Private Function formatXml(ByVal sUnformattedXml As String) As String
Dim xd As New XmlDocument()
xd.LoadXml(sUnformattedXml)
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)
Dim xtw As XmlTextWriter = Nothing
Try
xtw = New XmlTextWriter(sw)
xtw.Formatting = Formatting.Indented
xtw.Indentation =
xtw.IndentChar = Char.Parse(vbTab)
xd.WriteTo(xtw)
Finally
If xtw IsNot Nothing Then
xtw.Close()
End If
End Try
Return sb.ToString()
End Function <System.Runtime.CompilerServices.Extension>
Public Sub FromPem(ByVal rsa As RSA, pemString As String)
Const FLAG_PUBLIC As String = "-----BEGIN PUBLIC KEY-----"
Const FLAG_PRIVATE As String = "-----BEGIN PRIVATE KEY-----" Dim content As String = pemString If pemString.StartsWith(FLAG_PUBLIC) Then
content = content.Replace(FLAG_PUBLIC, "").Replace("-----END PUBLIC KEY-----", "").Replace(vbCrLf, "")
Dim publicKeyParam As RsaKeyParameters = PublicKeyFactory.CreateKey(Convert.FromBase64String(content))
Dim xml As String = String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned))
rsa.FromXml(xml)
ElseIf pemString.StartsWith(FLAG_PRIVATE) Then
content = content.Replace(FLAG_PRIVATE, "").Replace("-----END PRIVATE KEY-----", "").Replace(vbCrLf, "")
Dim privateKeyParam As RsaPrivateCrtKeyParameters = PrivateKeyFactory.CreateKey(Convert.FromBase64String(content))
Dim parameters As New RSAParameters() With
{
.Modulus = privateKeyParam.Modulus.ToByteArrayUnsigned(),
.Exponent = privateKeyParam.PublicExponent.ToByteArrayUnsigned(),
.P = privateKeyParam.P.ToByteArrayUnsigned(),
.Q = privateKeyParam.Q.ToByteArrayUnsigned(),
.DP = privateKeyParam.DP.ToByteArrayUnsigned(),
.DQ = privateKeyParam.DQ.ToByteArrayUnsigned(),
.InverseQ = privateKeyParam.QInv.ToByteArrayUnsigned(),
.D = privateKeyParam.Exponent.ToByteArrayUnsigned()
}
rsa.ImportParameters(parameters)
Else
Throw New ArgumentException("pemString is not validate")
End If
End Sub <System.Runtime.CompilerServices.Extension>
Public Function ToPem(ByVal rsa As RSA, ByVal includePrivateParameters As Boolean) As String
Dim ret As String = String.Empty
If includePrivateParameters Then
Return exportPrivateKey(rsa)
Else
Return exportPublicKey(rsa)
End If
End Function ''' <summary>
''' 输出PEM格式公钥
''' </summary>
''' <param name="rsa"></param>
''' <returns></returns>
Private Function exportPublicKey(ByVal rsa As RSA) As String
Dim outputStream As TextWriter = New StringWriter() Dim parameters = rsa.ExportParameters(False)
Using stream = New MemoryStream()
Dim writer = New BinaryWriter(stream)
writer.Write(CByte(&H30)) ' SEQUENCE
Using innerStream = New MemoryStream()
Dim innerWriter = New BinaryWriter(innerStream)
innerWriter.Write(CByte(&H30)) ' SEQUENCE
encodeLength(innerWriter, )
innerWriter.Write(CByte(&H6)) ' OBJECT IDENTIFIER
Dim rsaEncryptionOid = New Byte() {&H2A, &H86, &H48, &H86, &HF7, &HD, &H1, &H1, &H1}
encodeLength(innerWriter, rsaEncryptionOid.Length)
innerWriter.Write(rsaEncryptionOid)
innerWriter.Write(CByte(&H5)) ' NULL
encodeLength(innerWriter, )
innerWriter.Write(CByte(&H3)) ' BIT STRING
Using bitStringStream = New MemoryStream()
Dim bitStringWriter = New BinaryWriter(bitStringStream)
bitStringWriter.Write(CByte(&H0)) ' # of unused bits
bitStringWriter.Write(CByte(&H30)) ' SEQUENCE
Using paramsStream = New MemoryStream()
Dim paramsWriter = New BinaryWriter(paramsStream)
encodeIntegerBigEndian(paramsWriter, parameters.Modulus) ' Modulus
encodeIntegerBigEndian(paramsWriter, parameters.Exponent) ' Exponent
Dim paramsLength = CInt(paramsStream.Length)
encodeLength(bitStringWriter, paramsLength)
bitStringWriter.Write(paramsStream.GetBuffer(), , paramsLength)
End Using
Dim bitStringLength = CInt(bitStringStream.Length)
encodeLength(innerWriter, bitStringLength)
innerWriter.Write(bitStringStream.GetBuffer(), , bitStringLength)
End Using
Dim length = CInt(innerStream.Length)
encodeLength(writer, length)
writer.Write(innerStream.GetBuffer(), , length)
End Using Dim base64 = Convert.ToBase64String(stream.GetBuffer(), , CInt(stream.Length)).ToCharArray()
outputStream.WriteLine("-----BEGIN PUBLIC KEY-----")
For i = To base64.Length - Step
outputStream.WriteLine(base64, i, Math.Min(, base64.Length - i))
Next i
outputStream.WriteLine("-----END PUBLIC KEY-----")
End Using Return outputStream.ToString
End Function ''' <summary>
''' 输出PEM格式私钥
''' </summary>
''' <param name="rsa"></param>
Private Function exportPrivateKey(ByVal rsa As RSA) As String
'If csp.PublicOnly Then
' Throw New ArgumentException("CSP does not contain a private key", "csp")
'End If Dim outputStream As TextWriter = New StringWriter()
Dim parameters = rsa.ExportParameters(True)
If parameters.D Is Nothing Then
Throw New ArgumentException("object does not contain a private key", "csp")
End If
Using stream = New MemoryStream()
Dim writer = New BinaryWriter(stream)
writer.Write(CByte(&H30)) ' SEQUENCE
Using innerStream = New MemoryStream()
Dim innerWriter = New BinaryWriter(innerStream)
encodeIntegerBigEndian(innerWriter, New Byte() {&H0}) ' Version
encodeIntegerBigEndian(innerWriter, parameters.Modulus)
encodeIntegerBigEndian(innerWriter, parameters.Exponent)
encodeIntegerBigEndian(innerWriter, parameters.D)
encodeIntegerBigEndian(innerWriter, parameters.P)
encodeIntegerBigEndian(innerWriter, parameters.Q)
encodeIntegerBigEndian(innerWriter, parameters.DP)
encodeIntegerBigEndian(innerWriter, parameters.DQ)
encodeIntegerBigEndian(innerWriter, parameters.InverseQ)
Dim length = CInt(innerStream.Length)
encodeLength(writer, length)
writer.Write(innerStream.GetBuffer(), , length)
End Using Dim base64 = Convert.ToBase64String(stream.GetBuffer(), , CInt(stream.Length)).ToCharArray() outputStream.WriteLine("-----BEGIN RSA PRIVATE KEY-----")
' Output as Base64 with lines chopped at 64 characters
For i = To base64.Length - Step
outputStream.WriteLine(base64, i, Math.Min(, base64.Length - i))
Next i
outputStream.WriteLine("-----END RSA PRIVATE KEY-----")
End Using Return outputStream.ToString
End Function Private Sub encodeLength(ByVal stream As BinaryWriter, ByVal length As Integer)
If length < Then
Throw New ArgumentOutOfRangeException("length", "Length must be non-negative")
End If
If length < &H80 Then
' Short form
stream.Write(CByte(length))
Else
' Long form
Dim temp = length
Dim bytesRequired =
Do While temp >
temp >>=
bytesRequired +=
Loop
stream.Write(CByte(bytesRequired Or &H80))
For i = bytesRequired - To Step -
stream.Write(CByte(length >> ( * i) And &HFF))
Next i
End If
End Sub Private Sub encodeIntegerBigEndian(ByVal stream As BinaryWriter, ByVal value() As Byte, Optional ByVal forceUnsigned As Boolean = True)
stream.Write(CByte(&H2)) ' INTEGER
Dim prefixZeros =
For i = To value.Length -
If value(i) <> Then
Exit For
End If
prefixZeros +=
Next i
If value.Length - prefixZeros = Then
encodeLength(stream, )
stream.Write(CByte())
Else
If forceUnsigned AndAlso value(prefixZeros) > &H7F Then
' Add a prefix zero to force unsigned if the MSB is 1
encodeLength(stream, value.Length - prefixZeros + )
stream.Write(CByte())
Else
encodeLength(stream, value.Length - prefixZeros)
End If
For i = prefixZeros To value.Length -
stream.Write(value(i))
Next i
End If
End Sub End Module Friend Module DotNetCoreUtilities
''' <summary>
''' 返回 RSA 对象的 密钥对参数对象
''' </summary>
''' <param name="provider"></param>
''' <returns>
''' 用私钥初始化的 RSA 对象 - 返回有效的公钥和私钥密钥对
''' 用公钥初始化的 RSA 对象 - 返回 有效的公钥 和 无效的私钥组成的密钥对
''' </returns>
Public Function GetKeyPair(ByVal provider As RSA) As AsymmetricCipherKeyPair
Dim p As RSAParameters
Dim rkpPrivate As RsaKeyParameters Try
p = provider.ExportParameters(True)
rkpPrivate = New RsaKeyParameters(True, New BigInteger(, p.Modulus), New BigInteger(p.D)) '//PrivateKey 实际使用
Catch ex As Exception
p = provider.ExportParameters(False)
rkpPrivate = New RsaKeyParameters(True, BigInteger.One, BigInteger.One) '//PrivateKey 实际不使用
End Try Dim rpkPublic As New RsaKeyParameters(False, New BigInteger(, p.Modulus), New BigInteger(p.Exponent))
Dim keyPair As New AsymmetricCipherKeyPair(rpkPublic, rkpPrivate)
Return keyPair
End Function ''' <summary>
''' 通过 PEM 格式的私钥返回 密钥对参数对象
''' </summary>
''' <param name="privateKey">PEM 格式的私钥</param>
''' <returns></returns>
Public Function GetKeyPair(ByVal privateKey As String) As AsymmetricCipherKeyPair
Dim keyPair As AsymmetricCipherKeyPair
Using StringReader As New StringReader(privateKey)
Dim pemReader = New PemReader(StringReader)
keyPair = CType(pemReader.ReadObject, AsymmetricCipherKeyPair)
End Using
Return keyPair
End Function ''' <summary>
''' 通过 PEM 格式的公钥返回 密钥参数对象
''' </summary>
''' <param name="publicKey">PEM 格式的公钥</param>
''' <returns></returns>
Public Function GetKeyParmeter(ByVal publicKey As String) As AsymmetricKeyParameter
Dim ret As AsymmetricKeyParameter
Using StringReader As New StringReader(publicKey)
Dim pemReader = New PemReader(StringReader)
ret = CType(pemReader.ReadObject, AsymmetricKeyParameter)
End Using
Return ret
End Function
End Module

最后是调用代码示例:

         Dim ciphertext As String = RSAHelper.PublicKeyEncryptEx(RSAHelper.PublicKey, plaintext)
Console.WriteLine("===== ciphertext.Length={0}, PublicKeyEncypt Result:", ciphertext.Length)
Console.WriteLine(ciphertext)
Dim newData As String = RSAHelper.PrivateKeyDecryptEx(RSAHelper.PrivateKey, ciphertext)
Console.WriteLine("===== PrivateKeyDecrypt Result:")
Console.WriteLine(newData.Equals(plaintext))
Console.WriteLine("==============================================")
Console.WriteLine()
ciphertext = RSAHelper.PrivateKeyEncryptEx(RSAHelper.PrivateKey, plaintext)
Console.WriteLine("ciphertext.Length={0}, PrivateKeyEncypt Result:", ciphertext.Length)
Console.WriteLine(ciphertext)
newData = RSAHelper.PublicKeyDecryptEx(RSAHelper.PublicKey, ciphertext)
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 私钥加密工具类的相关教程结束。

《可用的 .net core 支持 RSA 私钥加密工具类.doc》

下载本文的Word格式文档,以方便收藏与打印。