-
Notifications
You must be signed in to change notification settings - Fork 1
2 of 5
Any implementation bridges a gap. There is an API on one side. That API describes features. It was created to serve use cases. This API will be used by a (graphical) user interface. That API has its roots in the application domain.
Each implementation is based on other software. That is the other side. In our case, that software is mainly ASAP.
Our implementation has to transform API calls into ASAP calls and vica versa. Our implementation must transform application data structures into ASAP structures and vice versa.
We defined our message datstructure with an interface: SharkMessage.
ASAP allows sending messages: sendASAPMessage. This methode requires three parameter: An application format an optional URI and a byte array that contains the actual content.
InMemoSharkMessage is the class that bridges that gap.
There is a static methode serializeMessage which produces a byte array which becomes the content of an ASAP message.
public static byte[] serializeMessage(byte[] content, CharSequence sender, Set<CharSequence> receiver,
boolean sign, boolean encrypt, ASAPKeyStore asapKeyStore)
throws IOException, ASAPException {
...
}
It takes all parameter which can be set with our API. It also provides a reference to an ASAPKeyStorage. This interface is provided by our SharkPKI component. Next section describes how we set up our and related components and from what source we have got that object reference.
The following code serializes all meta data of our Shark message.
// create a ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// serialize shark message content
ASAPSerialization.writeByteArray(content, baos);
// serialize shark message sender
ASAPSerialization.writeCharSequenceParameter(sender, baos);
// serialize shark message receiver
ASAPSerialization.writeCharSequenceSetParameter(receiver, baos);
// add a timestamp
Timestamp creationTime = new Timestamp(System.currentTimeMillis());
String timestampString = creationTime.toString();
ASAPSerialization.writeCharSequenceParameter(timestampString, baos);
// produce a byte array
content = baos.toByteArray();
We use our own serialization class. We propose to do the same. Variable content
contains the serialized Shark message. This content could be delivered as ASAP message.
User may want that message to be signed.
byte flags = 0;
if(sign) {
byte[] signature = ASAPCryptoAlgorithms.sign(content, asapKeyStore);
baos = new ByteArrayOutputStream();
ASAPSerialization.writeByteArray(content, baos); // message has three parts: content, sender, receiver
// append signature
ASAPSerialization.writeByteArray(signature, baos);
// attach signature to message
content = baos.toByteArray();
flags += SIGNED_MASK;
}
We use a byte variable to indicate if a message is e.g. signed. We add the signed flag in that case: flags += SIGNED_MASK
.
We sign the content. ASAPCryptoAlgorithms is already implemented in the core ASAPJava library. It provides a [signing method](ASAPCryptoAlgorithms.sign(content, ASAPKeyStore). There is video that gives an introducation in basic encryption algorithms including message signing and verifying.
Again we use a ByteArrayOutputStream to compile several parts into a single byte array. First, we write the content that was produced a few lines earlier. Second, we add the signature. Finally, we have got a new content
It now contains the serialized Shark message with its signature.
User may want that message to be encrypted.
if(encrypt) {
content = ASAPCryptoAlgorithms.produceEncryptedMessagePackage(
content, // complied Shark message (maybe with signature)
receiver.iterator().next(), // receiver
asapKeyStore);
flags += ENCRYPTED_MASK;
}
ASAPCryptoAlgorithms provides a method that creates a symmetric encyption key. That key is used to encrypt the content. This key is encrypted with receivers public key, see a video for details.
We set a flag to remember that our content
variable contains an encrypted message.
Finally, we produce the content of our ASAP message by adding the flags to the content.
// serialize Shark message
baos = new ByteArrayOutputStream();
ASAPSerialization.writeByteParameter(flags, baos);
ASAPSerialization.writeByteArray(content, baos);
return baos.toByteArray();
We write our flags and the content into a byte array. That array is returned and will serve as content of an ASAP message. Deserialization follows the same steps in reverse order, see parseMessage.
Sending a message is pretty simple thanks to our InMemoSharkMessage class.
The complete implementation can be found in SharkMessengerComponentImpl
public void sendSharkMessage(byte[] content, CharSequence uri,
Set<CharSequence> selectedRecipients, boolean sign,
boolean encrypt)
throws SharkMessengerException, IOException {
this.checkComponentRunning(); // throws an exception if component not yet running
//....
// serialize Shark message and send it as ASAP message
this.asapPeer.sendASAPMessage(SHARK_MESSENGER_FORMAT, uri,
InMemoSharkMessage.serializeMessage(
content,
this.asapPeer.getPeerID(),
selectedRecipients,
sign, encrypt,
this.sharkPKIComponent));
}
} catch (ASAPException e) {
throw new SharkMessengerException("...");
}
}
This methods throws an exception if this component is not yet initialized (see checkComponentRunning()
).
We call serializeMessage()
. Our Shark message is optionally signed and encrypted and finally compiled into a byte array. That byte array is used as content of our ASAP message. Our application format is a constant value (SHARK_MESSENGER_FORMAT
). Uri is parameter of this method.
this.asapPeer.sendASAPMessage
sends delegates message sending to our ASAP peer. Message sent.
- Project goals
- Step 0: Concept
- Step 1: API
- Step 2: Implementation
- Step 3: Shark Component
- Step 4: Testing
- Step 5: GUI
- Javadoc
- Shark Messenger User Guide
- How to use
- Command Page
- TODO