encrypt.java
来自「JGRoups源码」· Java 代码 · 共 1,405 行 · 第 1/3 页
JAVA
1,405 行
getAlgorithm(asymAlgorithm), asymProvider); } else { KpairGen = KeyPairGenerator .getInstance(getAlgorithm(asymAlgorithm)); } KpairGen.initialize(asymInit, new SecureRandom()); Kpair = KpairGen.generateKeyPair(); // set up the Cipher to decrypt secret key responses encrypted with our key asymCipher = Cipher.getInstance(asymAlgorithm); asymCipher.init(Cipher.DECRYPT_MODE,Kpair.getPrivate()); if (log.isInfoEnabled()) log.info(" asym algo initialized"); } /** Just remove if you don't need to reset any state */ public void reset() { } /* (non-Javadoc) * @see org.jgroups.stack.Protocol#up(org.jgroups.Event) */ public void up(Event evt) { switch (evt.getType()) { // we need to know what our address is case Event.SET_LOCAL_ADDRESS : local_addr = (Address) evt.getArg(); if (log.isDebugEnabled()) log.debug("set local address to " + local_addr); break; case Event.VIEW_CHANGE: View view=(View)evt.getArg(); if (log.isInfoEnabled()) log.info("handling view: " + view); if (!suppliedKey){ handleViewChange(view); } break; // we try and decrypt all messages case Event.MSG : try { handleUpMessage(evt); } catch (Exception e) { log.warn("exception occurred decrypting message", e); } return; default : break; } passUp(evt); } private synchronized void handleViewChange(View view){ // if view is a bit broken set me as keyserver if (view.getMembers() == null || view.getMembers().get(0) == null){ becomeKeyServer(local_addr); return; } // otherwise get keyserver from view controller Address tmpKeyServer = (Address)view.getMembers().get(0); //I am new keyserver - either first member of group or old key server is no more and // I have been voted new controller if (tmpKeyServer.equals(local_addr) && (keyServerAddr == null || (! tmpKeyServer.equals(keyServerAddr)))){ becomeKeyServer(tmpKeyServer); // a new keyserver has been set and it is not me }else if (keyServerAddr == null || (! tmpKeyServer.equals(keyServerAddr))){ handleNewKeyServer(tmpKeyServer); } else{ if (log.isDebugEnabled()) log.debug("Membership has changed but I do not care"); } } /** * Handles becoming server - resetting queue settings * and setting keyserver address to be local address. * * @param tmpKeyServer */ private void becomeKeyServer(Address tmpKeyServer){ keyServerAddr = tmpKeyServer; keyServer =true; if (log.isInfoEnabled()) log.info("I have become key server " + keyServerAddr); queue_down = false; queue_up = false; } /** * Sets up the peer for a new keyserver - this is * setting queueing to buffer messages until we have a new * secret key from the key server and sending a key request * to the new keyserver. * * @param newKeyServer */ private void handleNewKeyServer(Address newKeyServer){ // start queueing until we have new key // to make sure we are not sending with old key queue_up =true; queue_down = true; // set new keyserver address keyServerAddr = newKeyServer; keyServer =false; if (log.isInfoEnabled()) log.info("Sending key request"); // create a key request message sendKeyRequest(); } /** * @param evt */ private void handleUpMessage(Event evt) throws Exception { Message msg = (Message) evt.getArg(); if (msg == null) { if (trace) log.trace("null message - passing straight up"); passUp(evt); return; } if(msg.getLength() == 0) { passUp(evt); return; } EncryptHeader hdr = (EncryptHeader)msg.getHeader(EncryptHeader.KEY); // try and get the encryption header if (hdr == null) { if (log.isTraceEnabled()) log.trace("dropping message as ENCRYPT header is null or has not been recognized, msg will not be passed up, " + "headers are " + msg.getHeaders()); return; } if (trace) log.trace("header received " + hdr); // if a normal message try and decrypt it if (hdr.getType() == EncryptHeader.ENCRYPT) { // if msg buffer is empty, and we didn't encrypt the entire message, just pass up if (!hdr.encrypt_entire_msg && ((Message)evt.getArg()).getLength() == 0) { if (trace) log.trace("passing up message as it has an empty buffer "); passUp(evt); return; } // if queueing then pass into queue to be dealt with later if (queue_up){ if (trace) log.trace("queueing up message as no session key established: " + evt.getArg()); upMessageQueue.put(evt); } else{ // make sure we pass up any queued messages first // could be more optimised but this can wait // we only need this if not using supplied key if (!suppliedKey) { drainUpQueue(); } // try and decrypt the message Message tmpMsg=decryptMessage(symDecodingCipher, msg); if (tmpMsg != null){ if(trace) log.trace("decrypted message " + tmpMsg); passUp(new Event(Event.MSG, tmpMsg)); } else { log.warn("Unrecognised cipher discarding message"); } } } else { // check if we had some sort of encrypt control // header if using supplied key we should not // process it if (suppliedKey) { if (log.isWarnEnabled()) { log.warn("We received an encrypt header of " + hdr.getType() + " while in configured mode"); } } else{ // see what sort of encrypt control message we // have received switch (hdr.getType()){ // if a key request case EncryptHeader.KEY_REQUEST: if (log.isInfoEnabled()) { log.info("received a key request from peer"); } //if a key request send response key back try { // extract peer's public key PublicKey tmpKey = generatePubKey(msg.getBuffer()); // send back the secret key we have sendSecretKey(getSecretKey(), tmpKey, msg.getSrc()); } catch (Exception e){ log.warn("unable to reconstitute peer's public key"); } break; case EncryptHeader.SECRETKEY: if (log.isInfoEnabled()) { log.info("received a secretkey response from keyserver"); } try { SecretKey tmp = decodeKey(msg.getBuffer()); if (tmp == null) { // unable to understand response // lets try again sendKeyRequest(); }else{ // otherwise lets set the reurned key // as the shared key setKeys(tmp, hdr.getVersion()); if (log.isInfoEnabled()) { log.info("Decoded secretkey response"); } } } catch (Exception e){ log.warn("unable to process received public key"); } break; default: log.warn("Received ignored encrypt header of "+hdr.getType()); break; } } } } /** * used to drain the up queue - synchronized so we * can call it safely despite access from potentially two threads at once * @throws QueueClosedException * @throws Exception */ private void drainUpQueue() throws QueueClosedException, Exception { //we do not synchronize here as we only have one up thread so we should never get an issue //synchronized(upLock){ Event tmp =null; while ((tmp = (Event)upMessageQueue.poll(0L)) != null){ if (tmp != null){ Message msg = decryptMessage(symDecodingCipher, (Message)tmp.getArg()); if (msg != null){ if (trace){ log.trace("passing up message from drain " + msg); } passUp(new Event(Event.MSG, msg)); }else{ log.warn("discarding message in queue up drain as cannot decode it"); } } } } /** * Sets the keys for the app. and drains the queues - the drains could * be called att he same time as the up/down messages calling in to * the class so we may have an extra call to the drain methods but this slight expense * is better than the alternative of waiting until the next message to * trigger the drains which may never happen. * * @param key * @param version * @throws Exception */ private void setKeys(SecretKey key, String version) throws Exception{ // put the previous key into the map // if the keys are already there then they will overwrite keyMap.put(getSymVersion(), getSymDecodingCipher()); setSecretKey(key); initSymCiphers(key.getAlgorithm(),key ); setSymVersion(version); // drain the up queue log.info("setting queue up to false in setKeys"); queue_up =false; drainUpQueue(); queue_down =false; drainDownQueue(); } /** * Does the actual work for decrypting - if version does not match current cipher * then tries to use previous cipher * @param cipher * @param msg * @return * @throws Exception */ private Message decryptMessage(Cipher cipher, Message msg) throws Exception { EncryptHeader hdr = (EncryptHeader)msg.getHeader(EncryptHeader.KEY); if (!hdr.getVersion().equals(getSymVersion())){ log.warn("attempting to use stored cipher as message does not uses current encryption version "); cipher = (Cipher)keyMap.get(hdr.getVersion()); if (cipher == null) { log.warn("Unable to find a matching cipher in previous key map"); return null; } else{ if(trace) log.trace("decrypting using previous cipher version "+ hdr.getVersion()); return _decrypt(cipher, msg, hdr.encrypt_entire_msg); } } else { // reset buffer with decrypted message return _decrypt(cipher, msg, hdr.encrypt_entire_msg); } } private Message _decrypt(Cipher cipher, Message msg, boolean decrypt_entire_msg) throws Exception { if(!decrypt_entire_msg) { msg.setBuffer(cipher.doFinal(msg.getBuffer())); return msg; } byte[] decrypted_msg=cipher.doFinal(msg.getBuffer()); Message ret=(Message)Util.streamableFromByteBuffer(Message.class, decrypted_msg); if(ret.getDest() == null) ret.setDest(msg.getDest()); if(ret.getSrc() == null) ret.setSrc(msg.getSrc()); return ret; } /** * @param secret * @param pubKey * @throws InvalidKeyException * @throws IllegalStateException * @throws IllegalBlockSizeException * @throws BadPaddingException */ private void sendSecretKey(SecretKey secret, PublicKey pubKey, Address source) throws InvalidKeyException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, NoSuchAlgorithmException { Message newMsg; if (log.isDebugEnabled()) log.debug("encoding shared key "); // create a cipher with peer's public key Cipher tmp = Cipher.getInstance(asymAlgorithm); tmp.init(Cipher.ENCRYPT_MODE, pubKey); //encrypt current secret key byte[] encryptedKey = tmp.doFinal(secret.getEncoded()); //SW logout encrypted bytes we are sending so we // can match the clients log to see if they match if (log.isDebugEnabled()) log.debug(" Generated encoded key which only client can decode:" + formatArray(encryptedKey)); newMsg = new Message(source, local_addr, encryptedKey); newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader( EncryptHeader.SECRETKEY, getSymVersion())); if (log.isDebugEnabled()) log.debug(" Sending version " + getSymVersion() + " encoded key to client"); passDown(new Event(Event.MSG, newMsg)); } /** * @param msg * @return */// private PublicKey handleKeyRequest(Message msg)// {// Message newMsg;// if (log.isDebugEnabled())// log.debug("Request for key recieved");//// //SW log the clients encoded public key so we can// // see if they match// if (log.isDebugEnabled())// log.debug("Got peer's encoded public key:"// + formatArray(msg.getBuffer()));//// PublicKey pubKey = generatePubKey(msg.getBuffer());//// //SW log the clients resulting public key so we can// // see if it is created correctly// if (log.isDebugEnabled())// log.debug("Generated requestors public key" + pubKey);//// /*// * SW why do we send this as the client does not use it ? - although we// * could make use to provide some authentication later on rahter than// * just encryption send server's publicKey// */// newMsg = new Message(msg.getSrc(), local_addr, Kpair.getPublic()// .getEncoded());//// //SW Log out our public key in encoded format so we// // can match with the client debugging to// // see if they match// if (log.isInfoEnabled())// log.debug("encoded key is "// + formatArray(Kpair.getPublic().getEncoded()));////// newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(// EncryptHeader.SERVER_PUBKEY, getSymVersion()));////// passDown(new Event(Event.MSG, newMsg));// return pubKey;// } /** * @return Message */ private Message sendKeyRequest() { // send client's public key to server and request // server's public key Message newMsg = new Message(keyServerAddr, local_addr, Kpair.getPublic() .getEncoded());
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?