public static String byteArrayToHexString(byte[] b) { if(b == null) return "null"; return byteArrayToHexString(b, 0, b.length); }
public String toString() { if(type == null) return "n/a"; switch(type) { case SECRET_KEY_REQ: return String.format("%s dh-key %d bytes", type, dh_key.length); case SECRET_KEY_RSP: return String.format("%s dh-key %d bytes, encrypted secret %d bytes, version: %s", type, dh_key.length, encrypted_secret_key.length, Util.byteArrayToHexString(secret_key_version)); default: return "n/a"; } } }
protected static String print16(PublicKey pub_key) { // use SHA256 to create a hash of secret_key and only then truncate it to secret_key_length MessageDigest digest=null; try { digest=MessageDigest.getInstance("SHA-256"); digest.update(pub_key.getEncoded()); return Util.byteArrayToHexString(digest.digest(), 0, 16); } catch(NoSuchAlgorithmException e) { return e.toString(); } }
protected static String print16(PublicKey pub_key) { // use SHA256 to create a hash of secret_key and only then truncate it to secret_key_length MessageDigest digest=null; try { digest=MessageDigest.getInstance("SHA-256"); digest.update(pub_key.getEncoded()); return Util.byteArrayToHexString(digest.digest(), 0, 16); } catch(NoSuchAlgorithmException e) { return e.toString(); } }
@ManagedAttribute public String version() {return Util.byteArrayToHexString(sym_version);}
public String toString() { return String.format("%s [version=%s]", typeToString(type), (version != null? Util.byteArrayToHexString(version) : "null")); }
@Override protected void handleUnknownVersion(byte[] version) { if(!isKeyServer()) { log.debug("%s: received msg encrypted with version %s (my version: %s), getting new secret key from %s", local_addr, Util.byteArrayToHexString(version), Util.byteArrayToHexString(sym_version), key_server_addr); sendKeyRequest(key_server_addr); } }
protected synchronized void setKeys(Address sender, SecretKey key, byte[] version) throws Exception { if(Arrays.equals(this.sym_version, version)) { log.debug("%s: ignoring secret key received from %s (version: %s), as it has already been installed", local_addr, sender != null? sender : "key exchange protocol", Util.byteArrayToHexString(version)); return; } Cipher decoding_cipher=secret_key != null? decoding_ciphers.take() : null; // put the previous key into the map, keep the cipher: no leak, as we'll recreate decoding_ciphers in initSymCiphers() if(decoding_cipher != null) key_map.putIfAbsent(new AsciiString(version), decoding_cipher); log.debug("%s: installing secret key received from %s (version: %s)", local_addr, sender != null? sender : "key exchange protocol", Util.byteArrayToHexString(version)); secret_key=key; initSymCiphers(key.getAlgorithm(), key); sym_version=version; }
public void fetchSecretKeyFrom(Address target) throws Exception { try(SSLSocket sock=createSocketTo(target)) { DataInput in=new DataInputStream(sock.getInputStream()); OutputStream out=sock.getOutputStream(); // send the secret key request out.write(Type.SECRET_KEY_REQ.ordinal()); out.flush(); byte ordinal=in.readByte(); Type rsp=Type.values()[ordinal]; if(rsp != Type.SECRET_KEY_RSP) throw new IllegalStateException(String.format("expected response of %s but got type=%d", Type.SECRET_KEY_RSP, ordinal)); int version_len=in.readInt(); byte[] version=new byte[version_len]; in.readFully(version); int secret_key_len=in.readInt(); byte[] secret_key=new byte[secret_key_len]; in.readFully(secret_key); SecretKey sk=new SecretKeySpec(secret_key, secret_key_algorithm); Tuple<SecretKey,byte[]> tuple=new Tuple<>(sk, version); log.debug("%s: sending up secret key (version: %s)", local_addr, Util.byteArrayToHexString(version)); up_prot.up(new Event(Event.SET_SECRET_KEY, tuple)); } }
protected void createNewKey() { try { this.secret_key=createSecretKey(); initSymCiphers(sym_algorithm, secret_key); log.debug("%s: created new secret key (version: %s)", local_addr, Util.byteArrayToHexString(sym_version)); } catch(Exception ex) { log.error("%s: failed creating secret key and initializing ciphers", local_addr, ex); } }
/** send client's public key to server and request server's public key */ protected void sendKeyRequest(Address key_server) { if(key_server == null) return; if(last_key_request == 0 || System.currentTimeMillis() - last_key_request > min_time_between_key_requests) last_key_request=System.currentTimeMillis(); else return; if(use_external_key_exchange) { log.debug("%s: asking key exchange protocol to get secret key from %s", local_addr, key_server); down_prot.down(new Event(Event.FETCH_SECRET_KEY, key_server)); return; } log.debug("%s: asking %s for the secret key (my version: %s)", local_addr, key_server, Util.byteArrayToHexString(sym_version)); Message newMsg=new Message(key_server, key_pair.getPublic().getEncoded()).src(local_addr) .putHeader(this.id,new EncryptHeader(EncryptHeader.SECRET_KEY_REQ, null)); down_prot.down(newMsg); }
protected void handleSecretKeyResponse(PublicKey dh_public_key, byte[] encrypted_secret_key, byte[] version, Address sender) throws Exception { Tuple<SecretKey,byte[]> tuple=null; log.debug("%s: received public key rsp %s.. from %s", local_addr, print16(dh_public_key), sender); synchronized(this) { key_agreement.doPhase(dh_public_key, true); // Diffie-Hellman secret session key, to decrypt secret key byte[] secret_session_key=key_agreement.generateSecret(); SecretKey hashed_session_key=hash(secret_session_key); Cipher encrypter=Cipher.getInstance(secret_key_algorithm); encrypter.init(Cipher.DECRYPT_MODE, hashed_session_key); byte[] secret_key=encrypter.doFinal(encrypted_secret_key); // <-- this is the shared group key SecretKey sk=new SecretKeySpec(secret_key, secret_key_algorithm); tuple=new Tuple<>(sk, version); dh_key=null; } log.debug("%s: sending up secret key (version: %s)", local_addr, Util.byteArrayToHexString(version)); up_prot.up(new Event(Event.SET_SECRET_KEY, tuple)); }
protected void sendSecretKey(Key secret_key, PublicKey public_key, Address source) throws Exception { byte[] encryptedKey=encryptSecretKey(secret_key, public_key); Message newMsg=new Message(source, encryptedKey).src(local_addr) .putHeader(this.id, new EncryptHeader(EncryptHeader.SECRET_KEY_RSP, symVersion())); log.debug("%s: sending secret key response to %s (version: %s)", local_addr, source, Util.byteArrayToHexString(sym_version)); down_prot.down(newMsg); }
protected void handleSecretKeyResponse(final Message msg, final byte[] key_version) { if(!inView(msg.src(), "ignoring secret key sent by %s which is not in current view %s")) return; if(Arrays.equals(sym_version, key_version)) { log.debug("%s: secret key (version %s) already installed, ignoring key response from %s", local_addr, Util.byteArrayToHexString(key_version), msg.src()); return; } try { SecretKey tmp=decodeKey(msg.getBuffer()); if(tmp == null) sendKeyRequest(key_server_addr); // unable to understand response, let's try again else setKeys(msg.src(), tmp, key_version); // otherwise set the received key as the shared key } catch(Exception e) { log.warn("%s: unable to process key received from %s: %s", local_addr, msg.src(), e); } }
public static String byteArrayToHexString(byte[] b) { if(b == null) return "null"; return byteArrayToHexString(b, 0, b.length); }
public String toString() { if(type == null) return "n/a"; switch(type) { case SECRET_KEY_REQ: return String.format("%s dh-key %d bytes", type, dh_key.length); case SECRET_KEY_RSP: return String.format("%s dh-key %d bytes, encrypted secret %d bytes, version: %s", type, dh_key.length, encrypted_secret_key.length, Util.byteArrayToHexString(secret_key_version)); default: return "n/a"; } } }
protected static String print16(PublicKey pub_key) { // use SHA256 to create a hash of secret_key and only then truncate it to secret_key_length MessageDigest digest=null; try { digest=MessageDigest.getInstance("SHA-256"); digest.update(pub_key.getEncoded()); return Util.byteArrayToHexString(digest.digest(), 0, 16); } catch(NoSuchAlgorithmException e) { return e.toString(); } }
@Override protected void handleUnknownVersion(byte[] version) { if(!isKeyServer()) { log.debug("%s: received msg encrypted with version %s (my version: %s), getting new secret key from %s", local_addr, Util.byteArrayToHexString(version), Util.byteArrayToHexString(sym_version), key_server_addr); sendKeyRequest(key_server_addr); } }
protected void createNewKey() { try { this.secret_key=createSecretKey(); initSymCiphers(sym_algorithm, secret_key); log.debug("%s: created new secret key (version: %s)", local_addr, Util.byteArrayToHexString(sym_version)); } catch(Exception ex) { log.error("%s: failed creating secret key and initializing ciphers", local_addr, ex); } }
protected void sendSecretKey(Key secret_key, PublicKey public_key, Address source) throws Exception { byte[] encryptedKey=encryptSecretKey(secret_key, public_key); Message newMsg=new Message(source, encryptedKey).src(local_addr) .putHeader(this.id, new EncryptHeader(EncryptHeader.SECRET_KEY_RSP, symVersion())); log.debug("%s: sending secret key response to %s (version: %s)", local_addr, source, Util.byteArrayToHexString(sym_version)); down_prot.down(newMsg); }