public PublicKey getNodeKey() { return myInfo.getPublicKey(); }
/** * Start new client protocol session. It doesn't load network configuration. Only creates client protocol session with given node * @param myPrivateKey client private key * @param nodeInfo node info specifying node public key and url * @param session set to null or to the reconstructed instance * @throws IOException */ public Client(PrivateKey myPrivateKey, NodeInfo nodeInfo, BasicHttpClientSession session) throws IOException { httpClient = new BasicHttpClient(nodeInfo.publicUrlString()); this.clientPrivateKey = myPrivateKey; this.nodePublicKey = nodeInfo.getPublicKey(); httpClient.start(myPrivateKey, nodeInfo.getPublicKey(), session); }
@Override public void addNode(NodeInfo nodeInfo) { try (PooledDb db = dbPool.db()) { String sqlText = "insert into config(http_client_port,http_server_port,udp_server_port, node_number, node_name, public_host,host,public_key) values(?,?,?,?,?,?,?,?);"; try ( PreparedStatement statement = db.statementReturningKeys(sqlText) ) { statement.setInt(1, nodeInfo.getClientAddress().getPort()); statement.setInt(2, nodeInfo.getServerAddress().getPort()); statement.setInt(3, nodeInfo.getNodeAddress().getPort()); statement.setInt(4, nodeInfo.getNumber()); statement.setString(5, nodeInfo.getName()); statement.setString(6, nodeInfo.getPublicHost()); statement.setString(7, nodeInfo.getClientAddress().getHostName()); statement.setBytes(8, nodeInfo.getPublicKey().pack()); db.updateWithStatement(statement); } catch (Exception e) { e.printStackTrace(); throw e; } } catch (SQLException se) { se.printStackTrace(); throw new Failure("add node failed:" + se); } catch (Exception e) { e.printStackTrace(); } }
/** * We have received {@link PacketTypes#NACK} packet. Means that session is broken, e.g. remote node was * rebooted. Need to restart handshake procedure immediately. * @param packet received {@link Packet} */ private void onReceiveNack(Packet packet) throws EncryptionError, SymmetricKey.AuthenticationFailed { report(logLabel, ()->"received nack from " + packet.senderNodeId, VerboseLevel.BASE); Session session = getOrCreateSession(packet.senderNodeId); if (session != null) { if (session.state.get() == Session.STATE_EXCHANGING) { List dataList = Boss.load(packet.payload); byte[] data = ((Bytes)dataList.get(0)).toArray(); byte[] sign = ((Bytes)dataList.get(1)).toArray(); if (new PublicKey(session.remoteNodeInfo.getPublicKey().pack()).verify(data, sign, HashType.SHA512)) { List nackPacketIdList = Boss.load(data); Integer nackPacketId = (int)nackPacketIdList.get(0); if (session.retransmitMap.containsKey(nackPacketId)) { session.startHandshake(); restartHandshakeIfNeeded(session, Instant.now()); } } } } }
statement.setString(6, nodeInfo.getPublicHost()); statement.setString(7, nodeInfo.getClientAddress().getHostName()); statement.setBytes(8, nodeInfo.getPublicKey().pack());
private void checkNode(Session session, boolean checkKeyLimit) throws CommandFailedException { // checking node if (node == null) { throw new CommandFailedException(Errors.NOT_READY, "", "please call again after a while"); } if(node.isSanitating()) { //WHILE NODE IS SANITATING IT COMMUNICATES WITH THE OTHER NODES ONLY if(netConfig.toList().stream().anyMatch(nodeInfo -> nodeInfo.getPublicKey().equals(session.getPublicKey()))) return; throw new CommandFailedException(Errors.NOT_READY, "", "please call again after a while"); } // checking key limit if (checkKeyLimit) if (!node.checkKeyLimit(session.getPublicKey())) throw new CommandFailedException(Errors.COMMAND_FAILED, "", "exceeded the limit of requests for key per minute, please call again after a while"); }
byte[] remoteNonce = ((Bytes)packetData.get(0)).toArray(); byte[] packetSign = ((Bytes)packetData.get(1)).toArray(); if (new PublicKey(session.remoteNodeInfo.getPublicKey().pack()).verify(remoteNonce, packetSign, HashType.SHA512)) { session.removeHandshakePacketsFromRetransmitMap(); session.remoteNonce = remoteNonce; List data = Arrays.asList(session.localNonce, session.remoteNonce); byte[] packed = Boss.pack(data); byte[] encrypted = new PublicKey(session.remoteNodeInfo.getPublicKey().pack()).encrypt(packed); byte[] sign = new PrivateKey(ownPrivateKey.pack()).sign(encrypted, HashType.SHA512);
protected void sendDataGarbage(NodeInfo myNodeInfo, NodeInfo destination, UDPAdapter udpAdapter, DatagramSocket socket) throws Exception { byte[] data = new PublicKey(destination.getPublicKey().pack()).encrypt(Do.randomBytes(64)); byte[] crc32 = new Crc32().digest(data); byte[] payload = new byte[data.length + crc32.length]; System.arraycopy(data, 0, payload, 0, data.length); System.arraycopy(crc32, 0, payload, data.length, crc32.length); UDPAdapter.Packet packet = udpAdapter.createTestPacket( new Random().nextInt(Integer.MAX_VALUE), myNodeInfo.getNumber(), destination.getNumber(), UDPAdapter.PacketTypes.DATA, payload); sendBlock(packet, socket, destination); }
byte[] encrypted = session.handshake_sessionPart1; byte[] sign = session.handshake_sessionPart2; if (new PublicKey(session.remoteNodeInfo.getPublicKey().pack()).verify(encrypted, sign, HashType.SHA512)) { byte[] decryptedData = new PrivateKey(ownPrivateKey.pack()).decrypt(encrypted); List data = Boss.load(decryptedData);
protected void sendWelcome(NodeInfo myNodeInfo, NodeInfo destination, UDPAdapter udpAdapter, DatagramSocket socket) throws Exception { byte[] payload = new PublicKey(destination.getPublicKey().pack()).encrypt(Do.randomBytes(64)); UDPAdapter.Packet packet = udpAdapter.createTestPacket( new Random().nextInt(Integer.MAX_VALUE), myNodeInfo.getNumber(), destination.getNumber(), UDPAdapter.PacketTypes.WELCOME, payload); sendBlock(packet, socket, destination); }
if(contractNodes.size() != ownerKeys.size() || !contractNodes.stream().allMatch(nodeInfo -> nodeInfo instanceof NodeInfo && ownerKeys.contains(((NodeInfo)nodeInfo).getPublicKey()))) { return false;
byte[] packet_remoteNonce = ((Bytes) nonceList.get(1)).toArray(); if (Arrays.equals(packet_remoteNonce, sessionReader.localNonce)) { if (new PublicKey(sessionReader.remoteNodeInfo.getPublicKey().pack()).verify(encrypted, sign, HashType.SHA512)) { report(logLabel, ()->"key_req successfully verified", VerboseLevel.BASE); sessionReader.remoteNonce = packet_senderNonce;
/** * This is first step of creation and installation of the session. * @param session is {@link Session} in which sending is. */ private void sendHello(Session session) { try { report(logLabel, () -> "send hello to " + session.remoteNodeInfo.getNumber(), VerboseLevel.BASE); byte[] helloNonce = Do.randomBytes(64); Packet packet = new Packet(getNextPacketId(), myNodeInfo.getNumber(), session.remoteNodeInfo.getNumber(), PacketTypes.HELLO, new PublicKey(session.remoteNodeInfo.getPublicKey().pack()).encrypt(helloNonce)); sendPacket(session.remoteNodeInfo, packet); session.addPacketToRetransmitMap(packet.packetId, packet, helloNonce); } catch (EncryptionError e) { callErrorCallbacks("(sendHello) EncryptionError: " + e); } }
/** * Someone who sent {@link PacketTypes#HELLO} typed {@link Packet}, * send us new KEY_REQ typed {@link Packet} - if all is ok we send session keys to. * SESSION's payload is more than 512 bytes, so used two parts here. * From now we ready to data exchange. * @param sessionReader is {@link SessionReader} in which sending is. */ private void sendSessionKey(SessionReader sessionReader) throws EncryptionError { report(logLabel, ()->"send session_key to "+sessionReader.remoteNodeInfo.getNumber(), VerboseLevel.BASE); List data = Arrays.asList(sessionReader.sessionKey.getKey(), sessionReader.remoteNonce); byte[] packed = Boss.pack(data); byte[] encrypted = new PublicKey(sessionReader.remoteNodeInfo.getPublicKey().pack()).encrypt(packed); byte[] sign = new PrivateKey(ownPrivateKey.pack()).sign(encrypted, HashType.SHA512); Packet packet1 = new Packet(getNextPacketId(), myNodeInfo.getNumber(), sessionReader.remoteNodeInfo.getNumber(), PacketTypes.SESSION_PART1, encrypted); Packet packet2 = new Packet(getNextPacketId(), myNodeInfo.getNumber(), sessionReader.remoteNodeInfo.getNumber(), PacketTypes.SESSION_PART2, sign); sendPacket(sessionReader.remoteNodeInfo, packet1); sendPacket(sessionReader.remoteNodeInfo, packet2); sessionReader.addPacketToRetransmitMap(packet1.packetId, packet1, encrypted); sessionReader.addPacketToRetransmitMap(packet2.packetId, packet2, sign); }
private Contract createNetConfigContract(Contract contract, List<NodeInfo> netConfig, Collection<PrivateKey> currentConfigKeys) throws IOException { contract = contract.createRevision(); ListRole listRole = new ListRole("owner"); for(NodeInfo ni: netConfig) { SimpleRole role = new SimpleRole(ni.getName()); contract.registerRole(role); role.addKeyRecord(new KeyRecord(ni.getPublicKey())); listRole.addRole(role); } listRole.setQuorum(netConfig.size()-1); contract.registerRole(listRole); contract.getStateData().set("net_config",netConfig); List<KeyRecord> creatorKeys = new ArrayList<>(); for(PrivateKey key : currentConfigKeys) { creatorKeys.add(new KeyRecord(key.getPublicKey())); contract.addSignerKey(key); } contract.setCreator(creatorKeys); contract.seal(); return contract; }
nodes.add(Binder.of( "url", node.publicUrlString(), "key", node.getPublicKey().pack(), "number", node.getNumber() ));
private Contract createNetConfigContract(List<NodeInfo> netConfig,PrivateKey issuerKey) throws IOException { Contract contract = new Contract(); contract.setIssuerKeys(issuerKey.getPublicKey()); contract.registerRole(new RoleLink("creator", "issuer")); ListRole listRole = new ListRole("owner"); for(NodeInfo ni: netConfig) { SimpleRole role = new SimpleRole(ni.getName()); contract.registerRole(role); role.addKeyRecord(new KeyRecord(ni.getPublicKey())); listRole.addRole(role); } listRole.setQuorum(netConfig.size()-1); contract.registerRole(listRole); RoleLink ownerLink = new RoleLink("ownerlink","owner"); ChangeOwnerPermission changeOwnerPermission = new ChangeOwnerPermission(ownerLink); HashMap<String,Object> fieldsMap = new HashMap<>(); fieldsMap.put("net_config",null); Binder modifyDataParams = Binder.of("fields",fieldsMap); ModifyDataPermission modifyDataPermission = new ModifyDataPermission(ownerLink,modifyDataParams); contract.addPermission(changeOwnerPermission); contract.addPermission(modifyDataPermission); contract.setExpiresAt(ZonedDateTime.now().plusYears(40)); contract.getStateData().set("net_config",netConfig); contract.addSignerKey(issuerKey); contract.seal(); return contract; }