📄 srpserver.java
字号:
/* SRPServer.java -- Copyright (C) 2003, 2006 Free Software Foundation, Inc.This file is a part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or (atyour option) any later version.GNU Classpath is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301USALinking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception statement from your version. */package gnu.javax.crypto.sasl.srp;import gnu.java.security.Registry;import gnu.java.security.util.PRNG;import gnu.java.security.util.Util;import gnu.javax.crypto.assembly.Direction;import gnu.javax.crypto.cipher.CipherFactory;import gnu.javax.crypto.cipher.IBlockCipher;import gnu.javax.crypto.key.IKeyAgreementParty;import gnu.javax.crypto.key.KeyAgreementFactory;import gnu.javax.crypto.key.KeyAgreementException;import gnu.javax.crypto.key.OutgoingMessage;import gnu.javax.crypto.key.IncomingMessage;import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;import gnu.javax.crypto.sasl.IllegalMechanismStateException;import gnu.javax.crypto.sasl.InputBuffer;import gnu.javax.crypto.sasl.IntegrityException;import gnu.javax.crypto.sasl.OutputBuffer;import gnu.javax.crypto.sasl.ServerMechanism;import java.io.IOException;import java.io.PrintWriter;import java.io.ByteArrayOutputStream;import java.io.UnsupportedEncodingException;import java.math.BigInteger;import java.util.Arrays;import java.util.HashMap;import java.util.StringTokenizer;import javax.security.sasl.AuthenticationException;import javax.security.sasl.SaslException;import javax.security.sasl.SaslServer;/** * <p>The SASL-SRP server-side mechanism.</p> * * @version $Revision: 1.2 $ */public class SRPServer extends ServerMechanism implements SaslServer{ // Debugging methods and variables // ------------------------------------------------------------------------- private static final String NAME = "SRPServer"; // private static final String ERROR = "ERROR"; private static final String WARN = " WARN"; private static final String INFO = " INFO"; private static final String TRACE = "DEBUG"; private static final boolean DEBUG = true; private static final int debuglevel = 3; private static final PrintWriter err = new PrintWriter(System.out, true); private static void debug(final String level, final Object obj) { err.println("[" + level + "] " + NAME + ": " + String.valueOf(obj)); } // Constants and variables // ------------------------------------------------------------------------- private String U = null; // client's username private BigInteger N, g, A, B; private byte[] s; // salt private byte[] cIV, sIV; // client+server IVs, when confidentiality is on private byte[] cn, sn; // client's and server's nonce private SRP srp; // SRP algorithm instance used by this server private byte[] sid; // session ID when re-used private int ttl = 360; // session time-to-live in seconds private byte[] cCB; // peer's channel binding' private String mandatory; // List of available options private String L = null; private String o; private String chosenIntegrityAlgorithm; private String chosenConfidentialityAlgorithm; private int rawSendSize = Registry.SASL_BUFFER_MAX_LIMIT; private byte[] K; // shared session key private boolean replayDetection = true; // whether Replay Detection is on private int inCounter = 0; // messages sequence numbers private int outCounter = 0; private IALG inMac, outMac; // if !null, use for integrity private CALG inCipher, outCipher; // if !null, use for confidentiality private IKeyAgreementParty serverHandler = KeyAgreementFactory.getPartyBInstance(Registry.SRP_SASL_KA); /** Our default source of randomness. */ private PRNG prng = null; // Constructor(s) // ------------------------------------------------------------------------- public SRPServer() { super(Registry.SASL_SRP_MECHANISM); } // Class methods // ------------------------------------------------------------------------- // Instance methods // ------------------------------------------------------------------------- // abstract methods implementation ----------------------------------------- protected void initMechanism() throws SaslException { // TODO: // we must have a means to map a given username to a preferred // SRP hash algorithm; otherwise we end up using _always_ SHA. // for the time being get it from the mechanism properties map // and apply it for all users. final String mda = (String) properties.get(SRPRegistry.SRP_HASH); srp = SRP.instance(mda == null ? SRPRegistry.SRP_DEFAULT_DIGEST_NAME : mda); } protected void resetMechanism() throws SaslException { s = null; A = B = null; K = null; inMac = outMac = null; inCipher = outCipher = null; sid = null; } // javax.security.sasl.SaslServer interface implementation ----------------- public byte[] evaluateResponse(final byte[] response) throws SaslException { switch (state) { case 0: if (response == null) { return null; } state++; return sendProtocolElements(response); case 1: if (!complete) { state++; return sendEvidence(response); } // else fall through default: throw new IllegalMechanismStateException("evaluateResponse()"); } } protected byte[] engineUnwrap(final byte[] incoming, final int offset, final int len) throws SaslException { // if (DEBUG && debuglevel > 8) debug(TRACE, "==> engineUnwrap()"); // // if (inMac == null && inCipher == null) { // throw new IllegalStateException("connection is not protected"); // } // // if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (before security): "+Util.dumpString(incoming, offset, len)); // // byte[] data = null; // try { // InputBuffer frameIn = InputBuffer.getInstance(incoming, offset, len); // data = frameIn.getEOS(); // if (inMac != null) { // byte[] received_mac = frameIn.getOS(); // if (DEBUG && debuglevel > 6) debug(TRACE, "Got C (received MAC): "+Util.dumpString(received_mac)); // inMac.update(data); // if (replayDetection) { // inCounter++; // if (DEBUG && debuglevel > 6) debug(TRACE, "inCounter="+String.valueOf(inCounter)); // inMac.update(new byte[] { // (byte)(inCounter >>> 24), // (byte)(inCounter >>> 16), // (byte)(inCounter >>> 8), // (byte) inCounter }); // } // final byte[] computed_mac = inMac.doFinal(); // if (DEBUG && debuglevel > 6) debug(TRACE, "Computed MAC: "+Util.dumpString(computed_mac)); // if (!Arrays.equals(received_mac, computed_mac)) // throw new IntegrityException("engineUnwrap()"); // } // if (inCipher != null) { // data = inCipher.doFinal(data); // } // } catch (IOException x) { // if (x instanceof SaslException) { // throw (SaslException) x; // } // throw new SaslException("engineUnwrap()", x); // } // // if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (after security): "+Util.dumpString(data)); // if (DEBUG && debuglevel > 8) debug(TRACE, "<== engineUnwrap()"); // return data; if (DEBUG && debuglevel > 8) debug(TRACE, "==> engineUnwrap()"); if (inMac == null && inCipher == null) { throw new IllegalStateException("connection is not protected"); } if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (before security): " + Util.dumpString(incoming, offset, len)); // at this point one, or both, of confidentiality and integrity protection // services are active. final byte[] result; try { if (inMac != null) { // integrity bytes are at the end of the stream final int macBytesCount = inMac.length(); final int payloadLength = len - macBytesCount; final byte[] received_mac = new byte[macBytesCount]; System.arraycopy(incoming, offset + payloadLength, received_mac, 0, macBytesCount); if (DEBUG && debuglevel > 6) debug(TRACE, "Got C (received MAC): " + Util.dumpString(received_mac)); inMac.update(incoming, offset, payloadLength); if (replayDetection) { inCounter++; if (DEBUG && debuglevel > 6) debug(TRACE, "inCounter=" + String.valueOf(inCounter)); inMac.update(new byte[] { (byte) (inCounter >>> 24), (byte) (inCounter >>> 16), (byte) (inCounter >>> 8), (byte) inCounter }); } final byte[] computed_mac = inMac.doFinal(); if (DEBUG && debuglevel > 6) debug(TRACE, "Computed MAC: " + Util.dumpString(computed_mac)); if (!Arrays.equals(received_mac, computed_mac)) { throw new IntegrityException("engineUnwrap()"); } // deal with the payload, which can be either plain or encrypted if (inCipher != null) { result = inCipher.doFinal(incoming, offset, payloadLength); } else { result = new byte[payloadLength]; System.arraycopy(incoming, offset, result, 0, result.length); } } else { // no integrity protection; just confidentiality // if (inCipher != null) { result = inCipher.doFinal(incoming, offset, len); // } else { // result = new byte[len]; // System.arraycopy(incoming, offset, result, 0, len); // } } } catch (IOException x) { if (x instanceof SaslException) { throw (SaslException) x; } throw new SaslException("engineUnwrap()", x); } if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (after security): " + Util.dumpString(result)); if (DEBUG && debuglevel > 8) debug(TRACE, "<== engineUnwrap()"); return result; } protected byte[] engineWrap(final byte[] outgoing, final int offset, final int len) throws SaslException { // if (DEBUG && debuglevel > 8) debug(TRACE, "==> engineWrap()"); // // if (outMac == null && outCipher == null) { // throw new IllegalStateException("connection is not protected"); // } // // byte[] data = new byte[len]; // System.arraycopy(outgoing, offset, data, 0, len); // // if (DEBUG && debuglevel > 6) debug(TRACE, "Outgoing buffer (before security) (hex): "+Util.dumpString(data)); // if (DEBUG && debuglevel > 6) debug(TRACE, "Outgoing buffer (before security) (str): \""+new String(data)+"\""); // // final byte[] result; // try { // OutputBuffer frameOut = new OutputBuffer(); // // Process the data // if (outCipher != null) { // data = outCipher.doFinal(data); // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding c (encrypted plaintext): "+Util.dumpString(data)); // } else { // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding p (plaintext): "+Util.dumpString(data)); // } // frameOut.setEOS(data); // if (outMac != null) { // outMac.update(data); // if (replayDetection) { // outCounter++; // if (DEBUG && debuglevel > 6) debug(TRACE, "outCounter="+String.valueOf(outCounter)); // outMac.update(new byte[] { // (byte)(outCounter >>> 24), // (byte)(outCounter >>> 16), // (byte)(outCounter >>> 8), // (byte) outCounter}); // } // byte[] C = outMac.doFinal();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -