.NET Core 使用RSA算法 加密/解密/签名/验证签名 【VB.net翻译版】


感谢晓晨的C#版《.NET Core 使用RSA算法 加密/解密/签名/验证签名》

为了便于大家学习,翻译成了VB版,并测试通过

原文地址:https://cloud.tencent.com/developer/article/1151210

  1 Imports System.IO
  2 Imports System.Security.Cryptography
  3 Imports System.Text
  4 
  5 ''' 
  6 ''' SA加解密 使用OpenSSL的公钥加密/私钥解密
  7 ''' https://cloud.tencent.com/developer/article/1151210
  8 ''' 
  9 Public Class Class_RSAHelper
 10     Private ReadOnly _privateKeyRsaProvider As RSA
 11     Private ReadOnly _publicKeyRsaProvider As RSA
 12     Private ReadOnly _hashAlgorithmName As HashAlgorithmName
 13     Private ReadOnly _encoding As Encoding
 14 
 15     ''' 
 16     ''' 
 17     ''' 
 18     ''' 加密算法类型 RSA SHA1;RSA2 SHA256 密钥长度至少为2048
 19     ''' 编码类型
 20     ''' 私钥
 21     ''' 公钥
 22     Public Sub New(rsaType As RSAType,
 23                    encoding As Encoding,
 24                    privateKey As String,
 25                    publicKey As String
 26                    )
 27         If rsaType = RSAType.RSA Then
 28             _hashAlgorithmName = HashAlgorithmName.SHA1
 29         Else
 30             _hashAlgorithmName = HashAlgorithmName.SHA256
 31         End If
 32 
 33         _encoding = encoding
 34 
 35         If Not String.IsNullOrEmpty(privateKey) Then
 36             _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey)
 37         End If
 38         If Not String.IsNullOrEmpty(publicKey) Then
 39             _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey)
 40         End If
 41     End Sub
 42 
 43 
 44 
 45     ''' 
 46     ''' 使用私钥签名
 47     ''' 
 48     ''' 原始数据
 49     ''' 
 50     Public Function Sign(data As String) As String
 51         Dim dataBytes As Byte() = _encoding.GetBytes(data)
 52         Dim signatureBytes = _privateKeyRsaProvider.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1)
 53         Return Convert.ToBase64String(signatureBytes)
 54     End Function
 55 
 56 
 57 
 58 
 59 
 60     ''' 
 61     ''' 使用公钥验证签名
 62     ''' 
 63     ''' 原始数据
 64     ''' 签名
 65     ''' 
 66     Public Function Verify(data As String, sign As String) As Boolean
 67 
 68         Dim dataBytes As Byte() = _encoding.GetBytes(data)
 69         Dim signBytes As Byte() = Convert.FromBase64String(sign)
 70 
 71         Return _publicKeyRsaProvider.VerifyData(dataBytes, signBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1)
 72     End Function
 73 
 74 
 75     ''' 
 76     ''' 解密
 77     ''' 
 78     ''' 
 79     ''' 
 80     Public Function Decrypt(cipherText As String) As String
 81 
 82         If IsNothing(_privateKeyRsaProvider) Then
 83             Throw New Exception("_privateKeyRsaProvider is null")
 84         End If
 85         Return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1))
 86     End Function
 87 
 88 
 89     ''' 
 90     ''' 加密
 91     ''' 
 92     ''' 
 93     ''' 
 94     Public Function Encrypt(text As String) As String
 95         If IsNothing(_publicKeyRsaProvider) Then
 96             Throw New Exception("_publicKeyRsaProvider is null")
 97         End If
 98         Return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1))
 99     End Function
100 
101 
102 
103 
104 
105     ''' 
106     ''' 使用私钥创建RSA实例
107     ''' 
108     ''' 
109     ''' 
110     Public Function CreateRsaProviderFromPrivateKey(privateKey As String) As RSA
111 
112         Dim privateKeyBits = Convert.FromBase64String(privateKey)
113         Dim RSA = System.Security.Cryptography.RSA.Create()
114         Dim RSAParameters = New RSAParameters()
115 
116         Using binr As BinaryReader = New BinaryReader(New MemoryStream(privateKeyBits))
117             Dim bt As Byte = 0
118             Dim twobytes As UShort = 0
119             twobytes = binr.ReadUInt16()
120 
121             If twobytes = &H8130 Then
122                 binr.ReadByte()
123             ElseIf twobytes = &H8230 Then
124                 binr.ReadInt16()
125             Else
126                 Throw New Exception("Unexpected value read binr.ReadUInt16()")
127             End If
128 
129             twobytes = binr.ReadUInt16()
130             If twobytes <> &H102 Then
131                 Throw New Exception("Unexpected version")
132             End If
133 
134             bt = binr.ReadByte()
135             If bt <> &H0 Then
136                 Throw New Exception("Unexpected value read binr.ReadByte()")
137             End If
138 
139             RSAParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr))
140             RSAParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr))
141             RSAParameters.D = binr.ReadBytes(GetIntegerSize(binr))
142             RSAParameters.P = binr.ReadBytes(GetIntegerSize(binr))
143             RSAParameters.Q = binr.ReadBytes(GetIntegerSize(binr))
144             RSAParameters.DP = binr.ReadBytes(GetIntegerSize(binr))
145             RSAParameters.DQ = binr.ReadBytes(GetIntegerSize(binr))
146             RSAParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr))
147         End Using
148 
149         RSA.ImportParameters(RSAParameters)
150         Return RSA
151     End Function
152 
153 
154 
155     ''' 
156     ''' 使用公钥创建RSA实例
157     ''' 
158     ''' 
159     ''' 
160     Public Function CreateRsaProviderFromPublicKey(publicKeyString As String) As RSA
161 
162         ' encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
163         Dim seqOid As Byte() = {&H30, &HD, &H6, &H9, &H2A, &H86, &H48, &H86, &HF7, &HD, &H1, &H1, &H1, &H5, &H0}
164         Dim seq(15) As Byte
165 
166         Dim x509Key = Convert.FromBase64String(publicKeyString)
167 
168         ' ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
169         Using mem As MemoryStream = New MemoryStream(x509Key)
170             Using binr As BinaryReader = New BinaryReader(mem)  'wrap Memory Stream with BinaryReader for easy reading
171                 Dim bt As Byte = 0
172                 Dim twobytes As UShort = 0
173 
174                 twobytes = binr.ReadUInt16()
175                 If twobytes = &H8130 Then ' Data Then read As little endian order (actual data order For Sequence Is 30 81)
176                     binr.ReadByte()    'advance 1 Byte
177                 ElseIf twobytes = &H8230 Then
178                     binr.ReadInt16()   'advance 2 bytes
179                 Else
180                     Return Nothing
181                 End If
182 
183                 seq = binr.ReadBytes(15)       'read the Sequence OID
184                 If CompareBytearrays(seq, seqOid) = False Then ' make Then sure Sequence For OID Is correct
185                     Return Nothing
186                 End If
187 
188 
189                 twobytes = binr.ReadUInt16()
190                 If twobytes = &H8103 Then ' Data Then read As little endian order (actual data order For Bit String Is 03 81)
191                     binr.ReadByte()    'advance 1 Byte
192                 ElseIf twobytes = &H8203 Then
193                     binr.ReadInt16()   'advance 2 bytes
194                 Else
195                     Return Nothing
196                 End If
197 
198 
199                 bt = binr.ReadByte()
200                 If bt <> &H0 Then ' expect Then null Byte Next
201                     Return Nothing
202                 End If
203 
204                 twobytes = binr.ReadUInt16()
205                 If twobytes = &H8130 Then ' Data Then read As little endian order (actual data order For Sequence Is 30 81)
206                     binr.ReadByte()    'advance 1 Byte
207                 ElseIf twobytes = &H8230 Then
208                     binr.ReadInt16()   'advance 2 bytes
209                 Else
210                     Return Nothing
211                 End If
212 
213                 twobytes = binr.ReadUInt16()
214                 Dim lowbyte As Byte = &H0
215                 Dim highbyte As Byte = &H0
216 
217                 If twobytes = &H8102 Then ' Data Then read As little endian order (actual data order For Integer Is 02 81)
218                     lowbyte = binr.ReadByte()  ' read Next bytes which Is bytes In modulus
219                 ElseIf twobytes = &H8202 Then
220                     highbyte = binr.ReadByte() 'advance 2 bytes
221                     lowbyte = binr.ReadByte()
222                 Else
223                     Return Nothing
224                 End If
225 
226                 Dim modint As Byte() = {lowbyte, highbyte, &H0, &H0}   'reverse Byte order since asn.1 key uses big endian order
227                 Dim modsize As Integer = BitConverter.ToInt32(modint, 0)
228 
229                 Dim firstbyte As Integer = binr.PeekChar()
230                 If firstbyte = &H0 Then
231                     'if first byte (highest order) of modulus Is zero, don't include it
232                     binr.ReadByte()    'skip this null Byte
233                     modsize -= 1   'reduce modulus buffer size by 1
234                 End If
235 
236                 Dim modulus As Byte() = binr.ReadBytes(modsize)   'read the modulus bytes
237                 If binr.ReadByte() <> &H2 Then ' expect Then an Integer For the exponent data
238                     Return Nothing
239                 End If
240 
241                 Dim expbytes As Integer = binr.ReadByte()        ' should only need one Byte For actual exponent data (For all useful values)
242                 Dim exponent As Byte() = binr.ReadBytes(expbytes)
243 
244                 ' ------- create RSACryptoServiceProvider instance And initialize with public key -----
245                 Dim RSA = System.Security.Cryptography.RSA.Create()
246                 Dim rsaKeyInfo As RSAParameters = New RSAParameters With {
247                     .Modulus = modulus,
248                     .Exponent = exponent
249                 }
250                 RSA.ImportParameters(rsaKeyInfo)
251 
252                 Return RSA
253             End Using
254 
255         End Using
256     End Function
257 
258 
259 
260 
261 
262     ''' 
263     ''' 导入密钥算法
264     ''' 
265     ''' 
266     ''' 
267     Private Function GetIntegerSize(binr As BinaryReader) As Integer
268 
269         Dim bt As Byte = 0
270         Dim count As Integer = 0
271         bt = binr.ReadByte()
272         If bt <> &H2 Then
273             Return 0
274         End If
275 
276         bt = binr.ReadByte()
277 
278         If bt = &H81 Then
279             count = binr.ReadByte()
280         Else
281             If bt = &H82 Then
282                 Dim highbyte = binr.ReadByte()
283                 Dim lowbyte = binr.ReadByte()
284                 Dim modint As Byte() = {lowbyte, highbyte, &H0, &H0}
285                 count = BitConverter.ToInt32(modint, 0)
286             Else
287                 count = bt
288             End If
289         End If
290 
291         While binr.ReadByte() = &H0
292             count -= 1
293         End While
294         binr.BaseStream.Seek(-1, SeekOrigin.Current)
295         Return count
296     End Function
297 
298 
299     Private Function CompareBytearrays(a As Byte(), b As Byte()) As Boolean
300 
301         If (a.Length <> b.Length) Then
302             Return False
303         End If
304 
305         Dim i As Integer = 0
306         For Each c As Byte In a
307             If c <> b(i) Then
308                 Return False
309             End If
310             i += 1
311         Next
312 
313         Return True
314     End Function
315 
316 
317 
318     ''' 
319     ''' RSA算法类型
320     ''' 
321     Public Enum RSAType
322 
323         ''' 
324         ''' SHA1
325         ''' 
326         RSA = 0
327         ''' 
328         ''' RSA2 密钥长度至少为2048
329         ''' SHA256
330         ''' 
331         RSA2
332     End Enum
333 End Class