[VB.net] - Verschlüsselung nach PHP

  • PHP

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von KingOsirisOne.

    [VB.net] - Verschlüsselung nach PHP

    Sehr geehrte Schwarm-Wissende,

    ich komme derzeit leider nicht weiter. Egal, wie ich im Netz suche und bei StackOverflow und ähnlichen lande, ich bekomme keine so rechte Lösung hin.

    Ich hatte vor geraumer Zeit mal Code gefunden, umgesetzt, welcher mir bei kleinen Tools bei der Verschlüsselung von Daten helfen sollte.. funktioniert auch.

    Ich möchte diese verschlüsselten Daten nun aber auch gern in PHP verwenden und mit diesen arbeiten. Ich bekomme sie in PHP aber nicht mal entschlüsselt.. weder per Mcrypt-Erweiterung, noch per OpenSSL.

    In VB.net arbeite ich bspw. mit diesen Funktionen zum ver- und entschlüsseln:

    VB.NET-Quellcode

    1. Public Function Encrypt(ByVal input As String, ByVal pass As String) As String
    2. Dim AES As New System.Security.Cryptography.RijndaelManaged
    3. Dim Hash_AES As New System.Security.Cryptography.SHA256Cng
    4. Dim encrypted As String = ""
    5. Try
    6. Dim hash(31) As Byte
    7. Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.Default.GetBytes(pass))
    8. Array.Copy(temp, 0, hash, 0, 16)
    9. Array.Copy(temp, 0, hash, 15, 16)
    10. AES.Key = hash
    11. AES.Mode = Security.Cryptography.CipherMode.ECB
    12. Dim DESEncrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateEncryptor
    13. Dim Buffer As Byte() = System.Text.ASCIIEncoding.Default.GetBytes(input)
    14. encrypted = Convert.ToBase64String(DESEncrypter.TransformFinalBlock(Buffer, 0, Buffer.Length))
    15. Return encrypted
    16. Catch ex As Exception
    17. Return ex.Message
    18. End Try
    19. End Function


    VB.NET-Quellcode

    1. Public Function Decrypt(ByVal input As String, ByVal pass As String) As String
    2. Dim AES As New System.Security.Cryptography.RijndaelManaged
    3. Dim Hash_AES As New System.Security.Cryptography.SHA256Cng
    4. Dim decrypted As String = ""
    5. Try
    6. Dim hash(31) As Byte
    7. Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.Default.GetBytes(pass))
    8. Array.Copy(temp, 0, hash, 0, 16)
    9. Array.Copy(temp, 0, hash, 15, 16)
    10. AES.Key = hash
    11. AES.Mode = Security.Cryptography.CipherMode.ECB
    12. Dim DESDecrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateDecryptor
    13. Dim Buffer As Byte() = Convert.FromBase64String(input)
    14. decrypted = System.Text.ASCIIEncoding.Default.GetString(DESDecrypter.TransformFinalBlock(Buffer, 0, Buffer.Length))
    15. Return decrypted
    16. Catch ex As Exception
    17. Return ex.Message
    18. End Try
    19. End Function


    Es ist mir aber bisher kein Weg gelungen, anhand dieser Funktionen verschlüsselte Daten in PHP wieder zu entschlüsseln. Und am Ende möchte ich natürlich auch gern per PHP Daten nach gleichem Prinzip verschlüsseln können um wiederum in meinem eigentlichen Tool damit weiter arbeiten zu können.

    Ich hoffe, seien es nur Verweise hier im Forum, dass ihr mir weiterhelfen könnt. Vllt. ist ja schon mein Ansatz in VB falsch.

    Danke Euch und einen schönen 3ten Advent!

    Sascha
    Hi,

    welche Verschlüsselung nutzt du denn? Du könntest zB AES-256-CBC verwenden, es müssen nur die selben encryption keys benutzt werden und dann wird bei identischer Implementierung des Algorithmus die Ent- und Verschlüsselung auch in beiden Umgebungen funktionieren.


    Link :thumbup:
    Hello World
    Guten Morgen @KingOsirisOne

    Was mir gleich aufgefallen ist.

    Manchmal liegt es daran, dass der BlockSize unterschiedlich ist.
    Sofern es mir recht ist, ist der BlockSize auf der C#-Seite standardmässig 128 Bit eingestellt, während auf der PhP-Seite der BlockSize auf 256 Bit standardmässig eingestellt ist. Die müssen auf jedenfall übereinstimmen.

    Dann verwendest du ECB als CipherMode. Ich nehme an, dass die Verschlüsselung in dem Falle nicht stark sein muss. Auch verwendest du keinen Salt, was meiner Meinung nicht gemacht werden sollte, auch wenn die Verschlüsselung schwach sein soll, weil ohne Salz, ist sie dann wirklich sehr schwach.

    Dann sollte beachtet werden, dass der IV (InitialisierungsVektor im Normalfall 128 Bit) wie auch der Key (im Normalfall 256 Bit) beim Verschlüsseln wie auch beim Entschlüsseln gleich sein müssen. Dein IV z.B. wird nirgendswo festgehalten. Bei einer Neuinstanzierung von RijndaelManaged , werden beide Schlüssel zufällig neu generiert(!!).

    Vielleicht schaust du kurz hier rein, auch wenn die Vorgehensweise ein bisschen veraltet ist. Ich glaube ich habe hier sogar auch den RijndaelManaged verwendet. Als Basis für das Kennenlernen von Verschlüsselungen sollte das aber reichen.
    3-dimensionales String-Array umwandeln in "hier könnte Ihre Lösung stehen"?

    EDIT: Es wäre noch gut, wenn du angeben würdest, mit welcher Vb.Net-Version du arbeitest. Ich sehe gerade, dass RijndaelManaged obsolete ist. Alternative wäre AesCng, jedoch nur mit BlockSize 128 / CBC

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „exc-jdbi“ () aus folgendem Grund: Angepasst. Bei der letzten Korrektur sind ein paar Textabschnitte irgendwie verloren gegangen beim Abspeichern. :thumbdown:​

    Ich danke Euch beiden jeweils für den Input, werde das Thema aber nun wahrscheinlich doch erst mal eher in das VBNet-Forum schieben lassen müssen.

    Ich habe mir die Hinweise von @exc-jdbi angeschaut und letztlich auch noch mal herumgesucht. Es erschien mir schon wichtig, dass die Verschlüsselung trotz allem sicher ist, weswegen ich auf CBC wechseln wollte. Wenn ich das mache, muss ich aber scheinbar jedes Mal erst mal alle Daten entschlüsseln um bspw. Änderungen an vorhandenen Datensätzen speichern zu wollen.

    Ein Beispiel: Ich prüfe beim Start einer Anwendung, ob ein Benutzer und Benutzergruppen existieren. Wenn nicht, sollen erst mal die Benutzergruppen angelegt werden und dann ein Benutzer. In der Admingruppe. Die ID der Admingruppe kann je nach Fall variieren und somit mache ich auf der Datenbank eine kleine verschachtelte Abfrage und in dem Moment ist der Gruppenname verschlüsselt schon nicht mehr der gleiche, wie in dem Moment, wo ich den Benutzer anlege.

    Der IV scheint mir hier etwas in die Quere zu kommen. Ich beschäftige mich mit der Thematik, im Rahmen meines Hobbys, erst seit Kurzem. Daher stelle ich mir im Falle Verschlüsselung wahrscheinlich gerade erst recht dumm an.

    Ich schaue mal, wohin ich komme, oder ob ich es dann doch bei meiner Lösung belassen (muss), mit EBC.

    Danke Euch auf jeden Fall!!

    P.s.: Ach so.. ich Nutzer VB.Net mir Visual Studio 2019, aber in der Community Edition.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „KingOsirisOne“ ()

    @KingOsirisOne

    Da führt wohl kein anderer Weg mehr vorbei.

    Wenn die Daten schon mit ECB verkryptet sind, dann müssen die natürlich zuerst wieder entkryptet werden, um auf die CBC-Ciphermode zu wechseln.

    C# ist natürlich identisch vergleichbar mit Vb.net. Sind beide DotNet. Was die Verschlüsselungen jedoch in den höheren Versionen angeht, weiss ich jetzt nicht, wie es in Vb.Net ist. RijndaelManaged gibt es aber sicher auch als Vb.Net in VS2019.

    Das Problem bei deinem Code ist, dass du nur den Key bewusst zuweist. Deine IV muss aber auch wieder bei der Entschlüsselung der gleiche sein, sonst wirst du die Daten nie wieder entschlüsseln können (BackUp der unverkrypteten Daten hoffentlich gemacht), weil sobald RijndaelManaged wieder Neuinstanziert wird, werden Key wie auch IV neu generiert. D.H. Bei deinem Code wäre nur der Key wieder der gleiche, weil er zugewiesen wird. Der IV hingegen ist nicht mehr der gleiche, und irgendeine Zuweisung von der ursprünglichen IV findet man in deinem Code nicht.
    Mit obigen Code frage ich mich also, wie du deine Daten richtig entschlüsseln kannst.

    Hier noch ein Link
    itsecblog.de/haeufige-schwachs…schluesselung-durch-apps/

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hey @exc-jdbi,

    danke dir für deine Antwort. Tatsächlich muss ich sagen, dass ich den verwendeten Code mal im Netz fand und er arbeitet rein mit meinem Key und zerlegt den für sich. Greift daher auf keinen IV zurück. Aber der Code scheint eben etwas zwar nützliches, aber für bzw. in anderen Umgebungen schwer nachstellbares abzuarbeiten und auszugeben. Aber der Code funktioniert. Er ver- und entschlüsselt zu beliebiger Zeit die Daten.

    Dein Ansatz, das Ganze sauberer zu gestalten und nach gängigen Wegen vorzugehen ist schon vollkommen richtig. Derzeit teste ich das Ganze auch nur in einer "Testanwendung", weshalb es noch nicht so schlimm ist, dass ich zuvor per EBC gearbeitet habe. Bei der CBC-Variante ärgert mich ein wenig, dass in den Strings der IV-Teil letztlich immer zu erkennen ist. Das is bei obigen Code nicht der Fall, gibt ja keinen IV. Mir macht das dann Sorge, dass es doch einfacher ist für Fremde die Daten zu entschlüsseln. Aber ich bin auch noch nicht so sehr in der Materie an sich drin.

    Deinen Beitrag von ITSec werde ich mir auch mal zu Gemüte führen. Danke dafür.

    Im Netz war ich noch auf folgenden Code gestoßen:

    VB.NET-Quellcode

    1. Private Function AESEncryptStringToBase64(strPlainText As String, strKey As String) As String
    2. Dim Algo As RijndaelManaged = RijndaelManaged.Create()
    3. With Algo
    4. .BlockSize = 128
    5. .FeedbackSize = 128
    6. .KeySize = 256
    7. .Mode = CipherMode.CBC
    8. .IV = Guid.NewGuid().ToByteArray()
    9. .Key = Encoding.ASCII.GetBytes(strKey)
    10. End With
    11. Using Encryptor As ICryptoTransform = Algo.CreateEncryptor()
    12. Using MemStream As New MemoryStream
    13. Using CryptStream As New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
    14. Using Writer As New StreamWriter(CryptStream)
    15. Writer.Write(strPlainText)
    16. End Using
    17. AESEncryptStringToBase64 = Convert.ToBase64String(Algo.IV.Concat(MemStream.ToArray()).ToArray())
    18. End Using
    19. End Using
    20. End Using
    21. End Function
    22. Private Function AESDecryptBase64ToString(strCipherText As String, strKey As String) As String
    23. Dim arrSaltAndCipherText As Byte() = Convert.FromBase64String(strCipherText)
    24. Dim Algo As RijndaelManaged = RijndaelManaged.Create()
    25. With Algo
    26. .BlockSize = 128
    27. .FeedbackSize = 128
    28. .KeySize = 256
    29. .Mode = CipherMode.CBC
    30. .IV = arrSaltAndCipherText.Take(16).ToArray()
    31. .Key = Encoding.ASCII.GetBytes(strKey)
    32. End With
    33. Using Decryptor As ICryptoTransform = Algo.CreateDecryptor()
    34. Using MemStream As New MemoryStream(arrSaltAndCipherText.Skip(16).ToArray())
    35. Using CryptStream As New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)
    36. Using Reader As New StreamReader(CryptStream)
    37. AESDecryptBase64ToString = Reader.ReadToEnd()
    38. End Using
    39. End Using
    40. End Using
    41. End Using
    42. End Function


    Aber auch hier.. der IV wird anhand GUID dynamisch erstellt und spätestens beim nächsten Start haut es mit dem sauberen Entschlüsseln nicht mehr hin, da ich den IV zum Zeitpunkt der Verschlüsselung ja nicht mehr kenne. Das verwirrt mich alles etwas.

    Mal sehen, ob ich da noch dahinter steige...

    Beste Grüße

    KingOsirisOne schrieb:

    Convert.ToBase64String(Algo.IV.Concat(MemStream.ToArray()).ToArray())


    Hier wird doch der IV mit dem MemoryStream verkettet, heist, die ersten 16 Bytes in der ganzen Kette die zu einem Base64 String konvertiert werden sind der IV, der ist also da drin.

    Beim decrypten .IV = arrSaltAndCipherText.Take(16).ToArray() wird der IV aus dem byte aray vom Base64 string genutzt. Die ersten 16 Bytes!

    Und hier: Using MemStream As New MemoryStream(arrSaltAndCipherText.Skip(16).ToArray()) sieht man das die ersten 16 Bytes(welche der IV sind) ausgelassen werden.

    Das ich den Code von SO kenne, kopier ich mal den PHP Code von dort zm vergleichen, da wird das auch so gehandhabt. Der IV ist eingebaut.$ivCiphertext = $iv . $ciphertext; und $iv = substr($ivCiphertext, 0, 16);

    PHP-Quellcode

    1. function encrypt($key, $plaintext){
    2. $iv = random_bytes(16);
    3. $ciphertext = openssl_encrypt($plaintext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    4. $ivCiphertext = $iv . $ciphertext;
    5. $ivCiphertextB64 = base64_encode($ivCiphertext);
    6. return $ivCiphertextB64;
    7. }
    8. function decrypt($key, $ivCiphertextB64){
    9. $ivCiphertext = base64_decode($ivCiphertextB64);
    10. $iv = substr($ivCiphertext, 0, 16);
    11. $ciphertext = substr($ivCiphertext, 16);
    12. $decryptedData = openssl_decrypt($ciphertext, "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv);
    13. return $decryptedData;
    14. }

    Danke dir @Takafusa!

    Beim zweiten Code ja, genau. Da kommt ein IV vor. Beim zuerst geposteten von mir nicht. Das passt soweit.

    Der IV wird aus einer GUID immer wieder neu generiert und verkettet. Der dynamische IV ist auch super und sicherer, aber bspw. habe ich durch diese Dynamik das Problem, dass ich bspw. alle Datensätze einer Tabelle durchgehen und zumindest bestimmte Felder entschlüsseln muss, um bspw. die Daten eines bestimmten Benutzers ausgeworfen zu bekommen. Der gleiche Benutzer(name) bekommt ja jedes Mal einen anderen gecrypteten Wert..

    Persönlich kann ich mir nicht vorstellen, dass der Weg so gehen soll.. jedes Mal eine ganze Tabelle zu entschlüsseln um die Zeilen dann durchzugehen, auf der Suche nach den benötigten Daten. Aber ich finde aktuell keinen anderen Weg, unter Verwendung des dynamischen IV. Oder ich sehe den Wald vor lauter Bäumen nicht.

    Den PHP-Code werde ich mal ausprobieren.. notfalls erst mal mit statischen IV. Sieht auf jeden Fall plausibel aus. Danke dir für den Link.

    KingOsirisOne schrieb:

    Danke dir für den Link.


    Müsstest du vermutlich kennen, denn der VB Code auf der Seite ist identisch mit dem, den du gepostet hast.(kann natürlich auch von woanders stammen)

    Also wenn ich dich richtig verstehe, willst du im verschlüsselten was suchen. Da du das als base64string speicherst, musst du den so oder so jedesmal zum string konvertieren. Ob der IV drin ist oder nicht. Oder verstehe ich dich falsch?
    Ich musste den Link jetzt selbst noch mal suchen.

    Den Code hatte ich letztlich von hier: vbdotnetforums.com/threads/aes-encryption-of-a-string.65799/

    Mit den von mir zuerst geposteten VB-Code, ohne IV, hatte es ja ausgereicht, wenn ich bspw. den Benutzer verschlüsselt habe und mit diesen String dann die Abfrage auf der Tabelle aufgebaut habe. Der Benutzer ist ja dann immer gleich verschlüsselt, wenn es ohne den dynamischen IV und per ECB ist.. dadurch habe ich mir erst alle Daten zum Benutzer geholt und im Anschluss beim befüllen der Felder etc. in der Anwendung die Daten entschlüsselt.

    Nun, mit dynamischen IV und per CBC ist der gleiche Plain-String verschlüsselt jedes Mal ein anderer. Soll so sein, habe ich verstanden. Ich finde es dann aber schwierig und irgendwie auch nicht leistungsschonend, wenn ich nun jedes Mal eine ganze Tabelle entschlüsseln muss, um dann die gesuchten Daten zu bekommen. Anders wird es aber halt nicht gehen.

    Also erst SELECT auf die gesamte Tabelle, per Schleife entschlüsseln und bei passenden, gesuchten Werten, die Daten in der Anwendung darstellen. :/

    Ist wahrscheinlich einfach nur die Bequemlichkeit die Abfragen anzupassen, wegen der ich mich nun so schwer tue und diesen Weg noch nicht so akzeptieren kann. :D
    Hi @KingOsirisOne

    Kannst natürlich auch mit dem TransformFinalBlock weiterhin arbeiten

    Schau es dir einfach mal an. Bin leider ab heute Nachtmittag bis Ende Jahr nicht mehr hier. Daher stell ich den Code gleich zur Verfügung.

    Gruss exc-jdbi

    EDIT:Danke euch und dir auch einen guten Rutsch.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.IO
    4. Imports System.Text
    5. Imports System.Security.Cryptography
    6. 'In Net Core funkst nur BlockSize 128 Bit.
    7. 'Im FrameWork 4.7.1 kann der BlockSize auf 256 Bit gesetzt werden
    8. Public Module TestRijndaelManaged
    9. Private CryptData As CryptoInfo
    10. Public Sub Main()
    11. Dim pw = "password"
    12. Dim plain = "my plaintext "
    13. plain = MultPlain(plain, 10000) '10000
    14. 'Ohne Authentifizierung und ohne Signierung
    15. Dim ciphertfb = EncryptionTfb(plain, pw)
    16. Dim deciphertfb = DecryptionTfb(ciphertfb, pw)
    17. Debug.Assert(plain.SequenceEqual(deciphertfb))
    18. 'Über die StreamVariante
    19. Dim decipherstream = DecryptionStream(ciphertfb, pw)
    20. Debug.Assert(plain.Length = decipherstream.Length)
    21. Debug.Assert(plain.SequenceEqual(decipherstream))
    22. End Sub
    23. Private Function CryptoData() As CryptoInfo
    24. 'Habe das jetzt extra separiert um zu zeigen was ich damit meine.
    25. 'Für die Sicherhheit wie auch die korrekte Nutzung
    26. 'dieser Daten ist der Entwickler verantwortlich.
    27. 'Da sie nicht im CipherCode integriert sind, müssen sie selber
    28. 'vom Entwickler irgendwie sicher abgespeichert werden.
    29. Dim salt = RngBytes(16) 'better 32
    30. Dim iteration = Rand.Next(5000, 15000)
    31. Dim hashes = {HashAlgorithmName.SHA256, HashAlgorithmName.SHA384, HashAlgorithmName.SHA512}
    32. Dim hashalgo = hashes(Rand.Next(hashes.Length))
    33. 'Dim iv wird später hinzugefügt
    34. Return New CryptoInfo() With
    35. {
    36. .Salt = salt,
    37. .Iteration = iteration,
    38. .HashAlgoName = hashalgo
    39. }
    40. End Function
    41. Private Function EncryptionTfb(plaintext As String, password As String) As String
    42. Dim pw = Encoding.UTF8.GetBytes(password)
    43. Dim plain = Encoding.UTF8.GetBytes(plaintext)
    44. CryptData = CryptoData()
    45. Dim cipherbytes = EncryptionTfb(plain, pw, CryptData)
    46. Return Convert.ToBase64String(cipherbytes)
    47. End Function
    48. Private Function DecryptionTfb(ciphertext As String, password As String) As String
    49. Dim pw = Encoding.UTF8.GetBytes(password)
    50. Dim cipher = Convert.FromBase64String(ciphertext)
    51. 'CryptData >>> muss schon vorhanden sein
    52. Dim decipherbytes = DecryptionTfb(cipher, pw, CryptData)
    53. Return Encoding.UTF8.GetString(decipherbytes)
    54. End Function
    55. Private Function DecryptionStream(ciphertext As String, password As String) As String
    56. Dim pw = Encoding.UTF8.GetBytes(password)
    57. Dim cipher = Convert.FromBase64String(ciphertext)
    58. 'CryptData >>> muss schon vorhanden sein
    59. Dim decipherbytes = DecryptionStream(cipher, pw, CryptData)
    60. Return Encoding.UTF8.GetString(decipherbytes)
    61. End Function
    62. Private Function EncryptionTfb(plaintext() As Byte, password() As Byte, cryptodata As CryptoInfo) As Byte()
    63. Dim errormsg = String.Empty
    64. Using aes As New RijndaelManaged With
    65. {
    66. .BlockSize = 256,
    67. .FeedbackSize = 256,
    68. .Mode = CipherMode.CBC,
    69. .Padding = PaddingMode.PKCS7
    70. }
    71. aes.GenerateIV()
    72. cryptodata.IV = aes.IV.ToArray 'kopie
    73. 'in VS2019 sollte schon die neuere Version drin sein
    74. 'd.h. ein HashAlgorithmName kann noch hinzugefügt werden.
    75. aes.Key = ToRfc2898(password, cryptodata.Salt, cryptodata.Iteration, aes.KeySize \ 8, cryptodata.HashAlgoName)
    76. Try
    77. Dim readsize = 0, cnt = -1
    78. Dim result() = New Byte() {}
    79. Dim size = Convert.ToInt32(2 ^ 16)
    80. Dim buffer = New Byte(size - 1) {}
    81. Using ce As ICryptoTransform = aes.CreateEncryptor
    82. Do
    83. cnt += 1
    84. Dim tmp = plaintext.Skip(cnt * readsize).Take(buffer.Length).ToArray
    85. readsize = tmp.Length
    86. Array.Copy(tmp, buffer, readsize)
    87. Dim enc = ce.TransformFinalBlock(buffer, 0, readsize)
    88. result = result.Concat(enc).ToArray()
    89. Loop While readsize = buffer.Length
    90. Return result
    91. End Using
    92. Catch ex As Exception
    93. errormsg = ex.Message
    94. Console.WriteLine(ex.Message)
    95. End Try
    96. End Using
    97. Throw New InvalidOperationException(errormsg)
    98. End Function
    99. Private Function DecryptionStream(ciphertext() As Byte, password() As Byte, cryptodata As CryptoInfo) As Byte()
    100. Dim errormsg = String.Empty
    101. Using aes As New RijndaelManaged With
    102. {
    103. .BlockSize = 256,
    104. .FeedbackSize = 256,
    105. .Mode = CipherMode.CBC,
    106. .Padding = PaddingMode.PKCS7
    107. }
    108. aes.IV = cryptodata.IV
    109. aes.Key = ToRfc2898(password, cryptodata.Salt, cryptodata.Iteration, aes.KeySize \ 8, cryptodata.HashAlgoName)
    110. Try
    111. Dim result() As Byte
    112. Dim readsize = 0, cnt = -1
    113. Dim cs As CryptoStream
    114. Dim size = Convert.ToInt32(2 ^ 16)
    115. Dim buffer = New Byte(size - 1) {}
    116. Dim cd = aes.CreateDecryptor(aes.Key, aes.IV)
    117. Using msi As New MemoryStream(ciphertext)
    118. Using mso As New MemoryStream()
    119. Do
    120. 'Den grundlegenden Stream (msi) nicht schliessen, auch wenn
    121. 'der CryptoStream (cs) komplett geschlossen wird. >> True
    122. 'In VS2019 sollte das jedoch möglich sein
    123. 'Using cs As New CryptoStream(msi, cd, CryptoStreamMode.Read, True)
    124. ' readsize = cs.Read(buffer, 0, buffer.Length)
    125. ' mso.Write(buffer, 0, readsize)
    126. 'End Using
    127. 'Im FrameWork 4.7.1 ist es nicht möglich den grundlegeneden Stream
    128. 'über New CryptoStream(...,True) offen zu halten, daher ein kleiner Kompromiss
    129. cs = New CryptoStream(msi, cd, CryptoStreamMode.Read)
    130. readsize = cs.Read(buffer, 0, buffer.Length)
    131. mso.Write(buffer, 0, readsize)
    132. cs.Flush()
    133. If Not cs.HasFlushedFinalBlock Then
    134. cs.FlushFinalBlock()
    135. End If
    136. Loop While readsize = buffer.Length
    137. result = mso.ToArray
    138. End Using
    139. End Using
    140. Return result
    141. Catch ex As Exception
    142. errormsg = ex.Message
    143. Console.WriteLine(ex.Message)
    144. End Try
    145. End Using
    146. Throw New InvalidOperationException(errormsg)
    147. End Function
    148. Private Function DecryptionTfb(ciphertext() As Byte, password() As Byte, cryptodata As CryptoInfo) As Byte()
    149. Dim errormsg = String.Empty
    150. Using aes As New RijndaelManaged With
    151. {
    152. .BlockSize = 256,
    153. .FeedbackSize = 256,
    154. .Mode = CipherMode.CBC,
    155. .Padding = PaddingMode.PKCS7
    156. }
    157. aes.IV = cryptodata.IV
    158. aes.Key = ToRfc2898(password, cryptodata.Salt, cryptodata.Iteration, aes.KeySize \ 8, cryptodata.HashAlgoName)
    159. Try
    160. Dim readsize = 0, cnt = -1
    161. Dim result() = New Byte() {}
    162. Dim size = Convert.ToInt32(2 ^ 16) + aes.BlockSize \ 8
    163. Dim buffer = New Byte(size - 1) {}
    164. Using cd As ICryptoTransform = aes.CreateDecryptor
    165. Do
    166. cnt += 1
    167. Dim tmp = ciphertext.Skip(cnt * readsize).Take(buffer.Length).ToArray
    168. readsize = tmp.Length
    169. Array.Copy(tmp, buffer, readsize)
    170. Dim dec = cd.TransformFinalBlock(buffer, 0, readsize)
    171. result = result.Concat(dec).ToArray()
    172. Loop While readsize = buffer.Length
    173. Return result
    174. End Using
    175. Catch ex As Exception
    176. errormsg = ex.Message
    177. Console.WriteLine(ex.Message)
    178. End Try
    179. End Using
    180. Throw New InvalidOperationException(errormsg)
    181. End Function
    182. Private Function ToRfc2898(password() As Byte, salt() As Byte, iteration As Int32, keysize As Int32, hashalgo As HashAlgorithmName) As Byte()
    183. 'in VS2019 sollte schon die neuere Version drin sein
    184. 'd.h. ein HashAlgorithmName kann noch hinzugefügt werden.
    185. Using rfc = New Rfc2898DeriveBytes(password, salt, iteration) ', HashAlgorithmName.SHA512
    186. Return rfc.GetBytes(keysize)
    187. End Using
    188. End Function
    189. Private Function MultPlain(plain As String, mult As Int32) As String
    190. Dim sb = New StringBuilder
    191. Enumerable.Range(0, mult).ToList.ForEach(Function(x) sb.Append(plain))
    192. Return sb.ToString
    193. End Function
    194. Private Function RngBytes(size As Int32) As Byte()
    195. Dim result = New Byte(size - 1) {}
    196. Rand.NextBytes(result)
    197. Return result
    198. End Function
    199. Private Class CryptoInfo
    200. 'Für die Sicherhheit wie die korrekte Nutzung dieser Daten
    201. 'ist der Entwickler verantwortlich.
    202. 'Da sie nicht im CipherCode integriert sind, müssen sie selber
    203. 'vom Entwickler irgendwie sicher abgespeichert werden.
    204. Public IV() As Byte
    205. Public Salt() As Byte
    206. Public Iteration As Int32
    207. Public HashAlgoName As HashAlgorithmName
    208. End Class
    209. End Module
    210. Friend Module RandomHolder
    211. Friend ReadOnly Rand As New Random
    212. End Module

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „exc-jdbi“ ()