Advertisement
PiToLoKo

vb.net

Mar 5th, 2014
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 53.72 KB | None | 0 0
  1. #Region " Usage Examples "
  2.  
  3. 'Public Class Form1
  4.  
  5. '    ''' <summary>
  6. '    ''' Instance of a Class containing most of the methods involving image-related actions,
  7. '    ''' common to both encryption and decryption.
  8. '    ''' </summary>
  9. '    Dim curentIO As New IO
  10.  
  11. '    Private Sub Test() Handles MyBase.Load
  12.  
  13.  
  14. '        ' Encrypt text into image:
  15. '        Dim Encrypt As New Encrypting(Color.Red, "Hello World!", curentIO, 0)
  16. '        Dim EncryptedImage As Bitmap = Nothing
  17.  
  18. '        Select Case Encrypt.errors
  19.  
  20. '            Case False
  21. '                ' Encrypts the text and returns the encrypted Bitmap.
  22. '                EncryptedImage = curentIO.Encrypt(500, 500, Encrypt)
  23.  
  24. '                ' Or encrypts the text and save it directlly in a image file.
  25. '                Encrypt = curentIO.SaveImageFile("C:\File.png", 500, 500, Encrypt)
  26.  
  27. '            Case True
  28. '                MessageBox.Show(Encrypt.errorMessage, "There was an error while encrypting the text.")
  29.  
  30. '        End Select
  31.  
  32.  
  33. '        ' Decrypt image into text:
  34. '        Dim Decrypt As New Decrypting(Color.Red, EncryptedImage, curentIO, 0)
  35. '        ' Dim Decrypt As New Decrypting(Color.Red, Bitmap.FromFile("C:\File.png"), curentIO, 0)
  36.  
  37. '        If Not Decrypt.errors Then
  38. '            MsgBox(Decrypt.decryptedString)
  39. '        Else
  40. '            MessageBox.Show(Decrypt.errorMessage, "Either the input parameters or the image are wrong.")
  41. '        End If
  42.  
  43.  
  44. '    End Sub
  45.  
  46. 'End Class
  47.  
  48. #End Region
  49.  
  50. #Region " Imports "
  51.  
  52. Imports System.Globalization
  53. Imports System.IO
  54.  
  55. #End Region
  56.  
  57. #Region " Chromatic Encryption/Decryption "
  58.  
  59. ''' <summary>
  60. ''' Class storing the main methods dealing with the encryption process (i.e., application of the "hashed values" to the input characters).
  61. ''' Pretty small class, as far as most of the actions are performed in Hashing and while dealing with image (in IO).
  62. ''' </summary>
  63. Public Class Encrypting
  64.  
  65.     ''' <summary>
  66.     ''' List of colors representing the true output from this class.
  67.     ''' These are the only pixels containing information the remaining ones in the output picture are just to "make dummy space".
  68.     ''' </summary>
  69.     Public encryptedString As List(Of Color)
  70.  
  71.     ''' <summary>
  72.     ''' In some cases, the input text might be changed
  73.     ''' (e.g., characters with no color equivalent); this variable will store this variations.
  74.     ''' </summary>
  75.     Public modifiedText As String
  76.  
  77.     ''' <summary>
  78.     ''' This list include all the characters which are not encrypted (if any).
  79.     ''' </summary>
  80.     Public ignoredChars As List(Of Char)
  81.  
  82.     ''' <summary>
  83.     ''' Very important in the encryption process as far as it represents the
  84.     ''' only parameter which cannot deduced from the picture.
  85.     ''' </summary>
  86.     Public errors As Boolean
  87.  
  88.     Public origText As String
  89.     Public curHashing As Hashing
  90.     Public errorMessage As String
  91.     Public encryptingNumber As Integer
  92.  
  93.     ''' <summary>
  94.     ''' Contructor carrying out the main actions for this class
  95.     ''' </summary>
  96.     ''' <param name="startColor">The start color.</param>
  97.     ''' <param name="temp_origText">The temp_orig text.</param>
  98.     ''' <param name="curIO">The current io.</param>
  99.     ''' <param name="temp_encryptingNumber">The temp_encrypting number.</param>
  100.     Public Sub New(ByVal startColor As Color,
  101.                    ByVal temp_origText As String,
  102.                    ByVal curIO As IO,
  103.                    ByVal temp_encryptingNumber As Integer)
  104.  
  105.         If temp_origText Is Nothing AndAlso temp_origText.Trim.Length < 1 Then
  106.  
  107.             errorMessage = "Please, introduce the string to be encrypted."
  108.             errors = True
  109.             Return
  110.  
  111.         End If
  112.  
  113.         ignoredChars = New List(Of Char)
  114.         origText = temp_origText
  115.         modifiedText = origText
  116.         encryptingNumber = temp_encryptingNumber
  117.  
  118.         ' Creating the "hash table" (list of colors associated to the characters) has, logically, to be done before starting the encryption.
  119.         ' Note that the input string (it's length) is also brought into picture while hashing.
  120.         curHashing = New Hashing(startColor, Me, Nothing, curIO)
  121.  
  122.         'Performing the actual encryption
  123.         If Not curHashing.errors Then
  124.             encryptText(startColor, origText)
  125.  
  126.         Else
  127.             errorMessage = curHashing.errorMessage
  128.             errors = True
  129.  
  130.         End If
  131.  
  132.     End Sub
  133.  
  134.     ''' <summary>
  135.     ''' Method performing the pure encription, that is:
  136.     ''' Conversion of each character from the input string into the corresponding color.
  137.     ''' </summary>
  138.     ''' <param name="curColor">Current color.</param>
  139.     ''' <param name="curText">Current text to encrypt.</param>
  140.     Public Sub encryptText(curColor As Color, curText As String)
  141.  
  142.         ignoredChars = New List(Of Char)
  143.         encryptedString = New List(Of Color)
  144.  
  145.         For Each curChar As Char In origText
  146.  
  147.             If curHashing.charsVsColors.ContainsKey(curChar) Then
  148.                 encryptedString.Add(curHashing.charsVsColors(curChar))
  149.  
  150.             Else
  151.  
  152.                 'Due to the limited number of available colors (to ease the usability),
  153.                 ' quite a few characters are not accounted for.
  154.                 encryptedString.Add(curHashing.charsVsColors(" "c))
  155.  
  156.                 If Not ignoredChars.Contains(curChar) Then
  157.                     ignoredChars.Add(curChar)
  158.                     modifiedText = modifiedText.Replace(curChar, " "c)
  159.                 End If ' ignoredChars.Contains(curChar)
  160.  
  161.             End If ' curHashing.charsVsColors.ContainsKey(curChar)
  162.  
  163.         Next ' curChar
  164.  
  165.     End Sub
  166.  
  167. End Class
  168.  
  169. ''' <summary>
  170. ''' Class storing the main methods dealing with the decryption process
  171. ''' (i.e., extracting the encrypted information contained in the input image).
  172. ''' Pretty small class, as far as most of the actions are performed in Hashing and while dealing with image (in IO).
  173. ''' </summary>
  174. Public Class Decrypting
  175.  
  176.     Public origBitmap As Bitmap
  177.  
  178.     ' Number input via numericUpDown.
  179.     ' Very important in the encryption process as far as it represents the only parameter which cannot deduced from the picture.
  180.     Public encryptingNumber As Integer
  181.  
  182.     Public curHashing As Hashing
  183.     Public decryptedString As String
  184.     Public errors As Boolean
  185.     Public errorMessage As String
  186.  
  187.     ''' <summary>
  188.     ''' Constructor with the required "pre-actions" (e.g., hashing) before starting the process
  189.     ''' </summary>
  190.     ''' <param name="startColor">The start color.</param>
  191.     ''' <param name="curBitMap">The current bit map.</param>
  192.     ''' <param name="curIO">The current IO object.</param>
  193.     ''' <param name="temp_encryptingNumber">The temporal encrypting number.</param>
  194.     Public Sub New(ByVal startColor As Color,
  195.                    ByVal curBitMap As Bitmap,
  196.                    ByVal curIO As IO,
  197.                    ByVal temp_encryptingNumber As Integer)
  198.  
  199.         origBitmap = curBitMap
  200.         encryptingNumber = temp_encryptingNumber
  201.         curHashing = New Hashing(startColor, Nothing, Me, curIO)
  202.  
  203.         If Not curHashing.errors Then
  204.             startDecrypting(curIO)
  205.         Else
  206.             errorMessage = curHashing.errorMessage
  207.             errors = True
  208.         End If
  209.  
  210.     End Sub
  211.  
  212.     ''' <summary>
  213.     ''' Decrypting process which, as far as it involves image management, is located in the 'IO' class.
  214.     ''' </summary>
  215.     ''' <param name="curIO">Indicates the current 'IO' object.</param>
  216.     Public Sub startDecrypting(ByVal curIO As IO)
  217.  
  218.         curIO.decryptImage(Me)
  219.  
  220.     End Sub
  221.  
  222. End Class
  223.  
  224. ''' <summary>
  225. ''' Class containing all the hashing-related methods. This is an extremely important pre-step for both encryption and decryption  
  226. ''' </summary>
  227. Public Class Hashing
  228.  
  229.     Public curIO As IO
  230.     Public charsVsColors As Dictionary(Of Char, Color)
  231.     Public startColor As Color
  232.     Public curColors As List(Of Color)
  233.     Public replacePair As KeyValuePair(Of Char, Color) 'Color not present in the current hashing table and used to replace the startColor if required (e.g., char assigned to startColor used in the offset before the first start pixel)
  234.     Public encryptingNumber As Integer 'Input value, of high importance in the hashing process (also in the encrypting/decrypting ones)
  235.     Public curStep As Integer 'Variable determining the variation color-to-color (in the original array of colors) accounted for while assigning a color to each variable. It is influenced by numerous parameters
  236.     Public curLength As Integer 'Total length of the encrypted string. This value is always bigger than the actual length of the string (to store further information). It is part of the information accounted for while encrypting/decrypting
  237.     Public errors As Boolean
  238.     Public errorMessage As String
  239.  
  240.     '----- Decrypting
  241.     Public startPixel As Point, endPixel As Point 'This has to be calculated here because the length is accounted for while hashing
  242.     Public startPixelOrig As Point 'Stores the "fake start point", relevant while analysing the next pixels storing length information
  243.     Public pixelsToIgnore As List(Of Point) 'List of pixels storing security information which does not have to be decrypted (e.g., length of the original string)
  244.     Public pixelsLength As pixelsLengthInfo 'Instance referring the information regarding the pixels storing the length of the encrypted text
  245.     Public startOffset As startOffsetInfo
  246.     '-----
  247.  
  248.     ''' <summary>
  249.     ''' Starting actions on account of the given process (encryption/decription)
  250.     ''' </summary>
  251.     ''' <param name="temp_startColor">Color of the temp_start.</param>
  252.     ''' <param name="curEncrypting">The current encrypting.</param>
  253.     ''' <param name="curDecrypting">The current decrypting.</param>
  254.     ''' <param name="temp_curIO">The temp_cur io.</param>
  255.     Public Sub New(temp_startColor As Color, curEncrypting As Encrypting, curDecrypting As Decrypting, temp_curIO As IO)
  256.  
  257.         startColor = temp_startColor
  258.         curIO = temp_curIO
  259.         curColors = New List(Of Color)(curIO.allKnownColor)
  260.         startOffset = New startOffsetInfo()
  261.  
  262.         If curEncrypting IsNot Nothing Then
  263.  
  264.             If curEncrypting.origText Is Nothing OrElse curEncrypting.origText.Length < 1 Then
  265.  
  266.                 errors = True
  267.                 Return
  268.  
  269.             End If
  270.  
  271.             curLength = curEncrypting.origText.Length + 2 + (curEncrypting.origText.Length + 2).ToString.Length 'Length considered while decrypting
  272.             encryptingNumber = curEncrypting.encryptingNumber
  273.  
  274.         Else
  275.  
  276.             If curDecrypting.origBitmap Is Nothing Then
  277.  
  278.                 errorMessage = "There was a problem while accessing the image file."
  279.                 errors = True
  280.                 Return
  281.  
  282.             End If
  283.  
  284.             encryptingNumber = curDecrypting.encryptingNumber
  285.             pixelsToIgnore = New List(Of Point)
  286.  
  287.             'Preliminary validaty check by looking for the startColor (in the right position) and determining the length (and the offset, if applicable)
  288.             curIO.getBoundaryPixels(curDecrypting, Me)
  289.  
  290.             If curLength <= 0 Then
  291.  
  292.                 errors = True
  293.                 Return
  294.  
  295.             End If
  296.  
  297.         End If
  298.  
  299.         calculateStartStep() 'Calculating curStep
  300.  
  301.         buildCharsVsColors() 'Building the hash table (dictionary with all the accounted characters and their equivalent color) which will be used in the current encryption/decryption process
  302.  
  303.         If curDecrypting IsNot Nothing Then
  304.  
  305.             'For decryption. Confirming that the length value, calculated above, matches the information in the pixels enconding the actual length.
  306.             'The reason for not having this analysis before is the fact that the charsVsColors is required
  307.             If Not curIO.lengthIsOK(curDecrypting, Me) Then errors = True
  308.  
  309.         End If
  310.  
  311.     End Sub
  312.  
  313.     ''' <summary>
  314.     ''' To increase the importance of the startIndex
  315.     ''' (first KnownColors index considered while populating the charsVsColors collection),
  316.     ''' the original array of known colors is completely reordered on account of it.
  317.     ''' This is a new way to increase the randomness/complexity of the encryption and make sure that the
  318.     ''' effect from the Encrypting Number is influential enough, mainly for short texts.
  319.     ''' </summary>
  320.     ''' <param name="startIndex">Indicates the start index.</param>
  321.     Private Sub reorderKnownColors(startIndex As Integer)
  322.  
  323.         Dim newList As List(Of Color) = New List(Of Color)
  324.  
  325.         For i As Integer = startIndex To curColors.Count - 1
  326.  
  327.             Dim newIndex As Integer = i + encryptingNumber
  328.             If newIndex >= curColors.Count Then newIndex = 0
  329.  
  330.             Dim iterations As Integer = 0
  331.  
  332.             While newIndex < curColors.Count AndAlso newList.Contains(curColors(newIndex))
  333.  
  334.                 newIndex = newIndex + 1
  335.                 If newIndex >= curColors.Count Then
  336.  
  337.                     If iterations = 0 Then
  338.  
  339.                         newIndex = 0
  340.                         iterations = iterations + 1
  341.  
  342.                     Else
  343.                         Exit While
  344.                     End If
  345.  
  346.                 End If
  347.  
  348.             End While
  349.  
  350.             If Not newList.Contains(curColors(newIndex)) Then newList.Add(curColors(newIndex))
  351.  
  352.             If newList.Count = curColors.Count Then Exit For
  353.  
  354.             If i >= curColors.Count - 1 AndAlso newList.Count < curColors.Count Then i = 0
  355.  
  356.         Next
  357.  
  358.         curColors = New List(Of Color)(newList)
  359.  
  360.     End Sub
  361.  
  362.     ''' <summary>
  363.     ''' Building the basic "hashing dictionary", charsVsColors,
  364.     ''' where each (recognised) character is related to a given color.
  365.     ''' The relationships characters->colors is different every time and varies
  366.     ''' on account of different variables (e.g., encrypting integer or length of the input text)
  367.     ''' </summary>
  368.     Private Sub buildCharsVsColors()
  369.  
  370.         charsVsColors = New Dictionary(Of Char, Color)
  371.  
  372.         Dim curColor As Color = startColor
  373.         Dim minIndex As Integer = 0
  374.         Dim maxIndex As Integer = 240 'The restricted number of colors forces to choose just specific characters
  375.  
  376.         Dim curRGB As RGBInfo = New RGBInfo
  377.         curRGB.lastR = startColor.R
  378.         curRGB.lastG = startColor.G
  379.         curRGB.lastB = startColor.B
  380.         curRGB.lastIndex = calculateFirst() 'Calculating the start index (from the original List of known colors) from which all the analysis will be started
  381.  
  382.         reorderKnownColors(curRGB.lastIndex) 'Reordering the original list with all the known colors on account of the inputs
  383.  
  384.         Dim availableColors As List(Of Color) = New List(Of Color)(curColors)
  385.  
  386.         For i As Integer = minIndex To maxIndex - 1
  387.  
  388.             If Not (i >= 127 AndAlso i <= 160) Then 'The restricted number of colors forces to choose just specific characters
  389.  
  390.                 Dim noDiacritics As String = Me.ConvertDiacritics(Convert.ToChar(i).ToString())
  391.  
  392.                 If Not (noDiacritics <> Convert.ToChar(i).ToString) Then 'The restricted number of colors forces to choose just specific characters
  393.  
  394.                     curRGB = updateRGB(curRGB, availableColors)
  395.                     curColor = availableColors(curRGB.curIndex)
  396.                     curRGB.lastR = curColor.R
  397.                     curRGB.lastG = curColor.G
  398.                     curRGB.lastB = curColor.B
  399.  
  400.                     charsVsColors.Add(Convert.ToChar(i), curColor)
  401.  
  402.                     availableColors.RemoveAt(curRGB.curIndex) 'Avoiding the given color to be considered for a different character
  403.  
  404.                 End If
  405.             End If
  406.         Next
  407.  
  408.         If availableColors.Count > 0 AndAlso charsVsColors.ContainsValue(startColor) Then
  409.  
  410.             Dim replaceColor As Color = availableColors(0) 'There has to be always unused availableColors
  411.             Dim tempPair As KeyValuePair(Of Char, Color) = charsVsColors.FirstOrDefault(Function(x) IO.twoColorsAreEqual(x.Value, startColor))
  412.             replacePair = New KeyValuePair(Of Char, Color)(tempPair.Key, replaceColor)
  413.             availableColors.RemoveAt(0)
  414.  
  415.         End If
  416.  
  417.         Dim afterIndex As Integer = curIO.allKnownColor.IndexOf(startColor) + encryptingNumber
  418.         If afterIndex > curIO.allKnownColor.Count - 1 Then afterIndex = encryptingNumber
  419.         Dim afterOffset As Color = curIO.allKnownColor(afterIndex)
  420.         startOffset.afterOffset = afterOffset
  421.  
  422.         If availableColors.Count > 0 AndAlso charsVsColors.ContainsValue(startOffset.afterOffset) Then
  423.  
  424.             Dim replaceColor As Color = availableColors(0) 'There has to be always unused availableColors
  425.             Dim tempPair As KeyValuePair(Of Char, Color) = charsVsColors.First(Function(x) IO.twoColorsAreEqual(x.Value, startOffset.afterOffset))
  426.             startOffset.replaceAfter = New KeyValuePair(Of Char, Color)(tempPair.Key, replaceColor)
  427.             availableColors.RemoveAt(0)
  428.  
  429.         End If
  430.  
  431.     End Sub
  432.  
  433.     ''' <summary>
  434.     ''' Determining the first index from which the arrays populations will be started on account of the inputs.
  435.     ''' The over-complication is meant to increase the realibility of the encryption:
  436.     ''' the more random is the behaviour when the value is not exactly the right input, the more secure.
  437.     ''' </summary>
  438.     ''' <returns>System.Int32.</returns>
  439.     Private Function calculateFirst() As Integer
  440.  
  441.         Dim firstIndex As Integer = curColors.IndexOf(startColor)
  442.         Dim firstColorI As Integer = encryptingNumber
  443.         Dim secondColorI As Integer = -1
  444.  
  445.         If firstColorI > startColor.Name.Length - 1 Then
  446.             firstColorI = startColor.Name.Length - 1
  447.         Else
  448.  
  449.             secondColorI = firstColorI + Convert.ToInt32(Math.Floor(Convert.ToDouble(encryptingNumber) / 2.0))
  450.             If secondColorI > startColor.Name.Length - 1 Then secondColorI = startColor.Name.Length - 1
  451.  
  452.         End If
  453.  
  454.         firstIndex = firstIndex + firstColorI
  455.         Dim firstColor As Color = curColors(firstColorI)
  456.         If firstColor.R > startColor.R Then firstIndex = firstIndex + 2
  457.  
  458.         If secondColorI > -1 Then
  459.  
  460.             Dim secondColor As Color = curColors(secondColorI)
  461.             If Convert.ToInt32(secondColor.G.ToString()) < Convert.ToInt32(firstColor.G.ToString()) Then firstIndex = firstIndex + Convert.ToInt32(Math.Floor(2.0 * Convert.ToDouble(secondColorI) / Convert.ToDouble(firstColorI)))
  462.  
  463.         End If
  464.  
  465.         If firstIndex < 0 Then
  466.             firstIndex = 0
  467.         ElseIf firstIndex > curColors.Count - 1 Then
  468.             firstIndex = curColors.Count - 1
  469.         End If
  470.  
  471.         Return firstIndex
  472.  
  473.     End Function
  474.  
  475.     ''' <summary>
  476.     ''' Function called from the loop populate the main array chars->colors to determine the index to be considered next.
  477.     ''' It includes various arbitrary modifications increasing the security of the method.
  478.     ''' </summary>
  479.     ''' <param name="curRGB">Indicates the current RGB.</param>
  480.     ''' <param name="availableColors">Indicates the available colors.</param>
  481.     ''' <returns>RGBInfo.</returns>
  482.     Private Function updateRGB(curRGB As RGBInfo, availableColors As List(Of Color)) As RGBInfo
  483.  
  484.         Dim curIndex As Integer = curStep
  485.  
  486.         If curRGB.lastR >= 100 Then curIndex = curIndex + 1
  487.         If curRGB.lastG < 100 Then curIndex = curIndex + 2
  488.         If curRGB.lastB >= 100 Then curIndex = curIndex - 2
  489.  
  490.         If curIndex + curRGB.lastIndex < availableColors.Count - 10 Then curIndex = curIndex + curRGB.lastIndex
  491.  
  492.         If curLength <= 10 Then
  493.             curIndex = curIndex - 1
  494.         Else
  495.             curIndex = curIndex + 1
  496.         End If
  497.  
  498.         If curIndex < 0 Then
  499.             curIndex = curIndex = 0
  500.         ElseIf curIndex > availableColors.Count - 1 Then
  501.             curIndex = availableColors.Count - 1
  502.         End If
  503.  
  504.         curRGB.curIndex = curIndex
  505.         curRGB.lastIndex = curRGB.curIndex
  506.  
  507.         Return curRGB
  508.  
  509.     End Function
  510.  
  511.     ''' <summary>
  512.     ''' The "step" represents the basic variable in charge of determining the next color to be considered
  513.     ''' while populating the char->color array.
  514.     ''' This variable is one of the most "randomly-affected" ones,
  515.     ''' as far as is very relevant in the main hash-table population.
  516.     ''' </summary>
  517.     Private Sub calculateStartStep()
  518.  
  519.         curStep = 0
  520.  
  521.         If startColor.R >= 120 Then curStep = curStep + 1
  522.         If startColor.G >= 120 Then curStep = curStep + 2
  523.         If startColor.B >= 120 Then curStep = curStep + 1
  524.  
  525.         If encryptingNumber < 3 Then
  526.             curStep = curStep + 2
  527.         ElseIf encryptingNumber >= 3 AndAlso encryptingNumber < 7 Then
  528.             curStep = curStep + 1
  529.         Else
  530.             curStep = curStep - 1
  531.         End If
  532.  
  533.         If curLength > 0 Then
  534.  
  535.             Dim addStep As Integer = Convert.ToInt32(Math.Floor(Convert.ToDouble(curLength) / 100.0))
  536.  
  537.             If addStep <= 1 Then
  538.                 addStep = 1
  539.             ElseIf addStep > 80 Then
  540.                 addStep = 3
  541.             End If
  542.  
  543.             curStep = curStep + addStep
  544.  
  545.         End If
  546.  
  547.         If curStep < 1 Then
  548.             curStep = 1
  549.         ElseIf curStep > 10 Then
  550.             curStep = 10 'Otherwise colors might be too concentrated
  551.         End If
  552.  
  553.     End Sub
  554.  
  555.     ' Convert Diacritics
  556.     '
  557.     ' Usage Examples:
  558.     ' MsgBox(RemoveDiacritics("áéíóú àèìòù äëïöü ñÑ çÇ", UnicodeNormalization:=System.Text.NormalizationForm.FormKD))
  559.     ' Result: 'aeiou aeiou aeiou nN cC'
  560.     '
  561.     ''' <summary>
  562.     ''' Converts the diacritic characters in a String to an equivalent normalized English characters.
  563.     ''' </summary>
  564.     ''' <param name="String">
  565.     ''' Indicates the string that contains diacritic characters.
  566.     ''' </param>
  567.     ''' <param name="UnicodeNormalization">
  568.     ''' Defines the type of Unicode character normalization to perform.
  569.     ''' (Default is 'NormalizationForm.FormKD')
  570.     ''' </param>
  571.     ''' <returns>System.String.</returns>
  572.     Public Function ConvertDiacritics(ByVal [String] As String,
  573.                                       Optional ByVal UnicodeNormalization As System.Text.NormalizationForm =
  574.                                                                              System.Text.NormalizationForm.FormKD) As String
  575.  
  576.         Dim Characters As String = String.Empty
  577.  
  578.         For Each c As Char In [String].Normalize(UnicodeNormalization)
  579.  
  580.             Select Case Globalization.CharUnicodeInfo.GetUnicodeCategory(c)
  581.  
  582.                 Case Globalization.UnicodeCategory.NonSpacingMark,
  583.                      Globalization.UnicodeCategory.SpacingCombiningMark,
  584.                      Globalization.UnicodeCategory.EnclosingMark
  585.  
  586.                     ' Do nothing.
  587.                     Exit Select
  588.  
  589.                 Case Else
  590.                     Characters &= CStr(c)
  591.  
  592.             End Select
  593.  
  594.         Next c
  595.  
  596.         Return Characters
  597.  
  598.     End Function
  599.  
  600. End Class
  601.  
  602. ''' <summary>
  603. ''' Small accessory class storing some of the variables used in the loop populating the char->color dictionary
  604. ''' </summary>
  605. Public Class RGBInfo
  606.  
  607.     Public curIndex As Integer
  608.     Public lastR As Integer
  609.     Public lastG As Integer
  610.     Public lastB As Integer
  611.     Public lastIndex As Integer
  612.  
  613. End Class
  614.  
  615. ''' <summary>
  616. ''' Class storing all the information required by the pixels in charge of storing the lenght information (security check reducing the options of a false positive)
  617. ''' </summary>
  618. Public Class pixelsLengthInfo
  619.  
  620.     Public startPixel As Point
  621.     Public endPixel As Point
  622.     Public length As Integer
  623.  
  624.     ''' <summary>
  625.     ''' Initializes a new instance of the <see cref="pixelsLengthInfo"/> class.
  626.     ''' </summary>
  627.     Public Sub New()
  628.  
  629.         startPixel = New Point
  630.         endPixel = New Point
  631.  
  632.     End Sub
  633.  
  634. End Class
  635.  
  636. ''' <summary>
  637. ''' Class dealing with the offset start. This is a new security feature making varying the position of the color indicating the start of the encrypted string
  638. ''' </summary>
  639. Public Class startOffsetInfo
  640.  
  641.     Public replaceAfter As KeyValuePair(Of Char, Color) 'To replace afterOffset in case it would have to be used
  642.     Public startOffsetCount As Integer
  643.     Public startPoint As Point
  644.     Public afterOffset As Color 'Additional pixel telling the decryptor that an offset exists. Without this pixel, there might be cases where the presence of the offset might be ignored
  645.  
  646.     ''' <summary>
  647.     ''' Initializes a new instance of the <see cref="startOffsetInfo"/> class.
  648.     ''' </summary>
  649.     Public Sub New()
  650.         startOffsetCount = -1
  651.     End Sub
  652.  
  653. End Class
  654.  
  655. ''' <summary>
  656. ''' Class storing all the methods dealing with I/O system, that is, with the image file.
  657. ''' As far as the image file plays an important role in both processes (encryption/decryption), the methods in this class are used systematically from everywhere
  658. ''' </summary>
  659. Public Class IO
  660.  
  661.     Public imageExtensions As List(Of String)
  662.     Public allKnownColor As List(Of Color)
  663.  
  664.     ''' <summary>
  665.     ''' Constructor populating the two main arrays of this class: list of valid extensions and all the known colors
  666.     ''' </summary>
  667.     Public Sub New()
  668.  
  669.         imageExtensions = GetType(System.Drawing.Imaging.ImageFormat).GetProperties().Select(Function(x) x.Name.ToLower).ToList
  670.         populateKnownColors()
  671.  
  672.     End Sub
  673.  
  674.     ''' <summary>
  675.     ''' There are various colors in the default known colors list which are identical.
  676.     ''' The List created by this method does not include repeated colors..
  677.     ''' </summary>
  678.     Private Sub populateKnownColors()
  679.  
  680.         allKnownColor = New List(Of Color)
  681.  
  682.         For Each colorName As String In [Enum].GetNames(GetType(KnownColor))
  683.  
  684.             Dim curColor As Color = Color.FromName(colorName)
  685.             If allKnownColor.FirstOrDefault(Function(x) twoColorsAreEqual(x, curColor)).IsEmpty Then allKnownColor.Add(curColor)
  686.  
  687.         Next
  688.  
  689.         allKnownColor = allKnownColor.OrderBy(Function(x) x.Name).ToList
  690.  
  691.     End Sub
  692.  
  693.     ''' <summary>
  694.     ''' Method determining if the selected path contains a valid image or not.
  695.     ''' </summary>
  696.     ''' <param name="_path">Indicates the _path.</param>
  697.     ''' <returns>Bitmap.</returns>
  698.     Public Function fileValidImage(_path As String) As Bitmap
  699.  
  700.         Dim outBitmap As Bitmap = Nothing
  701.  
  702.         Dim curExtension As String = Path.GetExtension(_path)
  703.         If curExtension.Trim.Length > 0 Then
  704.  
  705.             curExtension = curExtension.Substring(1, curExtension.Length - 1).ToLower
  706.  
  707.             If imageExtensions.Contains(curExtension) Then
  708.                 outBitmap = Bitmap.FromFile(_path)
  709.             End If
  710.  
  711.         End If
  712.  
  713.         Return outBitmap
  714.  
  715.     End Function
  716.  
  717.     ''' <summary>
  718.     ''' The mere "=" is not enough while comparing the stored, known colors against the ones from the pixels being read.
  719.     ''' </summary>
  720.     ''' <param name="color1">Indicates the color1.</param>
  721.     ''' <param name="color2">Indicates the color2.</param>
  722.     ''' <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
  723.     Public Shared Function twoColorsAreEqual(color1 As Color, color2 As Color) As Boolean
  724.  
  725.         Return color1.R = color2.R AndAlso color1.G = color2.G AndAlso color1.B = color2.B
  726.  
  727.     End Function
  728.  
  729.  
  730.     '------------------------------- ENCRYPTING
  731.  
  732.     ''' <summary>
  733.     ''' Method performing the last actions in the encryption process:
  734.     ''' the ones required to create the output image with the encrypted pixels and the other irrelevant, surrounding ones.
  735.     ''' </summary>
  736.     ''' <param name="width">Indicates the width.</param>
  737.     ''' <param name="height">Indicates the height.</param>
  738.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  739.     ''' <returns>Encrypting.</returns>
  740.     Public Function SaveImageFile(ByVal ImagePath As String,
  741.                                   ByVal width As Integer,
  742.                                   ByVal height As Integer,
  743.                                   ByVal curEncrypting As Encrypting) As Encrypting
  744.  
  745.         Try
  746.  
  747.             Dim curBitMap = createImage(width, height, curEncrypting)
  748.             If curBitMap IsNot Nothing Then
  749.                 curBitMap.Save(ImagePath, Drawing.Imaging.ImageFormat.Png)
  750.             End If
  751.  
  752.             If Not File.Exists(ImagePath) Then
  753.                 curEncrypting.errors = True
  754.             End If
  755.  
  756.         Catch
  757.             curEncrypting.errors = True
  758.  
  759.         End Try
  760.  
  761.         Return curEncrypting
  762.  
  763.     End Function
  764.  
  765.     ''' <summary>
  766.     ''' Encrypts the text into an image.
  767.     ''' </summary>
  768.     ''' <param name="width">Indicates the width.</param>
  769.     ''' <param name="height">Indicates the height.</param>
  770.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  771.     ''' <returns>Encrypting.</returns>
  772.     Public Function Encrypt(ByVal width As Integer,
  773.                             ByVal height As Integer,
  774.                             ByVal curEncrypting As Encrypting) As Bitmap
  775.  
  776.         Try
  777.             Dim curBitMap As Bitmap = createImage(width, height, curEncrypting)
  778.             Return curBitMap
  779.  
  780.         Catch
  781.             curEncrypting.errors = True
  782.             Return Nothing
  783.  
  784.         End Try
  785.  
  786.     End Function
  787.  
  788.     ''' <summary>
  789.     ''' Method called by the one above to actually create the image.
  790.     ''' </summary>
  791.     ''' <param name="width">Indicates the width.</param>
  792.     ''' <param name="height">Indicates the height.</param>
  793.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  794.     ''' <returns>Bitmap.</returns>
  795.     Private Function createImage(width As Integer, height As Integer, curEncrypting As Encrypting) As Bitmap
  796.  
  797.         Dim curHashing As Hashing = curEncrypting.curHashing
  798.         Dim allColors As List(Of Color) = curHashing.charsVsColors.Values.ToList 'Colors being considered in the current encryption: neither their number nor their order is kept constant
  799.  
  800.         curEncrypting = setBoundaryColor(curEncrypting) 'Including the additional pixels surrounding the ones including the encrypted information
  801.  
  802.         'Accounting for the fact that the default size (500*500) is not enough to store all the required information
  803.         Dim totSize As Integer = width * height
  804.         If totSize < curHashing.curLength Then
  805.  
  806.             Dim ratio As Double = Math.Ceiling(Math.Sqrt(Math.Ceiling(Convert.ToDouble(allColors.Count) / Convert.ToDouble(curHashing.curLength))))
  807.             height = Convert.ToInt32(Math.Ceiling(height * ratio))
  808.             width = Convert.ToInt32(Math.Ceiling(width * ratio))
  809.  
  810.         End If
  811.  
  812.         Dim outBitmap As Bitmap = New Bitmap(width, height)
  813.         Dim curPixel As pixelInfo = New pixelInfo()
  814.  
  815.         'Determining the start/end pixels (where the encrypted string + additional info will be located)
  816.         curPixel.startI = calculateStartI(width, height, curEncrypting)
  817.         If curEncrypting.encryptedString IsNot Nothing Then curPixel.endI = curPixel.startI + curEncrypting.encryptedString.Count - 1
  818.  
  819.         'Main loop populating the bitmap with all the pixels: ones containing encrypted information and all the other ones
  820.         curPixel.i = -1
  821.         For x As Integer = 0 To width - 1
  822.  
  823.             For y As Integer = 0 To height - 1
  824.  
  825.                 curPixel.i = curPixel.i + 1
  826.                 curPixel.x = x
  827.                 curPixel.y = y
  828.  
  829.                 outBitmap = addColorToPixel(curPixel, outBitmap, allColors, curEncrypting)
  830.  
  831.             Next
  832.         Next
  833.  
  834.         Return outBitmap
  835.  
  836.     End Function
  837.  
  838.     ''' <summary>
  839.     ''' Method determining the start position from which the encrypted string will be added to the image.
  840.     ''' </summary>
  841.     ''' <param name="width">Indicates the width.</param>
  842.     ''' <param name="height">Indicates the height.</param>
  843.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  844.     ''' <returns>System.Int32.</returns>
  845.     Public Function calculateStartI(width As Integer, height As Integer, curEncrypting As Encrypting) As Integer
  846.  
  847.         If curEncrypting Is Nothing OrElse curEncrypting.encryptedString Is Nothing Then Return -1
  848.  
  849.         Dim curHashing As Hashing = curEncrypting.curHashing
  850.         Dim availableSize As Integer = width * height - curEncrypting.encryptedString.Count
  851.         Dim startI As Integer = availableSize
  852.  
  853.         If startI > 0 Then
  854.  
  855.             'Curious (, required?!) method to force VB.NET to treat the RGB values as integers
  856.             Dim tempStart As Integer = Convert.ToInt32(curHashing.startColor.R.ToString()) + Convert.ToInt32(curHashing.startColor.G.ToString()) + Convert.ToInt32(curHashing.startColor.B.ToString())
  857.             If tempStart <= availableSize Then
  858.                 startI = tempStart
  859.             Else
  860.  
  861.                 tempStart = Convert.ToInt32(curHashing.startColor.R.ToString()) + Convert.ToInt32(curHashing.startColor.G.ToString())
  862.                 If tempStart <= availableSize Then
  863.                     startI = tempStart
  864.                 Else
  865.  
  866.                     If curHashing.startColor.R <= availableSize Then
  867.                         startI = Convert.ToInt32(curHashing.startColor.R.ToString())
  868.                     Else
  869.                         startI = availableSize - 1
  870.                     End If
  871.                 End If
  872.             End If
  873.         End If
  874.  
  875.         Return startI
  876.  
  877.     End Function
  878.  
  879.     ''' <summary>
  880.     ''' Determining the color of the current pixel on account of the given position: inside start/end pixels or outside them.
  881.     ''' </summary>
  882.     ''' <param name="curPixelInfo">Indicates the current pixel information.</param>
  883.     ''' <param name="curBitmap">Indicates the current bitmap.</param>
  884.     ''' <param name="allColors">Indicates all colors.</param>
  885.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  886.     ''' <returns>Bitmap.</returns>
  887.     Public Function addColorToPixel(curPixelInfo As pixelInfo, curBitmap As Bitmap, allColors As List(Of Color), curEncrypting As Encrypting) As Bitmap
  888.  
  889.         Dim noChange As Boolean = False
  890.         Dim curIndex As Integer = curPixelInfo.i
  891.         If curPixelInfo.startI > -1 AndAlso curIndex >= curPixelInfo.startI AndAlso curIndex <= curPixelInfo.endI Then
  892.             noChange = True
  893.         End If
  894.  
  895.         Dim curColor As Color = New Color
  896.         If Not noChange Then
  897.  
  898.             'The current pixel is randomly assigned
  899.             curIndex = curPixelInfo.random.Next(0, allColors.Count - 1)
  900.  
  901.             While IO.twoColorsAreEqual(allColors(curIndex), curEncrypting.curHashing.startColor) 'StartColor determines where the encrypted chunk starts/ends and thus cannot be used outside it
  902.                 curIndex = curPixelInfo.random.Next(0, allColors.Count - 1)
  903.             End While
  904.  
  905.             curColor = allColors(curIndex)
  906.  
  907.         Else
  908.  
  909.             'This is part of the "encrypted chunk" and thus the pixels, as calculated so far, have to be added
  910.             curPixelInfo.encryptedAdded = True
  911.             curIndex = curIndex - curPixelInfo.startI
  912.             curColor = curEncrypting.encryptedString(curIndex)
  913.  
  914.             If curEncrypting.curHashing.startOffset.startOffsetCount = -1 Then
  915.  
  916.                 'There is no offset; thus the color in the "offset position" cannot be curEncrypting.curHashing.startOffset.afterOffset
  917.                 If twoColorsAreEqual(curColor, curEncrypting.curHashing.startOffset.afterOffset) AndAlso Not curEncrypting.curHashing.startOffset.replaceAfter.Value.IsEmpty Then
  918.  
  919.                     If curEncrypting.encryptingNumber > 0 AndAlso curIndex = curEncrypting.encryptingNumber + 1 Then
  920.  
  921.                         curColor = curEncrypting.curHashing.startOffset.replaceAfter.Value
  922.  
  923.                     End If
  924.                 End If
  925.             End If
  926.  
  927.         End If
  928.  
  929.         curBitmap.SetPixel(curPixelInfo.x, curPixelInfo.y, curColor)
  930.  
  931.         Return curBitmap
  932.  
  933.     End Function
  934.  
  935.     ''' <summary>
  936.     ''' Method defining the pixels "surrounding" the encrypted string.
  937.     ''' These pixels are very important to allow the decryptor to undoubtedly locate the bunch of pixels to be decrypted.
  938.     ''' </summary>
  939.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  940.     ''' <returns>Encrypting.</returns>
  941.     Private Function setBoundaryColor(curEncrypting As Encrypting) As Encrypting
  942.  
  943.         Dim curHashing As Hashing = curEncrypting.curHashing
  944.         Dim analyseOffset As Boolean = curEncrypting.encryptingNumber > 0 AndAlso curEncrypting.encryptedString.Count - curEncrypting.encryptingNumber > 1
  945.  
  946.         If analyseOffset Then
  947.  
  948.             'startColor at the "encryptingNumber position"
  949.             curEncrypting.encryptedString.Insert(curEncrypting.encryptingNumber, curHashing.startColor)
  950.             curEncrypting.curHashing.startOffset.startOffsetCount = curEncrypting.encryptingNumber + 1
  951.             curEncrypting.encryptedString.Insert(curEncrypting.encryptingNumber + 1, curHashing.startOffset.afterOffset)
  952.  
  953.         Else
  954.  
  955.             'startColor as first pixel
  956.             curEncrypting.encryptedString.Insert(0, curHashing.startColor)
  957.  
  958.         End If
  959.  
  960.         'Method encrypting the current length in the required position
  961.         addLength(curEncrypting, curHashing, analyseOffset)
  962.  
  963.         'startColor as last pixel
  964.         curEncrypting.encryptedString.Add(curHashing.startColor)
  965.  
  966.         Return curEncrypting
  967.  
  968.     End Function
  969.  
  970.     ''' <summary>
  971.     ''' Adding pixels with information regarding the length of the string.
  972.     ''' </summary>
  973.     ''' <param name="curEncrypting">Indicates the current encrypting.</param>
  974.     ''' <param name="curHashing">Indicates the current hashing.</param>
  975.     ''' <param name="analyseOffset">if set to <c>true</c> [analyse offset].</param>
  976.     ''' <returns>Encrypting.</returns>
  977.     Private Function addLength(curEncrypting As Encrypting, curHashing As Hashing, analyseOffset As Boolean) As Encrypting
  978.  
  979.         Dim remString As String = curHashing.curLength.ToString
  980.         Dim curIndex As Integer = 0
  981.         If analyseOffset Then curIndex = curEncrypting.encryptingNumber + 1 'AfterOffset has also to be accounted
  982.  
  983.         'Loop creating one new pixel per digit defining the current length
  984.         While remString.Trim.Length > 0
  985.  
  986.             Dim curLength As Integer = remString.Length
  987.             curIndex = curIndex + 1
  988.             Dim curChar As Char = Convert.ToChar(remString.Substring(0, 1))
  989.             curEncrypting.encryptedString.Insert(curIndex, curHashing.charsVsColors(curChar))
  990.  
  991.             If curLength <= 1 Then Exit While
  992.             remString = remString.Substring(1, remString.Length - 1)
  993.  
  994.         End While
  995.  
  996.         If analyseOffset Then
  997.             'The default population of encryptedString already avoids any pixel before the start one to have startColor. This loop confirms this for all the pixels between
  998.             'the formal start and the actual start (offset)
  999.             If curEncrypting.encryptingNumber > 0 AndAlso curEncrypting.encryptedString.Count >= curEncrypting.encryptingNumber Then
  1000.  
  1001.                 For i As Integer = 0 To curEncrypting.encryptingNumber - 1
  1002.  
  1003.                     If twoColorsAreEqual(curEncrypting.encryptedString(i), curHashing.startColor) Then
  1004.  
  1005.                         'The start point is after this; thus the color of this pixel cannot be the startColor, it will be replaced with the replaceColor
  1006.                         curEncrypting.encryptedString(i) = curHashing.replacePair.Value
  1007.  
  1008.                     End If
  1009.                 Next
  1010.             End If
  1011.         End If
  1012.  
  1013.         Return curEncrypting
  1014.  
  1015.     End Function
  1016.  
  1017.  
  1018.     '------------------------------- DECRYPTING
  1019.  
  1020.     ''' <summary>
  1021.     ''' Method call soon in the hashing (for decrypting) process:
  1022.     ''' it does not only extract valuable information (start pixel, length and, eventually, offset),
  1023.     ''' but also avoids any wrong image to be analysed further.
  1024.     ''' </summary>
  1025.     ''' <param name="curDecrypting">Indicates the current decrypting.</param>
  1026.     ''' <param name="curHashing">Indicates the current hashing.</param>
  1027.     Public Sub getBoundaryPixels(curDecrypting As Decrypting, curHashing As Hashing)
  1028.  
  1029.         Dim tempLast As Point = New Point(-1, -1)
  1030.         Dim tempLength As Integer = -1
  1031.         Dim lastLength As Integer = 0
  1032.         Dim nextPixel As Color = New Color
  1033.         Dim storeNext As Boolean = False
  1034.         curHashing.curLength = -1
  1035.  
  1036.         For x As Integer = 0 To curDecrypting.origBitmap.Width - 1
  1037.  
  1038.             For y As Integer = 0 To curDecrypting.origBitmap.Height - 1
  1039.  
  1040.                 If tempLength >= 0 Then tempLength = tempLength + 1
  1041.  
  1042.                 Dim curColor As Color = curDecrypting.origBitmap.GetPixel(x, y)
  1043.                 If storeNext Then
  1044.  
  1045.                     'This is the "after pixel" which confirms that an offset actually exists
  1046.                     If Not twoColorsAreEqual(curColor, curHashing.startColor) Then nextPixel = curColor
  1047.                     storeNext = False
  1048.  
  1049.                 End If
  1050.  
  1051.                 'StartColor determines where the "relevant chunk" starts/ends, what is done by this condition
  1052.                 If twoColorsAreEqual(curColor, curHashing.startColor) Then
  1053.  
  1054.                     If tempLength < 0 Then
  1055.  
  1056.                         curHashing.startPixel = New Point(x, y)
  1057.                         curHashing.startPixelOrig = New Point(x, y)
  1058.                         storeNext = True
  1059.                         tempLength = 0
  1060.  
  1061.                     Else
  1062.  
  1063.                         tempLast = New Point(x, y)
  1064.                         lastLength = tempLength
  1065.  
  1066.                     End If
  1067.  
  1068.                 End If
  1069.  
  1070.             Next
  1071.  
  1072.         Next
  1073.  
  1074.         If tempLast <> New Point(-1, -1) AndAlso lastLength > 0 Then
  1075.  
  1076.             'The collected information seems right
  1077.  
  1078.             curHashing.endPixel = New Point(tempLast.X, tempLast.Y)
  1079.             curHashing.curLength = lastLength + 1
  1080.  
  1081.             Dim afterIndex As Integer = curHashing.curIO.allKnownColor.IndexOf(curHashing.startColor) + curDecrypting.encryptingNumber
  1082.             If afterIndex > curHashing.curIO.allKnownColor.Count - 1 Then afterIndex = curDecrypting.encryptingNumber
  1083.             Dim afterOffset As Color = curHashing.curIO.allKnownColor(afterIndex)
  1084.  
  1085.             Dim analyseOffset As Boolean = Not nextPixel.IsEmpty AndAlso twoColorsAreEqual(afterOffset, nextPixel)
  1086.  
  1087.             If analyseOffset Then
  1088.                 'There is an offset and thus some variables have to be updated
  1089.                 curHashing.curLength = curHashing.curLength - 1 'afterOffset is not included withing the length value
  1090.                 curHashing.startOffset.afterOffset = afterOffset
  1091.                 curHashing.startOffset.startOffsetCount = curDecrypting.encryptingNumber
  1092.                 curHashing.startOffset.startPoint = New Point(curHashing.startPixel.X, curHashing.startPixel.Y)
  1093.                 curHashing.curLength = curHashing.curLength + curHashing.startOffset.startOffsetCount
  1094.                 curHashing.startPixel = newStartFromOffset(curHashing.startPixel, curHashing.startOffset.startOffsetCount, curDecrypting)
  1095.  
  1096.             End If
  1097.  
  1098.             lengthCorrection(curHashing)
  1099.         End If
  1100.  
  1101.     End Sub
  1102.  
  1103.     ''' <summary>
  1104.     ''' Correction of the length under very specific conditions:
  1105.     ''' cases "close enough" to get a new digit, that is 10, 11, 100, etc.
  1106.     ''' This has been proven a very serious limitation of the approach (without an accurate length, lots of errors might be provoked),
  1107.     ''' which I might correct in next version by changing the way in which the length is being accounte for.
  1108.     ''' </summary>
  1109.     ''' <param name="curHashing">Indicates the current hashing.</param>
  1110.     Public Sub lengthCorrection(curHashing As Hashing)
  1111.  
  1112.         If curHashing.curLength >= 10 Then
  1113.  
  1114.             If (curHashing.curLength - 1).ToString.Length <> curHashing.curLength.ToString.Length OrElse (curHashing.curLength - 2).ToString.Length <> curHashing.curLength.ToString.Length Then
  1115.  
  1116.                 curHashing.curLength = curHashing.curLength - 1
  1117.  
  1118.             End If
  1119.  
  1120.         End If
  1121.  
  1122.     End Sub
  1123.  
  1124.     ''' <summary>
  1125.     ''' There is an offset and thus the actual start of the encrypted chunk is certain;
  1126.     ''' but this determination is not evident as far as it is stored as an integer (= distance).
  1127.     ''' This integer has to be converted into actual pixel/point position; this is what this function does:
  1128.     ''' returning the actual start point by bringing the offset into account
  1129.     ''' </summary>
  1130.     ''' <param name="curStart">Indicates the current start.</param>
  1131.     ''' <param name="offset">Indicates the offset.</param>
  1132.     ''' <param name="curDecrypting">Indicates the current decrypting.</param>
  1133.     ''' <returns>Point.</returns>
  1134.     Private Function newStartFromOffset(curStart As Point, offset As Integer, curDecrypting As Decrypting) As Point
  1135.  
  1136.         Dim newStart As Point = New Point
  1137.  
  1138.         Dim curCount As Integer = 0
  1139.         Dim firstTime As Boolean = True
  1140.  
  1141.         For x As Integer = curDecrypting.origBitmap.Width - 1 To 0 Step -1
  1142.  
  1143.             For y As Integer = curDecrypting.origBitmap.Height - 1 To 0 Step -1
  1144.  
  1145.                 If firstTime Then
  1146.  
  1147.                     x = curStart.X
  1148.                     y = curStart.Y
  1149.                     firstTime = False
  1150.  
  1151.                 End If
  1152.  
  1153.                 curCount = curCount + 1
  1154.  
  1155.                 If curCount > offset Then
  1156.  
  1157.                     newStart.X = x
  1158.                     newStart.Y = y
  1159.                     Exit For
  1160.  
  1161.                 End If
  1162.             Next
  1163.  
  1164.             If curCount >= offset Then Exit For
  1165.         Next
  1166.  
  1167.         Return newStart
  1168.  
  1169.     End Function
  1170.  
  1171.     ''' <summary>
  1172.     ''' Last check performed while hashing (for decryption):
  1173.     ''' the previously-calculated length has to match the value encrypted in some of the pixels of the image in order.
  1174.     ''' to confirm that this is a right image and to go ahead with the decryption.
  1175.     ''' </summary>
  1176.     ''' <param name="curDecrypting">Indicates the current decrypting.</param>
  1177.     ''' <param name="curHashing">Indicates the current hashing.</param>
  1178.     ''' <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
  1179.     Public Function lengthIsOK(curDecrypting As Decrypting, curHashing As Hashing) As Boolean
  1180.  
  1181.         Dim isOK As Boolean = True
  1182.  
  1183.         curHashing.pixelsLength = New pixelsLengthInfo
  1184.  
  1185.         Dim count As Integer = -1
  1186.         Dim calcLength As Integer = 0
  1187.         Dim lengthString As String = ""
  1188.  
  1189.         Dim firstTime As Boolean = True
  1190.         Dim foundStart As Boolean = False
  1191.  
  1192.         Dim startVal As Integer = 1
  1193.  
  1194.         If curHashing.startOffset.startOffsetCount > -1 Then startVal = startVal + 1 '"After pixel" of the offSet has also to be skipped
  1195.  
  1196.         For x As Integer = 0 To curDecrypting.origBitmap.Width - 1
  1197.  
  1198.             For y As Integer = 0 To curDecrypting.origBitmap.Height - 1
  1199.  
  1200.                 If firstTime Then
  1201.  
  1202.                     x = curHashing.startPixelOrig.X
  1203.                     y = curHashing.startPixelOrig.Y
  1204.                     firstTime = False
  1205.  
  1206.                 End If
  1207.  
  1208.                 count = count + 1
  1209.  
  1210.                 If count >= startVal Then 'to skip startColor and, eventually, offset after pixel
  1211.  
  1212.                     Dim curColor As Color = curDecrypting.origBitmap.GetPixel(x, y)
  1213.                     Dim tempPair As KeyValuePair(Of Char, Color) = curHashing.charsVsColors.FirstOrDefault(Function(x2) twoColorsAreEqual(x2.Value, curColor))
  1214.                     If Char.IsDigit(tempPair.Key) Then
  1215.  
  1216.                         curHashing.pixelsToIgnore.Add(New Point(x, y))
  1217.                         lengthString = lengthString & tempPair.Key.ToString
  1218.                         If foundStart Then
  1219.  
  1220.                             curHashing.pixelsLength.startPixel = New Point(x, y)
  1221.                             foundStart = True
  1222.  
  1223.                         End If
  1224.  
  1225.                     Else
  1226.                         Return False
  1227.                     End If
  1228.  
  1229.                     If Integer.TryParse(lengthString, calcLength) Then
  1230.  
  1231.                         If calcLength = curHashing.curLength Then
  1232.  
  1233.                             curHashing.pixelsLength.length = calcLength
  1234.                             curHashing.pixelsLength.endPixel = New Point(x, y)
  1235.                             Return True
  1236.  
  1237.                         End If
  1238.  
  1239.                     Else
  1240.                         Return False
  1241.                     End If
  1242.                 End If
  1243.             Next
  1244.         Next
  1245.  
  1246.         Return isOK
  1247.  
  1248.     End Function
  1249.  
  1250.     ''' <summary>
  1251.     ''' Final stage of the decryption process: application of all the previous calculations to the image to extract the encrypted message.
  1252.     ''' </summary>
  1253.     ''' <param name="curDecrypting">Indicates the current decrypting.</param>
  1254.     ''' <returns>Decrypting.</returns>
  1255.     Public Function decryptImage(curDecrypting As Decrypting) As Decrypting
  1256.  
  1257.         Dim curBitmap As Bitmap = curDecrypting.origBitmap
  1258.  
  1259.         curDecrypting.decryptedString = ""
  1260.  
  1261.         Dim curHashing As Hashing = curDecrypting.curHashing
  1262.         Dim origFound As Boolean = False
  1263.         Dim firstTime As Boolean = True
  1264.         Dim decryptColor As Boolean = False
  1265.  
  1266.         For x As Integer = 0 To curDecrypting.origBitmap.Width - 1 'The analysis starts from the startPixel, already calculated while creating the Hash table
  1267.  
  1268.             For y As Integer = 0 To curDecrypting.origBitmap.Height - 1
  1269.  
  1270.                 Dim analyseStart As Boolean = False
  1271.                 Dim goAhead As Boolean = False
  1272.  
  1273.                 If firstTime Then
  1274.  
  1275.                     x = curDecrypting.curHashing.startPixel.X
  1276.                     y = curDecrypting.curHashing.startPixel.Y
  1277.  
  1278.                 End If
  1279.  
  1280.                 Dim curColor As Color = curDecrypting.origBitmap.GetPixel(x, y)
  1281.  
  1282.                 If firstTime Then
  1283.  
  1284.                     If curHashing.startOffset.startOffsetCount = -1 Then 'No offset
  1285.                         analyseStart = True
  1286.                     Else
  1287.                         decryptColor = True
  1288.                     End If
  1289.                     firstTime = False
  1290.  
  1291.                 ElseIf curHashing.startOffset.startOffsetCount <> -1 Then 'Offset
  1292.  
  1293.                     If Not origFound AndAlso twoColorsAreEqual(curColor, curHashing.startColor) Then
  1294.                         analyseStart = True
  1295.                     End If
  1296.  
  1297.                 End If
  1298.  
  1299.                 If analyseStart Then
  1300.  
  1301.                     'No offset and thus the restrictions in the conversions start already here
  1302.                     If Not twoColorsAreEqual(curDecrypting.origBitmap.GetPixel(x, y), curHashing.startColor) Then
  1303.  
  1304.                         curDecrypting.errors = True
  1305.                         Return curDecrypting
  1306.  
  1307.                     Else
  1308.                         decryptColor = False
  1309.                     End If
  1310.  
  1311.                 End If
  1312.  
  1313.                 If decryptColor Then
  1314.  
  1315.                     'The original start point hasn't either be found or was found and all the surrounding, irrelevant information has already been skipped
  1316.                     If x = curHashing.endPixel.X AndAlso y = curHashing.endPixel.Y Then
  1317.                         Return curDecrypting
  1318.                     End If
  1319.                     goAhead = True
  1320.  
  1321.                 Else
  1322.  
  1323.                     If Not origFound Then
  1324.  
  1325.                         If x = curHashing.pixelsLength.endPixel.X AndAlso y = curHashing.pixelsLength.endPixel.Y Then
  1326.  
  1327.                             origFound = True
  1328.                             decryptColor = True 'from the next pixel onwards, all the information should be decrypted
  1329.  
  1330.                         End If
  1331.  
  1332.                     Else
  1333.  
  1334.                         curDecrypting.errors = True
  1335.                         Return curDecrypting
  1336.  
  1337.                     End If
  1338.  
  1339.                 End If
  1340.  
  1341.                 If goAhead Then
  1342.  
  1343.                     Dim tempPair As KeyValuePair(Of Char, Color) = curHashing.charsVsColors.FirstOrDefault(Function(x2) twoColorsAreEqual(x2.Value, curColor))
  1344.                     If tempPair.Value.IsEmpty AndAlso twoColorsAreEqual(curColor, curHashing.startColor) Then
  1345.  
  1346.                         Dim isOK As Boolean = False
  1347.                         If curDecrypting.encryptingNumber > 0 Then
  1348.  
  1349.                             If Not curHashing.replacePair.Value.IsEmpty AndAlso twoColorsAreEqual(curColor, curHashing.replacePair.Value) Then
  1350.  
  1351.                                 tempPair = New KeyValuePair(Of Char, Color)(curHashing.replacePair.Key, curColor)
  1352.                                 isOK = True
  1353.  
  1354.                             ElseIf Not curHashing.startOffset.replaceAfter.Value.IsEmpty And twoColorsAreEqual(curColor, curHashing.startOffset.replaceAfter.Value) Then
  1355.  
  1356.                                 tempPair = New KeyValuePair(Of Char, Color)(curHashing.startOffset.replaceAfter.Key, curColor)
  1357.                                 isOK = True
  1358.  
  1359.                             End If
  1360.                         End If
  1361.  
  1362.                         If Not isOK Then
  1363.  
  1364.                             curDecrypting.errors = True
  1365.                             Return curDecrypting
  1366.  
  1367.                         End If
  1368.                     End If
  1369.  
  1370.                     curDecrypting.decryptedString = curDecrypting.decryptedString & tempPair.Key.ToString
  1371.  
  1372.                 End If
  1373.             Next
  1374.         Next
  1375.  
  1376.         Return curDecrypting
  1377.  
  1378.     End Function
  1379.  
  1380. End Class
  1381.  
  1382. ''' <summary>
  1383. ''' Class storing some pixel-related information relevant while encrypting/decrypting an image.
  1384. ''' </summary>
  1385. Public Class pixelInfo
  1386.  
  1387.     Public x As Integer
  1388.     Public y As Integer
  1389.  
  1390.     '---- Encrypting
  1391.     Public random As Random
  1392.     Public startI As Integer
  1393.     Public endI As Integer
  1394.     Public i As Integer
  1395.     Public encryptedAdded As Boolean
  1396.     '----
  1397.  
  1398.     '---- Decrypting
  1399.     Public color As Color
  1400.     Public decryptedSofar As String
  1401.     '----
  1402.  
  1403.     Public Sub New()
  1404.         random = New Random
  1405.     End Sub
  1406.  
  1407. End Class
  1408.  
  1409. #End Region
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement