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.


Monday, April 28, 2014

Message Digest in Java Using Secret Key

I have made a post about message digest and secret key before. Now we will see how to generate a message digest using a secret key in Java.


First, we created the message and convert it to array of byte.


Then, we created a KeyGenerator object, the object that will generate our secret key, by supplying  an algorithm name. In this case we use AES to generate the secret key. Note that we can also create s secret key using a secret key string as we did in this post.


Next, we created a Mac object. Message Authentication Code (MAC) is a Message Digest that is generated using a secret key. There are several algorithms available for Mac. For now we choose HmacMD5. Note that the secret key and mac algorithms are completely separated, for example we use AES for secret key generation and HmacMD5 for Mac.

Then we initialize Mac with our secret key object and then update it with our original message.


We then call doFinal() method of Mac object against our original message to generate the message digest byte. Converting the byte to String using UTF8 encoding enables us to display the generated message digest to console as shown below.


Sunday, April 27, 2014

Asymmetric Encryption in Java

Asymmetric encryption uses a pair of public and private key to encrypt and decrypt messages. A message that is encrypted using a public or private key can only be decrypted using the other corresponding private or public key. RSA is an algorithm that is widely used to generate public and private key pair. RSA allows us to define how long the key is, 1024, 2048, or 4096 bits. Let's now try how to implement asymmetric encryption in Java.


First, we define the message that we want to encrypt and convert it to array of byte.


Then, we created a KeyPairGenerator object that will generate a pair of public-private key for us. We passed RSA, the algorithm name that will be used to generate the keys and then initialized it with the key size of 2048 bits. We can also initialize it with key size of 1024 or 4096 bits depending on our need. One thing to note is the longer the key, the longer it takes to generate the public-private key.


In the code above, we obtain the public and private key objects. Usually, the keys are then serialized to a file so that it can be read later to encrypt or decrypt messages.


Next, we created a Cipher object by passing, what javadoc refers as, a transformation. It is a string that describes the operations to be performed on the given input to produce some output. There are several transformation strings we can choose depending on the algorithm we use. Since in this case we use RSA, we use RSA/ECB/PKCS1Padding. We can use other transformation string of our preference.

Then we initialize the Cipher object by passing it the public key object we created before and a flag to tell the Cipher that we want to do encryption as stated on ENCRYPT_MODE.


After everything is ready, we called doFinal() on Cipher object to start the encryption. The result is shown below:


After successfully encrypting the message now we will try to decrypt it. The code below shows how we do this by simply passing the private key and a flag indicating that now we are interested in decrypting a text instead of encrypting it.

The decryption happens when we call doFinal() on Cipher object as we did when encrypting message.


The decryption result is shown below:

Symmetric Encryption in Java

Symmetric encryption uses a secret key (also known as private key) to encrypt and decrypt messages. Data Encryption Standard (DES) is an algorithm that is widely used to generate secret key. Other algorithms are AES and DEDede.

Session key is a term that is used to represent a secret key that its lifetime is limited. For example a secret key that is generated to encrypt a digital conversation. The key is destroyed after the conversation is finished. DES allows us to use 8 characters string as a key while AES allows 16 characters key and DESede allows 24 characters key. Let's try to encrypt and decrypt string in Java.


First we define our secret key string. Since we want to try AES, we have a 16 characters string as the secret key. We also created the message and convert it to an array of byte.


Next we created a SecretKey object by passing our secret key and the algorithm name of our preference. In this case we passed AES and its 16 bytes secret key.


Next we created a Cipher object by passing, what Javadoc refers as, a transformation. It is a string that describes the operations to be performed on the given input to produce some output. There are several transformation strings we can choose depending on the algorithm we use. Since in this case we use AES, we use AES/ECB/PKCS5Padding. We can use other transformation string of our preference.

Then we initialize the Cipher object by passing it the secret key object we created before and a flag to tell the Cipher that we want to do encryption as stated on ENCRYPT_MODE.


Now we can start encryption by calling doFinal() on the Cipher object as we did above. The encrypted text is show below:

After successfully encrypting the message now we will try to decrypt it. The code below shows how we do it by simply passing the secret key and a flag indicating that now we are interested in decrypting a text instead of encrypting it.


The decryption happens when we call doFinal() on Cipher object as we did when encrypting message.


The decryption result is shown below:

Instead of providing a string of secret key, Java provides us a secret key generator class named KeyGenerator. Our code below shows how we can take advantage of this class to generate a random secret key:

KeyGenerator takes algorithm name as a parameter to generate the secret key for us.

Saturday, April 26, 2014

Message Digest in Java

Message Digest is a function to verify a message integrity. A sender sends a message along with its message digest. The recipient then has to generate a new message digest from the original message. If the two message digests are equal then the message is verified. There are several algorithms we can use to generate message digest hash code including MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512. Let's now try to generate a message digest using MessageDigest class.


First we create the message and convert it to array of byte.


Then we create a MessageDigest object by passing an algorithm name of our preference. In the code above we passed "SHA-512". Next we update the object with our original message.


We then call digest() method of MessageDigest object against our original message to generate the message digest byte. Converting the byte to String using UTF8 encoding enables us to display the generated message digest to console as shown below.


This message digest is sent along with the original message. The recipient has to generate a new message digest against the original message as we did before. If the two message digests are equal then the original message is verified. Message digest is used to guarantee that the original message is intact because if the original message is changed even a bit, the MessageDigest will generate a completely different digest.

Sunday, December 29, 2013

WebSocket

Back in December 2012 when googling about websocket, the results were Atmosphere, jWebSocket, websockets4j, socket.io, and Weberknecht. But in December 2013, the result is JSR 356. Yes, there is finally a standardization about websocket. Apache Tomcat 7.0.47 has also implemented it and we will use it in this blog post.

To start, we can create usual dynamic web project in eclipse. Don't forget to specify Tomcat as the server target runtime. I created a super simple chat application. The chat room can have many users. You can try it by opening as many tabs as you like, each tab represents a new user session. All messages are saved so that users that joined after the conversation has started don't miss anything. In this example, each time a message is sent it will be broadcasted to all users joining the chat. Below is the source code hosted on box:


Below is the result when running the code with three users involved:




Thursday, December 26, 2013

Java 3D

 

©2009 Stay the Same | by TNB