Security News
38% of CISOs Fear They’re Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
chat.dim:CryptoPlugins
Advanced tools
build.gradle
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
dependencies {
// https://bintray.com/dimchat/common/sdk
implementation group: 'chat.dim', name: 'SDK', version: '0.2.2'
}
pom.xml
<dependencies>
<!-- https://mvnrepository.com/artifact/chat.dim/SDK -->
<dependency>
<groupId>chat.dim</groupId>
<artifactId>SDK</artifactId>
<version>0.2.2</version>
<type>pom</type>
</dependency>
</dependencies>
User private key, ID, meta, and profile are generated in client,
and broadcast only meta
& profile
onto DIM station.
Step 1. generate private key (with asymmetric algorithm)
PrivateKey privateKey = PrivateKey.generate(PrivateKey.RSA);
NOTICE: After registered, the client should save the private key in secret storage.
Step 2. generate meta with private key (and meta seed)
String seed = "username";
Meta meta = Meta.generate(MetaType.Default, privateKey, seed);
Step 3. generate ID with meta (and network type)
ID identifier = meta.generateID(NetworkType.Main);
Step 4. create profile with ID and sign with private key
UserProfile profile = new UserProfile(identifier);
// set nickname and avatar URL
profile.setName("Albert Moky");
profile.setAvatar("https://secure.gravatar.com/avatar/34aa0026f924d017dcc7a771f495c086");
// sign
profile.sign(privateKey);
Step 5. send meta & profile to station
Messenger messenger = Messenger.getInstance();
Command cmd = new ProfileCommand(identifier, meta, profile);
messenger.sendCommand(cmd);
The profile should be sent to station after connected and handshake accepted, details are provided in later chapters
Step 1. connect to DIM station (TCP)
Step 2. prepare for receiving message data package
public void onReceive(byte[] responseData) {
byte[] response = messenger.onReceivePackage(responseData);
if (response != null && response.length > 0) {
// send processing result back to the station
send(response);
}
}
Step 3. send first handshake command
(1) create handshake command
// first handshake will have no session key
String sessionKey = null;
Command cmd = new HandshakeCommand(sessionKey);
(2) pack, encrypt and sign
InstantMessage iMsg = new InstantMessage(cmd, userId, stationId);
SecureMessage sMsg = messenger.encryptMessage(iMsg);
ReliableMessage rMsg = messenger.signMessage(sMsg);
(3) Meta protocol
Attaching meta in the first message package is to make sure the station can find it, particularly when it's first time the user connect to this station.
rMsg.setMeta(user.getMeta());
(4) send out serialized message data package
byte[] data = messenger.serializeMessage(rMsg);
send(data);
Step 4. waiting handshake response
The CPU (Command Processing Units) will catch the handshake command response from station, and CPU will process them automatically, so just wait untill handshake success or network error.
Content content = new TextContent("Hey, girl!");
Content content = new ImageContent(imageData, "image.png");
Content content = new AudioContent(voiceData, "voice.mp3");
NOTICE: file message content (Image, Audio, Video) will be sent out only includes the filename and a URL where the file data (encrypted with the same symmetric key) be stored.
Command cmd = new MetaCommand(identifier);
Command cmd = new ProfileCommand(identifier);
public class Messenger extends chat.dim.Messenger {
/**
* Pack and send command to station
*
* @param cmd - command
* @return true on success
*/
public boolean sendCommand(Command cmd) {
assert server != null;
return sendContent(cmd, server.identifier);
}
}
MetaCommand or ProfileCommand with only ID means querying, and the CPUs will catch and process all the response automatically.
You can send a customized command (such as search command) and prepare a processor to handle the response.
public class SearchCommandProcessor extends CommandProcessor {
public static final String SearchUpdated = "SearchUpdated";
public SearchCommandProcessor(Messenger messenger) {
super(messenger);
}
private void parse(SearchCommand cmd) {
Map<String, Object> results = cmd.getResults();
// TODO: processing results
}
@Override
public Content process(Content content, ID sender, InstantMessage iMsg) {
assert content instanceof SearchCommand;
parse((SearchCommand) content);
NotificationCenter nc = NotificationCenter.getInstance();
nc.postNotification(SearchUpdated, this, content);
// response nothing to the station
return null;
}
}
public class HandshakeCommandProcessor extends CommandProcessor {
public HandshakeCommandProcessor(Messenger messenger) {
super(messenger);
}
private Content success() {
Log.info("handshake success!");
String sessionKey = (String) getContext("session_key");
Server server = (Server) getContext("server");
server.handshakeAccepted(sessionKey, true);
return null;
}
private Content ask(String sessionKey) {
Log.info("handshake again, session key: " + sessionKey);
setContext("session_key", sessionKey);
return new HandshakeCommand(sessionKey);
}
@Override
public Content process(Content content, ID sender, InstantMessage iMsg) {
assert content instanceof HandshakeCommand;
HandshakeCommand cmd = (HandshakeCommand) content;
String message = cmd.message;
if ("DIM!".equals(message)) {
// S -> C
return success();
} else if ("DIM?".equals(message)) {
// S -> C
return ask(cmd.sessionKey);
} else {
// C -> S: Hello world!
throw new IllegalStateException("handshake command error: " + content);
}
}
}
And don't forget to register them.
CommandProcessor.register(Command.HANDSHAKE, HandshakeCommandProcessor.class);
CommandProcessor.register(SearchCommand.SEARCH, SearchCommandProcessor.class);
Override interface saveMessage()
in Messenger to store instant message:
public class Messenger extends chat.dim.Messenger {
@Override
public boolean saveMessage(InstantMessage msg) {
Content content = msg.content;
// TODO: check message type
// only save normal message and group commands
// ignore 'handshake', 'meta', 'profile', 'search', ...
// return true to allow responding
if (content instanceof HandshakeCommand) {
// handshake command will be processed by CPUs
// no need to save handshake command here
return true;
}
if (content instanceof MetaCommand) {
// meta & profile command will be checked and saved by CPUs
// no need to save meta & profile command here
return true;
}
if (content instanceof MuteCommand || content instanceof BlockCommand) {
// TODO: create CPUs for mute & block command
// no need to save mute & block command here
return true;
}
if (content instanceof SearchCommand) {
// search result will be parsed by CPUs
// no need to save search command here
return true;
}
Amanuensis clerk = Amanuensis.getInstance();
if (content instanceof ReceiptCommand) {
return clerk.saveReceipt(msg);
} else {
return clerk.saveMessage(msg);
}
}
}
Copyright © 2019 Albert Moky
FAQs
Extensions for cryptography
We found that chat.dim:CryptoPlugins demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.