Attributes in VB.NET - Part Two
< Continued from page 2
As noted earlier, you could make the class that is the target of the PubKey attribute as complicated as your application needs it to be. In this example, I've created a relatively simple four step operation to demonstrate how the code would be used:
1 - Create Ballot Text Class and Serialize It
Type some text into a TextBox control and assign the text to the property of a New theBallot class. The theBallot class is created on Form Load as an object with global scope for simplicity.
In a real application, the same object would not be re-used. In this case, we serialize it to a file to simulate transmitting the file across a network. Here's the code:
2 - Read Ballot Text From Class
The same file that was created in step 1 is read back again and deserialized to simulate receiving the class somewhere else on the network. This is standard serialization and file processing. Here's the code:
3 - Encrypt the Ballot
In this step, the application on the other side of the network uses the public key contained in the metadata to encrypt the text in the TextBox control. In a real application, the data that is encrypted would be the "vote" of whoever received the class and it would be different information than the text received. In this case, again for simplicity, I just encrypt whatever is received but I added a string, "My vote is: ", to the front of the text just to make some part of the text visibly different before encrypting it.
If there is "secret sauce" in any of this code, it's in this step. Here are a few of the tricks that make it work:
To retrieve the attribute, that is, the private key, you have to assign the class that is the target of the attribute to a variable of type System.Type.
That's because the GetCustomAttributes method only works on that type variable.
Why? Ask Microsoft. It's their design choice.
Note that GetCustomAttributes returns an array of System.Attribute objects. It will always do this even when there is only one. In this case, however, there are two since the class is also a target of the Serializable attribute. The PubKey attribute is in attrs(1) in this case. The value in that attribute is cast into the variable a.
Then the actual public key is extracted.
The rest of the code in this step is straightforward encryption. Here's the complete code for this step.
4 - Decrypt the Ballot
At this point, a real application would have to serialize the class again and transmit it back over the network to the sender. In this example, that would require code that you have already seen so I haven't included it. But to prove the point that the modified ballot text really is encrypted, I included a step to decrypt it using the private key. The private key is hard coded here, but in a real application, it would be kept secure by whoever sent out the ballots. Again, the entire private key isn't shown to keep the size of the code manageable. The code here is, again, standard decryption.
The entire cycle of steps is shown here:
--------
Click Here to display the illustration
--------
As noted earlier, you could make the class that is the target of the PubKey attribute as complicated as your application needs it to be. In this example, I've created a relatively simple four step operation to demonstrate how the code would be used:
1 - Create Ballot Text Class and Serialize It
Type some text into a TextBox control and assign the text to the property of a New theBallot class. The theBallot class is created on Form Load as an object with global scope for simplicity.
In a real application, the same object would not be re-used. In this case, we serialize it to a file to simulate transmitting the file across a network. Here's the code:
Const BallotFile As String ="..\..\SavedBallot.bin"Dim b As New theBallotPrivate Sub CreateBallotClass_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles CreateBallotClass.Clickb.BallotText = BallotText.TextDim TestFileStream As Stream =File.Create(BallotFile)Dim serializer As New BinaryFormatterserializer.Serialize(TestFileStream, b)TestFileStream.Close()TextBoxLabel.Text ="Message to be Encrypted"End Sub
2 - Read Ballot Text From Class
The same file that was created in step 1 is read back again and deserialized to simulate receiving the class somewhere else on the network. This is standard serialization and file processing. Here's the code:
Private Sub ReadBallotText_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles ReadBallotText.ClickIf File.Exists(BallotFile) ThenDim TestFileStream As Stream =File.OpenRead(BallotFile)Dim deserializer As New BinaryFormatterb = CType(deserializer.Deserialize(TestFileStream),Ballot.theBallot)TestFileStream.Close()End IfBallotText.Text = b.BallotTextTextBoxLabel.Text ="Message Retrieved From Ballot Class"End Sub
3 - Encrypt the Ballot
In this step, the application on the other side of the network uses the public key contained in the metadata to encrypt the text in the TextBox control. In a real application, the data that is encrypted would be the "vote" of whoever received the class and it would be different information than the text received. In this case, again for simplicity, I just encrypt whatever is received but I added a string, "My vote is: ", to the front of the text just to make some part of the text visibly different before encrypting it.
If there is "secret sauce" in any of this code, it's in this step. Here are a few of the tricks that make it work:
To retrieve the attribute, that is, the private key, you have to assign the class that is the target of the attribute to a variable of type System.Type.
Dim t As System.Typet = GetType(theBallot)
That's because the GetCustomAttributes method only works on that type variable.
Dim attrs() As System.Attribute =System.Attribute.GetCustomAttributes(t)
Why? Ask Microsoft. It's their design choice.
Note that GetCustomAttributes returns an array of System.Attribute objects. It will always do this even when there is only one. In this case, however, there are two since the class is also a target of the Serializable attribute. The PubKey attribute is in attrs(1) in this case. The value in that attribute is cast into the variable a.
Dim a As PubKey.PubKey =CType(attrs(1), PubKey.PubKey)
Then the actual public key is extracted.
Dim theKey As String = a.thePubKey
The rest of the code in this step is straightforward encryption. Here's the complete code for this step.
Private Sub EncryptBallot_Click( ByVal sender As System.Object, ByVal e As System.EventArgs ) Handles EncryptBallot.ClickDim t As System.Typet = GetType(theBallot)Dim attrs() As System.Attribute =System.Attribute.GetCustomAttributes(t)Dim a As PubKey.PubKey =CType(attrs(1), PubKey.PubKey)Dim theKey As String = a.thePubKeyDim rsa As New RSACryptoServiceProvider()Dim bytePlainText() As ByteDim byteCipherText() As ByteDim uEncode As New UnicodeEncoding()rsa.FromXmlString(theKey)bytePlainText =uEncode.GetBytes("My Vote is: " & b.BallotText)byteCipherText =rsa.Encrypt(bytePlainText, False)BallotText.Text =Convert.ToBase64String(byteCipherText)TextBoxLabel.Text = "Encrypted Message"End Sub
4 - Decrypt the Ballot
At this point, a real application would have to serialize the class again and transmit it back over the network to the sender. In this example, that would require code that you have already seen so I haven't included it. But to prove the point that the modified ballot text really is encrypted, I included a step to decrypt it using the private key. The private key is hard coded here, but in a real application, it would be kept secure by whoever sent out the ballots. Again, the entire private key isn't shown to keep the size of the code manageable. The code here is, again, standard decryption.
Private Sub DecryptBallot_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles DecryptBallot.ClickDim PrivateKey As String ="9+B ... "'Decrypt a string using the private keyDim rsa As New RSACryptoServiceProvider()Dim bytePlainText() As ByteDim byteCipherText() As ByteDim uEncode As New UnicodeEncoding()rsa.FromXmlString(PrivateKey)byteCipherText =Convert.FromBase64String(BallotText.Text)bytePlainText =rsa.Decrypt(byteCipherText, False)BallotText.Text =uEncode.GetString(bytePlainText)TextBoxLabel.Text ="Decrypted Message"rsa.Clear()End Sub
The entire cycle of steps is shown here:
--------
Click Here to display the illustration
--------