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 + -
显示快捷键?