/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.redPandaLib.core.messages; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; import org.redPandaLib.core.Channel; import org.redPandaLib.crypt.AESCrypt; import org.redPandaLib.crypt.ECKey; import org.redPandaLib.crypt.ECKey.ECDSASignature; import org.redPandaLib.crypt.Sha256Hash; /** * * @author robin */ public class RawMsg implements Serializable, Comparable<RawMsg> { int nichts = 2; public static final int SIGNATURE_LENGRTH = 72; //head public ECKey key; public long timestamp; public int nonce; public byte public_type = -1; //content public byte[] signature; public byte[] content; //extras public boolean verified = false; public boolean verifying = false; //decrypted content public boolean readable = false; public byte[] decryptedContent; public Channel channel; public int database_Id = -1; public RawMsg(ECKey key, long timestamp, int nonce) { this.key = key; this.timestamp = timestamp; this.nonce = nonce; } public RawMsg(ECKey key, long timestamp, int nonce, byte[] signature, byte[] content, byte[] decryptedContent, Channel channel, boolean verified, boolean readable, int database_Id) { this.key = key; this.timestamp = timestamp; this.nonce = nonce; this.signature = signature; this.content = content; this.decryptedContent = decryptedContent; this.channel = channel; this.verified = verified; this.readable = readable; this.database_Id = database_Id; } public RawMsg(long timestamp, int nonce, byte[] signature, byte[] content, boolean verified) { this.timestamp = timestamp; this.nonce = nonce; this.signature = signature; this.content = content; this.verified = verified; } @Override public boolean equals(Object obj) { if (!(obj instanceof RawMsg)) { return false; } RawMsg m2 = (RawMsg) obj; if (timestamp == m2.timestamp && key.equals(m2.key) && public_type == m2.public_type && nonce == m2.nonce) { return true; } return false; } @Override public int hashCode() { int hash = 3; hash = 67 * hash + (this.key != null ? this.key.hashCode() : 0); hash = 67 * hash + (int) (this.timestamp ^ (this.timestamp >>> 32)); hash = 67 * hash + this.nonce; return hash; } public byte[] getContent() { return content; } public ECKey getKey() { return key; } public int getNonce() { return nonce; } public byte[] getSignature() { return signature; } public long getTimestamp() { return timestamp; } public void sign() { verified = true; //String toSign = "" + timestamp + "" + nonce + "" + new String(content, "UTF-8"); byte[] toSign = new byte[1 + 8 + 4 + content.length]; ByteBuffer wrap = ByteBuffer.wrap(toSign); wrap.put(public_type); wrap.putLong(timestamp); wrap.putInt(nonce); wrap.put(content); Sha256Hash hash = Sha256Hash.create(toSign); ECDSASignature sign = key.sign(hash); byte[] encodeToDER = new byte[SIGNATURE_LENGRTH]; byte[] sigBytes = sign.encodeToDER(); System.arraycopy(sigBytes, 0, encodeToDER, 0, sigBytes.length); byte[] newBytes = new byte[encodeToDER.length]; int index = encodeToDER.length - 1; while (true) { System.arraycopy(encodeToDER, 0, newBytes, 0, index + 1); if (newBytes[index] == (byte) 0) { newBytes = new byte[index]; index--; } else { break; } } //System.out.println("Sigbytes len: " + sigBytes.length + " " + Utils.bytesToHexString(encodeToDER)); //System.out.println("Sigbytes len: " + sigBytes.length + " " + Utils.bytesToHexString(newBytes)); signature = encodeToDER; //System.out.println("len: " + encodeToDER.length); //System.out.println("len: " + encodeToDER.length); // Sha256Hash hash = Sha256Hash.create(toSign.getBytes()); // ECDSASignature sign = key.sign(hash); // // signature = sign.encodeToDER(); //forces 72 bytes... //signature = new byte[SIGNATURE_LENGRTH]; //byte[] sigBytes = sign.encodeToDER(); // signature = sign.encodeToDER(); //System.out.println("Signature1 length : " + Utils.bytesToHexString(signature)); //System.arraycopy(sigBytes, 0, signature, 0, sigBytes.length); //System.out.println("Signed: contentlen:" + content.length + " key: " + Utils.bytesToHexString(content) +new String(Base64.encode(key.getPubKey())) + " signature: " + new String(Base64.encode(signature)) + " time: " + timestamp + " nonce: " + nonce + " content: " + new String(Base64.encode(content))); // System.out.println("Signed: contentlen:" + content.length + " key: " + Base58.encode(key.getPubKey()) + " signature: " + Utils.bytesToHexString(signature) + " time: " + timestamp + " nonce: " + nonce + " content: " + Utils.bytesToHexString(content)); // System.out.println("Signed: contentlen:" + content.length + " key: " + Base58.encode(key.getPubKey()) + " signature: " + Utils.bytesToHexString(signature) + " time: " + timestamp + " nonce: " + nonce + " content: " + Utils.bytesToHexString(content)); // ECKey asdf = new ECKey(null, key.getPubKey(), true); // try { // asdf.verifyMessage(toSign, new String(Base64.encode(signature))); // } catch (SignatureException ex) { // System.out.println("dbhjadgwjgewzj"); // Logger.getLogger(RawMsg.class.getName()).log(Level.SEVERE, null, ex); // } // System.out.println("laenge::: " + signature.length); // System.out.println("test..."); // try { // //key.verifyMessage(toSign, new String(Base64.encode(Base64.decode(signMessage)))); // key.verifyMessage("" + timestamp + "" + nonce + "" + content, new String(Base64.encode(signature))); // } catch (SignatureException ex) { // ex.printStackTrace(); // } } public boolean verify() { byte[] encodeToDER = signature.clone(); byte[] newBytes = new byte[encodeToDER.length]; int index = encodeToDER.length - 1; while (true) { System.arraycopy(encodeToDER, 0, newBytes, 0, index + 1); if (newBytes[index] == (byte) 0) { newBytes = new byte[index]; index--; } else { break; } } //String toVerify = "" + timestamp + "" + nonce + "" + new String(content, "UTF-8"); //boolean verify = key.verify(content, signature); byte[] toVerify = new byte[1 + 8 + 4 + content.length]; ByteBuffer wrap = ByteBuffer.wrap(toVerify); wrap.put(public_type); wrap.putLong(timestamp); wrap.putInt(nonce); wrap.put(content); Sha256Hash hash2 = Sha256Hash.create(toVerify); //boolean verify = key.verify(hash2.getBytes(), newBytes); boolean verify = key.verify(hash2.getBytes(), encodeToDER); //System.out.println("signature len: " + newBytes.length + " " + Utils.bytesToHexString(newBytes)); //System.out.println("" + verify); //System.out.println("" + verify); // // boolean verify = false; // try { // verify = key.verify(toVerify.getBytes(), signature); // } catch (RuntimeException e) { // e.printStackTrace(); // } return verify; } public RawMsg toSpecificMsgType() { getChannel();//searches channel if (channel == null) { return this; } decrypt(); //Wrong key? if (decryptedContent == null || decryptedContent.length == 0) { System.out.println("Wrong crypt key for channel '" + channel.getName() + "'."); return this; //throw new RuntimeException("Wrong crypt key for channel"); } //check for block if (public_type == 0) { return new BlockMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); } else //Check for plain text if (decryptedContent[0] == TextMsg.BYTE) { TextMsg textMsg = new TextMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); return textMsg; } else //Check for deliveredMsg if (decryptedContent[0] == DeliveredMsg.BYTE) { DeliveredMsg deliveredMsg = new DeliveredMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); return deliveredMsg; } else //Check for ControlMsg if (decryptedContent[0] == ControlMsg.BYTE) { ControlMsg controlMsg = new ControlMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); return controlMsg; } else //Check for ImageMsg if (decryptedContent[0] == ImageMsg.BYTE) { ImageMsg imageMsg = new ImageMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); return imageMsg; } else //Check for InfoMsg if (decryptedContent[0] == InfoMsg.BYTE) { InfoMsg infoMsg = new InfoMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); return infoMsg; } return this; } public void encrypt() { if (channel.isPublic()) { content = AESCrypt.encode(channel.getExtraEncryptionKey(), timestamp, decryptedContent); } else { content = AESCrypt.encode(key.getPrivKeyBytes(), timestamp, decryptedContent); } } public void decrypt() { if (channel.isPublic()) { decryptedContent = AESCrypt.decode(channel.getExtraEncryptionKey(), timestamp, content); } else { decryptedContent = AESCrypt.decode(key.getPrivKeyBytes(), timestamp, content); } } public Channel getChannel() { if (channel != null) { return channel; } Channel findBytePublicKey = Channel.findBytePublicKey(key); channel = findBytePublicKey; if (channel != null) { //Update to new found key, now we should have the private in it! key = channel.getKey(); readable = true; } return channel; } @Override public int compareTo(RawMsg o) { return (int) (timestamp - o.timestamp); } @Deprecated public RawMsg clone() throws CloneNotSupportedException { RawMsg rawMsg = new RawMsg(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id); rawMsg.public_type = public_type; return rawMsg; } }