After establishing a security context, two communicating peers can exchange secure messages over the established context.
Either peer can originate a secure message, regardless of whether it served as initiator or acceptor when establishing context. To make the message secure, IBM® JGSS computes a cryptographic message integrity code (MIC) over the message. Optionally, IBM JGSS can have the Kerberos V5 mechanism encrypt the message to help ensure privacy.
IBM JGSS provides two sets of methods for securing messages: wrap() and getMIC().
Using wrap()
The calling application uses the MessageProp class in conjunction with GSSContext to specify whether to apply encryption to the message.
The returned token contains both the MIC and text of the message. The text of the message is either ciphertext (for an encrypted message) or the original plaintext (for messages that are not encrypted).
Using getMIC()
The returned token contains only the computed MIC and does not include the original message. So, in addition to transporting the MIC token to the peer, the peer must somehow be made aware of the original message so that it can verify the MIC.
Example: Using per-message services to send a message
byte[] message = "Ready to roll!".getBytes(); MessageProp mprop = new MessageProp(true); // foo wants the message encrypted byte[] wrappedMessage = fooContext.wrap(message, 0, message.length, mprop); send(wrappedMessage); // transfer the wrapped message to superSecureServer // This is how superSecureServer may obtain a MIC for delivery to foo: byte[] message = "You bet!".getBytes(); MessageProp mprop = null; // superSecureServer is content with // the default quality of protection byte[] mic = serverAcceptorContext.getMIC(message, 0, message.length, mprop); send(mic); // send the MIC to foo. foo also needs the original message to verify the MIC
The receiver of a wrapped message uses unwrap() to decode the message. The unwrap method performs the following actions:
If the sender encrypted the message, unwrap() decrypts the message before verifying the MIC and then returns the original plaintext message. The receiver of an MIC token uses verifyMIC() to verify the MIC over a given a message.
The peer applications use their own protocol to deliver JGSS context and message tokens to each other. Peer applications also need to define a protocol for determining whether the token is an MIC or a wrapped message. For example, part of such a protocol may be as simple (and rigid) as that used by Simple Authentication and Security Layer (SASL) applications. The SASL protocol specifies that the context acceptor is always the first peer to send a per-message (wrapped) token following context establishment.
For more information, see Simple Authentication and Security Layer (SASL).
Example: Using per-message services to receive a message
MessageProp mprop = new MessageProp(false); byte[] plaintextFromFoo = serverAcceptorContext.unwrap(wrappedTokenFromFoo, 0, wrappedTokenFromFoo.length, mprop); // superSecureServer can now examine mprop to determine the message properties // (such as whether the message was encrypted) applied by foo. // foo verifies the MIC received from superSecureServer: MessageProp mprop = new MessageProp(false); fooContext.verifyMIC(micFromFoo, 0, micFromFoo.length, messageFromFoo, 0, messageFromFoo.length, mprop); // foo can now examine mprop to determine the message properties applied by // superSecureServer. In particular, it can assert that the message was not // encrypted since getMIC should never encrypt a message.