/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.redPandaLib.core;
import org.redPandaLib.crypt.AddressFormatException;
import org.redPandaLib.crypt.Base58;
import org.redPandaLib.crypt.ECKey;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.*;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.redPandaLib.Main;
import org.redPandaLib.crypt.RSAKey;
import org.redPandaLib.crypt.Sha256Hash;
/**
*
* @author rflohr
*/
public class Channel implements Serializable, Comparable<Channel> {
private static final long serialVersionUID = -4056734674983489374L;
protected int id = -1;
protected ECKey key;
protected String securityHash;
protected String name;
protected double diffuculty = 0;
public long displayPriority = 0;
public HashMap<PeerTrustData, Integer> rating = new HashMap<PeerTrustData, Integer>();
public boolean useForContactExchange = false;
protected byte[] extraEncryptionKey = null;
boolean pub = false;
public String getName() {
return name;
}
public Channel() {
}
public Channel(ECKey key, String name) {
this.key = key;
this.name = name;
}
public Channel(ECKey key, String name, int id) {
this(key, name);
this.id = id;
}
public static Channel generateNew(String name) {
Channel newIdentity = new Channel();
newIdentity.key = new ECKey();
System.out.println("priv key: " + byte2String(newIdentity.key.getPrivKeyBytes()));
System.out.println("pub key: " + byte2String(newIdentity.key.getPubKey()));
newIdentity.name = name;
newIdentity.addToList();
return newIdentity;
}
public static Channel generateNewPublic(String name) {
// Channel newIdentity = new Channel();
//
//
// while (true) {
// newIdentity.key = new ECKey();
//
// //System.out.println("kkk");
//
// boolean wrong = false;
//
// //System.out.println("" + byte2String(newIdentity.key.getPubKeyHash()));
//
// //System.out.println("" + newIdentity.key.getPubKey()[1]);
//
//// for (int i = 1; i < 2; i++) {
////
////
////
//// if (newIdentity.key.getPubKey()[i] != (byte) 0) {
//// wrong = true;
//// }
//// }
//
// if (!byte2String(newIdentity.key.getPubKey()).matches("pub(.*)")) {
// wrong = true;
// }
//
// if (!wrong) {
// break;
// }
//
// }
//
//
//
// System.out.println("priv key: " + byte2String(newIdentity.key.getPrivKeyBytes()));
// System.out.println("pub key: " + byte2String(newIdentity.key.getPubKey()));
//
// newIdentity.name = name;
Channel generateNew = generateNew(name);
generateNew.pub = true;
return generateNew;
}
public String stringIdentity() {
return byte2String(key.getPubKey());
}
public String getPrivateKey() {
return byte2String(key.getPrivKeyBytes());
}
public static Channel getInstanceByPublicKey(String publicKey) {
try {
return getInstanceByPublicKey(string2Byte(publicKey));
} catch (IOException ex) {
Logger.getLogger(Channel.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public static Channel getInstanceByPublicKey(byte[] publicKey) {
Channel channel = new Channel();
channel.key = new ECKey(BigInteger.ZERO, publicKey, false);
channel.name = "unknown";
for (Channel c : Test.getChannels()) {
if (channel.equals(c)) {
return c;
}
}
return channel;
}
public static Channel getInstaceByPrivateKey(String privKeyBase58, String name, int id) {
try {
ECKey eCKey = new ECKey(new BigInteger(1, Base58.decode(privKeyBase58)), null, true);
return new Channel(eCKey, name, id);
} catch (AddressFormatException ex) {
}
return null;
}
public static String byte2String(byte[] b) {
// BASE64Encoder basE64Encoder = new BASE64Encoder();
// String encode = basE64Encoder.encode(b);
// String replaceAll = encode.replaceAll("\n", "");
// return replaceAll;
//return Base64.encodeToString(b, false);
return Base58.encode(b);
}
public static byte[] string2Byte(String in) throws IOException {
try {
// BASE64Decoder basE64Decoder = new BASE64Decoder();
// return decodeBuffer;
// return decodeBuffer;
//return Base64.decode(in);
return Base58.decode(in);
} catch (AddressFormatException ex) {
Logger.getLogger(Channel.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String sign(String str) {
return key.signMessage(str);
}
public boolean verifyString(String str, String signature) {
try {
key.verifyMessage(str, signature);
return true;
} catch (SignatureException ex) {
}
return false;
}
public String encrypt(String in) {
String out = null;
return out;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Channel) {
Channel o = (Channel) obj;
return key.equals(o.key);
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 11 * hash + (this.key != null ? this.key.hashCode() : 0);
return hash;
}
public ECKey getKey() {
return key;
}
@Override
public String toString() {
return name;
}
public int getId() {
return id;
}
public static Channel getChannelById(int id) {
for (Channel c : Test.getChannels()) {
if (c.id == id) {
return c;
}
}
return null;
}
public static int getNextId() {
LocalSettings localSettings = Test.getLocalSettings();
int out;
while (true) {
localSettings.channelIdCounter++;
out = localSettings.channelIdCounter;
boolean inUse = false;
for (Channel c : Main.getChannels()) {
if (c.id == out) {
inUse = true;
break;
}
}
if (!inUse) {
break;
}
}
localSettings.save();
return out;
}
public void setName(String name) {
this.name = name;
Test.saver.saveIdentities(Test.channels);
}
public String exportForHumans() {
String prefix = "";
byte[] mainBytes;
System.out.println("channel: " + id + " pub: " + pub);
if (pub) {
prefix = "pu";
mainBytes = key.getPubKey();
System.out.println("public key bytes used");
} else {
prefix = "pr";
mainBytes = key.getPrivKeyBytes();
}
ByteBuffer buffer = ByteBuffer.allocate(100);
buffer.put(prefix.getBytes());
buffer.put(mainBytes);
buffer.flip();
byte[] b = new byte[buffer.remaining()];
buffer.get(b);
Sha256Hash hash = Sha256Hash.createDouble(b);
byte[] bytes = hash.getBytes();
byte[] checksum = new byte[8];
for (int i = 0; i < checksum.length; i++) {
checksum[i] = bytes[i];
}
byte[] outBytes = new byte[mainBytes.length + checksum.length];
System.arraycopy(mainBytes, 0, outBytes, 0, mainBytes.length);
System.arraycopy(checksum, 0, outBytes, mainBytes.length, checksum.length);
String out = prefix;
out += Base58.encode(outBytes);
//out += "-";
//out += Base58.encode(checksum);
return out;
}
public static Channel importFromHuman(String address, String name) throws AddressFormatException {
if (address.length() < 4) {
return null;
}
address = address.replaceAll(" ", "");
String prefix = address.substring(0, 2);
System.out.println("Prefix: " + prefix);
boolean pub = (prefix.equals("pu"));
String remaining = address.substring(2, address.length());
System.out.println("rest: " + remaining);
byte[] bytes = Base58.decode(remaining);
if (pub) {
byte[] publicKeyBytes = new byte[33];
System.arraycopy(bytes, 0, publicKeyBytes, 0, publicKeyBytes.length);
ECKey ecKey = new ECKey(null, publicKeyBytes);
Channel channel = new Channel(ecKey, name);
channel.pub = true;
System.out.println("public channel: " + channel.exportForHumans());
System.out.println("given: " + address);
if (!channel.exportForHumans().equals(address)) {
return null;
}
return channel;
} else {
byte[] privateBytes = new byte[32];
System.arraycopy(bytes, 0, privateBytes, 0, privateBytes.length);
//ECKey ecKey = new ECKey(privateBytes, null);
ECKey ecKey = new ECKey(new BigInteger(1, privateBytes), null, true);
Channel channel = new Channel(ecKey, name);
channel.pub = false;
System.out.println("private channel: " + channel.exportForHumans());
if (!channel.exportForHumans().equals(address)) {
return null;
}
return channel;
}
}
public static Channel findBytePublicKey(ECKey key) {
for (Channel c : Test.channels) {
if (c.key.equals(key)) {
return c;
}
}
return null;
}
public boolean addToList() {
id = Channel.getNextId();
new Thread() {
@Override
public void run() {
if (Test.peerList != null) {
for (Peer p : Test.getClonedPeerList()) {
p.disconnect("added new channel");
}
Test.triggerOutboundthread();
}
}
}.start();
return Test.addChannel(this);
}
@Override
public int compareTo(Channel o) {
return (int) ((int) diffuculty - o.diffuculty);
}
public void setId(int id) {
this.id = id;
}
public void setExtraEncryptionKey(byte[] extraEncryptionKey) {
this.extraEncryptionKey = extraEncryptionKey;
}
public byte[] getExtraEncryptionKey() {
return extraEncryptionKey;
}
public void setPublic(boolean pub) {
this.pub = pub;
}
public boolean isPublic() {
return pub;
}
public boolean isWriteable() {
return key.getPrivKeyBytes() != null;
}
}