Tuesday, May 20, 2014

Steganography in Java

Steganography is a process of hiding text message on an image. This is achieved by putting text's bits to image's bit. It will produce a new image that contains hidden bits inside the image. There are a lot of approaches to do steganography but for now we will do it as simple as possible. In this approach, and many other approaches, we will use bit operations (AND, OR, XOR, RIGHT SHIFT, LEFT SHIFT, etc).


First, we define the input and output image file name, and also the text message to hide. In addition to the text message itself, we also need to persist the text message length so that we are able to fetch the hidden text message later. Integer has length of 32 bits which is equivalent to 4 bytes. That's why we have variable INT_LENGTH there.


Then we load the input image and put it into a BufferedImage object.


Next we create a new BufferedImage object by specifying its width and height. We get the width and height from input image. We also set its image type to be TYPE_3BYTE_BGR which means that we want to create an image with 8-bit RGB color Blue, Green, and Red stored in 3 bytes.


We can then obtain the Graphics2D object from the new BufferedImage. Then we copy the input BufferedImage data to our new BufferedImage for image processing later.


Since now our new BufferedImage contains data from input image, we can obtain its pixel bytes using WritableRaster and DataBufferByte classes as shown above.


Then we get text message bytes and check its length. If the text message length plus four bytes (remember that we will also persist the length, which is an integer of four bytes) doesn't fit the input image length, then an exception is thrown.


Next we persist the text message length to the image. Casting an integer to byte makes the first 3 bytes truncated. That is why we have to shift it to right. To get the left most byte, we need to right shift it 24 bits. To get the second left most byte, we need to right shift it 16 bits. To get the third left most byte, we need to right shift it 8 bits. Lastly, getting the right most byte we only need to cast it to byte.


We then replace the first four pixels in the image with our previous text message length bytes.


Next is the main part of Steganography, hiding the text message in the image. We do this by replacing pixels starting from position fourth until the text message length. We replace the original input image byte pixel with text message byte.


Next step is writing the new BufferedImage to an output file. This is the last step to produce the output image.

After successfully hiding the text message in an image, we will now try to read the hidden text message.


Our first step is to read the output image and put its data into a BufferedImage object.


Next step is to get its pixel bytes which we can do by the help of WritableRaster and DataBufferByte classes as shown above.


After getting the pixel bytes, now we can extract the data. The first four bytes have information about the text message length. We can extract the text message length by left shifting and combining them using OR. Below is the illustration of the process.



Next we create an array of byte that will hold our extracted text message data.


Next is the process of extracting the text message. Starting from position fourth until the text message length is where the text message bytes hidden. We put the data into our previously created array.


Converting the array of byte to string gives us the original text message. Below is the input and output image. There are some noise on upper left corner of the output image after we hide the text message inside. The more advanced Steganography technique can be applied to produce smoother output.



Friday, May 9, 2014

JAAS Revisited

Now we will try to use JAAS to authenticate a user, assign a principal to him/her, and checking whether he/she is permitted to do an action. But before we get our hands dirty with code, there are several terms in JAAS that we need to understand.
  • Subject: it represents a user that we want to authenticate.
  • Principal: it represents a role. A subject may have many principals.
  • Permission: it represents a permission to do an action. A permission has actions and target objects, which we will see later in policy file.
  • Policy: it is a mapping of principal and permission; that is, which role is allowed to do what kind of actions.
We will start with creating the policy file.


As shown above, we have granted AuthPermission to do createLoginContext, doAs, doAsPrivileged, etc for all principals. Then, we granted nothing for UserPrincipal. We also granted FilePermission to read file input.txt for SysAdminPrincipal. Note that we gave a name for each principal; "user" for UserPrincipal and "sysadmin" for SysAdminPrincipal. It means that we have to give a name "sysadmin" for every SysAdminPrincipal object to allow a Subject that is given that principal to be granted all permissions under SysAdminPrincipal. If, for example, a Subject is given SysAdminPrincipal name "myadmin" then it will not be granted SysAdminPrincipal's permissions.

Next we will see UserPrincipal and SysAdminPrincipal class.



As we can see, all principals implements Principal interface. It has one method that returns its name. It is the name that has to be matched with the one on policy file, "sysadmin" for SysAdminPrincipal and "user" for UserPrincipal.

The policy file is loaded when our application starts. We specify the file name as VM arguments as shown below.


In he VM arguments above, we also set argument for login configuration file. It is a configuration file that tells java security manager which class is responsible for authenticating a Subject when he/she logs in.


In the configuration file above we defined a package/application named bim. This is more like a group of modules while it has one module inside named SimpleLoginModule. Instead of having only single module, we can also have as many modules as we need. Below is an example of a configuration file that has many modules in a package/application.


It has REQUISITE as its control flag. There are four control flags available:
  1. REQUIRED: It must return true from its login() method. But, system will continue proceed the next module in the same package/application regardless of its result.
  2. REQUISITE: It must return true from its login() method. System will not continue proceed the next module in the same package/application if its result is false.
  3. SUFFICIENT: It is not required to return true from its login() method, but if it is, system will not proceed the next module in the same package/application.
  4. OPTIONAL: It is not required to return true from its login() method. Whatever its result, system will continue proceed the next module in the same package/application.
One thing to note here is that returning true from login() method means returning Boolean.TRUE while returning false means throwing a LoginException not returning Boolean.FALSE. We will see this in an example below in SimpleLoginModule class.







