/* * Copyright 2011 Future Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.webconsole.impl; import java.io.StringWriter; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.UUID; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.handler.codec.base64.Base64; import org.json.JSONWriter; import org.krakenapps.msgbus.Message; import org.krakenapps.msgbus.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class KrakenMessageEncoder { private static Logger logger = LoggerFactory.getLogger(KrakenMessageEncoder.class); private KrakenMessageEncoder() { } public static String encode(Session session, Message msg) { Map<String, Object> headers = new HashMap<String, Object>(); headers.put("guid", msg.getGuid()); if (msg.getRequestId() != null) headers.put("requestId", msg.getRequestId()); headers.put("type", msg.getType().toString()); headers.put("method", msg.getMethod()); headers.put("session", msg.getSession()); headers.put("source", msg.getSource()); headers.put("target", msg.getTarget()); if (msg.getErrorCode() != null) { headers.put("errorCode", msg.getErrorCode()); headers.put("errorMessage", msg.getErrorMessage()); } String json = jsonize(headers, msg.getParameters()); // encrypt if session has encrypt key if (session.has("enc_key")) { try { Charset utf8 = Charset.forName("utf-8"); byte[] iv = generateIv(); byte[] key = ByteUtil.asByteArray(UUID.fromString(session.getString("enc_key"))); SecretKeySpec secret = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); byte[] encrypted = cipher.doFinal(json.getBytes(utf8)); Map<String, Object> encHeaders = new HashMap<String, Object>(); encHeaders.put("iv", toBase64(iv)); Map<String, Object> encData = new HashMap<String, Object>(); encData.put("data", toBase64(encrypted)); json = jsonize(encHeaders, encData); } catch (Exception e) { logger.error("kraken webconsole: cannot encrypt msg", e); } } return json; } private static String toBase64(byte[] b) { ChannelBuffer buf = Base64.encode(ChannelBuffers.wrappedBuffer(b)); return new String(buf.array(), 0, buf.readableBytes()); } private static byte[] generateIv() { Random r = new Random(); byte[] b = new byte[16]; r.nextBytes(b); return b; } private static String jsonize(Map<String, Object> headers, Map<String, Object> properties) { StringWriter writer = new StringWriter(1024); JSONWriter jsonWriter = new JSONWriter(writer); try { jsonWriter.array(); jsonWriter.object(); for (String key : headers.keySet()) { jsonWriter.key(key).value(headers.get(key)); } jsonWriter.endObject(); jsonWriter.object(); properties = convertDate(properties); for (String key : properties.keySet()) { jsonWriter.key(key).value(properties.get(key)); } jsonWriter.endObject(); jsonWriter.endArray(); } catch (Exception e) { logger.error("kraken webconsole: json encode error", e); } return writer.toString(); } @SuppressWarnings("unchecked") private static Map<String, Object> convertDate(Map<String, Object> properties) { Map<String, Object> m = new HashMap<String, Object>(); if (properties == null) return m; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); for (String key : properties.keySet()) { Object value = properties.get(key); if (value instanceof Date) m.put(key, dateFormat.format((Date) value)); else if (value instanceof Map) m.put(key, convertDate((Map<String, Object>) value)); else if (value instanceof Collection) { Collection<Object> c = new ArrayList<Object>(); for (Object v : (Collection<?>) value) { if (v instanceof Date) c.add(dateFormat.format((Date) v)); else c.add(v); } m.put(key, c); } else m.put(key, value); } return m; } }