SimpleLoginModule implements LoginModule interface. There are five methods that we need to implement.
  1. initialize(): this is the first method called when we authenticate a user. We can initialize our class variables here. initialize() has 4 arguments on its method header and three of them are useful for us. First is Subject, it is the Subject that is being logged in. Then CallbackHandler, it is an object that is responsible for gathering credentials (username & password). We will see this class later. Last is a Map of options. On the configuration file, we put an option isUsed="true". This option is available in the Map of options. Our SimpleLoginModule's initialize() method above initialized our private variables Subject and CallbackHandler for future usage.
  2. login(): this method is used to gather and validate username and password. If the validation succeeds, it returns true. Otherwise we should throw LoginException. In the login() method, we declared two callback objects, NameCallback and PasswordCallback. They are used to gather username and password credentials through callbackHandler.handle(callbacks) method. We will see how this is done later when we visit our callback handler class. After getting the credentials, we simply validated them. If the validation succeed, we returns true, otherwise we throw a FailedLoginException. Note that we didn't return false if the validation fails. If it returns true, then commit() method is called; but if it throws LoginException, then abort() method is called instead. Returning false (Boolean.FALSE) will not make the abort() method called.
  3. commit(): this method is called if login() method returns true. We can put principles to a Subject here. In our commit() method, we added principles to Subject since he/she has successfully logged in. If the username is "sysadmin", a SysAdminPrincipal is added to the Subject. If the username is "user", a UserPrincipal is added to the Subject.
  4. abort(): this method is called if login() method throws LoginException. We can remove all credentials (username, password) here. In this method we cleaned up all credentials.
  5. logout(): this method is called if we logout from JAAS. When a user logout, we clean up all credentials and remove all principals that were assigned when he/she logged in.
Next we will see the callback handler, SimpleCallbackHandler class.


Our SimpleCallbackHandler above implements CallbackHandler. We need to implement handle() method. In handle() we iterate callbacks array that was sent by SimpleLoginModule.login() method as we did before. During iteration, we populate NameCallback with username and PasswordCallback with password. Now one thing missing is how we get the username and password credentials to be sent to this SimpleCallbackHandler. This is where LoginContext plays its role.



To authenticate a user, first we create SimpleCallbackHandler object and pass the username and password. Then we create LoginContext object by passing package/application name from configuration file we created before and the SimpleCallbackHandler object. LoginContext.login() is used to log the user in by passing control to the SimpleLoginModule. If the authentication succeeds, we can obtain the Subject. If fails, LoginException is thrown.

Now that the user is authenticated, we can start checking if a user is authorized to do some action. We have granted permissions as we did in policy file before. These permissions will be used to check user authorization. Subject.doAsPrivileged is the method we need. In the code above we test if a user is allowed to read file input.txt. If he/she is allowed, it simply returns. Otherwise, it throws SecurityException.

Below is the result from running the code:


From the result we can see that the Subject "user" and "sysadmin" authentication succeeds. The "user" is not allowed to access the input.txt file since we didn't grant any permission to it while "sysadmin" can.

Below is the project structure:


Saturday, May 3, 2014

Digital Signature in Java Part II

Previously on this blog post, we have created a digital signature by encrypting message digest using private key. Now we will see what Java provides for us to simplify digital signature creation.


First, we created the message that we want to sign and generate its byte array as shown above.


Next, we created a Signature object. This class takes an algorithm name as its parameter. In the code above we passed MD5WithRSA as the input since we want to use message digest with RSA as we did on this blog post. We could use other algorithm names as well.

Next we initialized the Signature object with our private key object. Refer to this post on how to create private key using RSA. Then we updated the signature with our original message.


Now we are ready to sign the message with our private key. The code above showed us how to do that by simply calling sign() method on the Signature object. The signatureByte above is our digital signature byte. We can now send it along with the message string to the recipients.


When the recipient receives our message, he/she needs to verify the signature as well as the message. First, recipient has to initialize the Signature object with our shared public key as shown above. Here is the post that explains how to create a public key. Note that for message signing we called initSign() while for message verifying we called initVerify() method.

Then we updated the Signature object with the plain message that was sent along with the signature by calling update() method. To verify if the signature is valid, we passed the signature byte that we got from the sender to the Signature object as we did above.

Friday, May 2, 2014

Digital Signature in Java

Digital Signature is used to verify the authenticity of the message sender and to verify that the message is intact. The simplest way is to encrypt the message using private key. If it can be decrypted using the corresponding public key then the sender is authenticated.

Another way is using message digest. First we generate a message digest from the message using hash function. Then the message digest is encrypted using private key. This way we can authenticate the sender by decrypting it using public key. And the message is verified by generating a new message digest from the message. If the digests are equal then the message is verified. We will try to implement this way in Java.

First, we create the message that we want to sign. Here we also create an array of byte from the text message.


Next, we need to generate a message digest from the message. The code below simply calls a method that generates a message digest from the message above. I have posted how to generate a message digest here and here.


Next, we need to encrypt the message digest using our private key as shown below. Here is the post that explains our code below.


The cipherByte above is our digital signature. We can now send it along with the message string to the recipients.

When the recipient receives our message, he/she needs to authenticate the signature. The recipient can achieve this by decrypting the signature with our shared public key as shown below. Here is the post that explains our code below.


If it succeeds, we can obtain the decrypted message digest. This also means that the signature is authenticated, but we still need to verify the message to make sure that it is intact. Using the plain message that was sent along with the signature, we can generate a new message digest as shown below.


Our next step is to compare those two message digests. If those two are equal then the signature is verified.


 

©2009 Stay the Same | by TNB