精华内容
下载资源
问答
  • NTLM加密和MD4加密

    千次阅读 2015-03-11 15:18:48
    搜了好半天,没一个有用的,不过好歹找到一个副件,测试后还是错误的,现自己写了一个NTML HASH(NT HASH)加密算法,希望大家不要在这方面在浪费时间了
    <pre name="code" class="java">package cn.kzfc.util;
    import java.security.MessageDigest;  
    import java.security.Security;  
    import org.bouncycastle.jce.provider.BouncyCastleProvider;  
    import org.bouncycastle.util.encoders.Hex; 
    public class MD4Coder {
    
    	 
    	      
    	      
    	    /** 
    	     * MD4的消息摘要算法实现 
    	     * @param data 要做消息摘要的数据 
    	     * @return byte[] 消息摘要 
    	     *  
    	     * */  
    	    public static byte[] encodeMD4(byte[] data) throws Exception{  
    	          
    	        Security.addProvider(new BouncyCastleProvider());  
    	        //初始化MessageDigest  
    	        MessageDigest md=MessageDigest.getInstance("MD4");  
    	          
    	        return md.digest(data);  
    	    }  
    	      
    	    /** 
    	     * MD4的消息摘要算法实现,转成16进制 
    	     * @param data 要做消息摘要的数据 
    	     * @return String 消息摘要 
    	     *  
    	     * */  
    	    public static String encodeMD4Hex(byte[] data) throws Exception{  
    	          
    	        byte[] b= encodeMD4(data);  
    	          
    	        return new String(Hex.encode(b));  
    	    }  
    	    /** 
    	     * @param args 
    	     * @throws Exception  
    	     */  
    	    public static void main(String[] args) throws Exception {  
    	        String str="123456";  
    	        System.out.println("原文:"+str);  
    	        byte[] data1=MD4Coder.encodeMD4(str.getBytes());  
    	        System.out.println("MD4的消息摘要算法值:"+data1.toString());  
    	          
    	        String data2=MD4Coder.encodeMD4Hex(str.getBytes());  
    	        System.out.println("MD4做十六进制编码处理的消息摘要算法值:"+data2);  
    	          
    	          
    	    }   
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    <pre name="code" class="html">/*
     *    This program is free software; you can redistribute it and/or modify
     *    it under the terms of the GNU General Public License as published by
     *    the Free Software Foundation; either version 2 of the License, or
     *    (at your option) any later version.
     *
     *    This program is distributed in the hope that it will be useful,
     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *    GNU General Public License for more details.
     *
     *    You should have received a copy of the GNU General Public License
     *    along with this program; if not, write to the Free Software
     *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
    
    /*
     *    NTLM.java
     *    Copyright (C) 2002 Luigi Dragone
     *
     */
    
    package cn.kzfc.util;
    
    import java.security.*;
    import java.security.spec.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;
     
    
    import java.io.*;
    
    /**
     * <p>
     * This class implements the Microsoft NTLM authentication protocol.
     * </p>
     * <p>
     * NTLM is a Microsoft proprietary network authentication protocol used in many
     * situations (e.g. by the Microsoft Proxy Server to authenticate a browser).
     * </p>
     * <p>
     * It requires a JCE compatible MD4 hash algorithm implementation and
     * a DES with no-padding ECB cipher to compute the requested value. <br>
     * An open source JCE compatible library is Cryptix JCE and it is available
     * <a href="http://www.cryptix.org/">here</a>. We are assuming that the JCE provider
     * is correctly installed and configured. Notice that the Sun JCE implementation
     * proviedes the DES cipher but doesn't provide the MD4 hashing.
     * </p>
     * To perform an authentication the following information are needed:
     * <ul>
     * <li>the host name (with its own domain);</li>
     * <li>the user name (with its own domain);</li>
     * <li>the user password.</li>
     * </ul>
     * Alternatively, the user password can be replaced with its Lan Manager and
     * NT hashed versions. On a Windows system these data can be collected in the
     * registry, otherwise they can be extracted from a SAMBA password file.<br>
     * Notice that the host and user domain could not be the same.
     * </p>
     * <p>
     * To start an NTLM authentication procedure (e.g. with a proxy server) build a
     * request message calling {@link #formatRequest(String, String) formatRequest}
     * and send it to the server.<br>
     * Once the challenge packet has been correctly received extract from it the nonce
     * with {@link #getNonce(byte[]) getNonce} function and use it to compute the
     * reply and build the response message with
     * {@link #formatResponse(String, String, String, byte[], byte[], byte[]) formatResponse}
     * method and send it back to the server.<br>
     * Repeat the previous steps until the server authenticates the client's identity
     * or a large number of retries has been made. The check of a successful authentication
     * is protocol specific (e.g. code 200 in HTTP), thus it is not performed by this component.
     * </p>
     * <p>
     * We want to access to the page <code>http://www.server.com/page.html</code>
     * through an NTLM proxy <code>proxy.domain.com</code> that accepts connection on
     * port 80.<br>
     * We access to proxy from host <code>HOSTDOMAIN\\HOST<code> with the user
     * <code>USERDOMAIN\\user</code> (password <code>"1234567890"</code>).<br>
     * As first step we open a socket connection to proxy server and set up the
     * required object. Notice that we use a keep-alive connection, because NTLM
     * authentication is connection based and the connection must be alive through the
     * whole process.<br>
     * <pre>
     *     Socket s = new Socket("proxy.domain.com", 80);
     *     s.setKeepAlive(true);
     *     InputStream is = s.getInputStream();
     *     OutputStream os = s.getOutputStream();
     *     BufferedReader r = new BufferedReader(new InputStreamReader(is));
     *     BufferedWriter w = new BufferedWriter(new OutputStreamWriter(os));
     *
     *     String host = "HOST";
     *     String hostDomain = "HOSTDOMAIN";
     *     String user = "user";
     *     String userDomain = "USERDOMAIN";
     *     String password = "1234567890";
     * </pre>
     * Then, we format a request message and send it in a HTTP compliant GET message.<br>
     * <pre>
     *     byte[] fstMsg = NTLM.formatRequest(host, hostDomain);
     *     byte[] fstMsg64 = Codecs.base64Encode(fstMsg);
     *     System.out.println("NTLM Request Packet: " + new String(fstMsg64));
     *
     *     w.write("GET http://www.server.com/page.html HTTP/1.0\n");
     *     w.write("Host: www.server.com\n");
     *     w.write("Proxy-Connection: Keep-Alive\n");
     *     w.write("Proxy-Authorization: NTLM " + new String(fstMsg64) + "\n\n");
     *     w.flush();
     *     System.out.println("First Message Sent");
     * </pre>
     * We wait for the server response and we parse it to extract the nonce.<br>
     * <pre>
     *     String resp = "";
     *     int contentLength = 0;
     *     while((line = r.readLine()) != null)
     *       if(line.length() == 0)
     *         break;
     *       if(line.startsWith("Content-Length"))
     *         contentLength = Integer.parseInt(line.substring(line.indexOf(":") + 1).trim());
     *       else if(line.startsWith("Proxy-Authenticate"))
     *         resp = line.substring(line.indexOf(":") + 1).trim();
     *     r.skip(contentLength);
     *     System.out.println("Second Message Received");
     *     System.out.println("Content Length: " + contentLength);
     *     System.out.println("Proxy-Authenticate: " + resp);
     *     resp = resp.substring(resp.indexOf(" ")).trim();
     *     System.out.println("NTLM Chellange Packet: " + resp);
     *     resp = Codecs.base64Decode(resp);
     *     byte[] sndMsg = resp.getBytes();
     *     byte[] nonce = NTLM.getNonce(sndMsg);
     * </pre>
     * With the nonce collected in the previous step we create a response message.<br>
     * <pre>
     *     byte[] trdMsg = NTLM.formatResponse(host, user, userDomain,
     *     	NTLM.computeLMPassword(password), NTLM.computeNTPassword(password),
     *     	nonce);
     *     System.out.println(trdMsg.length);
     *     byte[] trdMsg64 = Codecs.base64Encode(trdMsg);
     *     System.out.println("NTLM Response Packet: " + new String(trdMsg64));
     * </pre>
     * We sent the message to the server.<br>
     * <pre>
     *     w.write("GET http://www.server.com/page.html HTTP/1.0\n");
     *     w.write("Proxy-Connection: Keep-Alive\n");
     *     w.write("Host: www.server.com\n");
     *     w.write("Proxy-Authorization: NTLM " + new String(trdMsg64) + "\n\n");
     *     w.flush();
     *     System.out.println("Third Message Sent");
     * </pre>
     * Finally we wait the server reply.<br>
     * <pre>
     *     System.out.println("Server response: " + r.readLine());
     * </pre>
     * If the reply is like <code>"HTTP/1.0 200 OK"</code> it has worked fine, else
     * the server response is containing a new nonce.
     * </p>
     * <p>
     * Notice that despite the computing of hashed passwords and of nonce response is
     * exactly the same of the SMB authentication protocol, the message format is slightly
     * different. <br>
     * Therefore, the methods {@link #computeLMPassword(String) computeLMPassword},
     * {@link #computeNTPassword(String) computeNTPassword} and
     * {@link #computeNTLMResponse(byte[], byte[], byte[], byte[], byte[]) computeNTLMResponse}
     * can be used to perform a SMB authentication too.
     * </p>
     * <p>
     * This implementation is based on:
     * <ul>
     * <li>the reverse engineering of the NTLM protocol made by Ronald Tschalär
     * and available <a href="http://www.innovation.ch/java/ntlm.html">here</a>;</li>
     * <li>the documentation about NTLM provided with <a href="http://www.atstake.com/research/lc3/">
     * L0phtCrack 1.5</a>;</li>
     * <li>the "Handbook of Applied Cryptography", freely available
     * <a href="http://www.cacr.math.uwaterloo.ca/hac/">here</a>;</li>
     * <li>the C source code of NTLM library in the <a href="http://www.samba.org/">
     * SAMBA Project</a>.</li>
     * </ul>
     * Nevertheless, because there isn't any official protocol specification publicly
     * available there is any warranty that code works correctly and that it is
     * conforming to Microsoft NTLM protocol.
     * </p>
     * <p>
     * For implementation reasons only the public members perform argument consistency
     * checks. The public members also catch and hide every exceptions that can be
     * throwed (even though interfaces specify otherwise).
     * </p>
     *
     * @author Luigi Dragone (<a href="mailto:luigi@luigidragone.com">luigi@luigidragone.com</a>)
     *
     * @version 1.0.1
     *
     * @see <a href="http://www.innovation.ch/java/ntlm.html">NTLM Authentication Scheme for HTTP</a>
     * @see <a href="ftp://ftp.samba.org/pub/samba/docs/textdocs/ENCRYPTION.txt">LanMan and NT Password Encryption in Samba 2.x</a>
     * @see <a href="http://www.cacr.math.uwaterloo.ca/hac/">"Handbook of Applied Cryptography"</a>
     * @see <a href="http://java.sun.com/products/jce/">JCE</a>
     * @see <a href="http://www.cryptix.org/">Cryptix</a>
     */
    public class NTLM {
      protected NTLM() {}
      /**
       * The magic number used to compute the Lan Manager hashed password.
       */
      protected static final byte[] MAGIC = new byte[] {0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
      /**
       * <p>
       * Converts an unsigned byte to an unsigned integer.
       * </p>
       * <p>
       * Notice that Java bytes are always signed, but the cryptographic algorithms
       * rely on unsigned ones, that can be simulated in this way.<br>
       * A bit mask is employed to prevent that the signum bit is extended to MSBs.
       * </p>
       */
      protected static int unsignedByteToInt(byte b) {
        return (int)b & 0xFF;
      }
      protected static byte getLoByte(char c) {
        return (byte)c;
      }
      protected static byte getHiByte(char c) {
        return (byte)((c >>> 8) & 0xFF);
      }
      protected static short swapBytes(short s) {
        return (short)(((s << 8) & 0xFF00) | ((s >>> 8) & 0x00FF));
      }
      /**
       * <p>
       * Computes an odd DES key from 56 bits represented as a 7-bytes array.
       * </p>
       * <p>
       * Keeps elements from index <code>offset</code> to index <code>offset + 7</code> of
       * supplied array.
       * </p>
       *
       * @param keyData a byte array containing the 56 bits used to compute the DES key
       * @param offset the offset of the first element of the 56-bits key data
       *
       * @return the odd DES key generated
       *
       * @exception InvalidKeyException
       * @exception NoSuchAlgorithmException
       * @exception InvalidKeySpecException
       */
      protected static Key computeDESKey(byte[] keyData, int offset) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] desKeyData = new byte[8];
        int[] k = new int[7];
    
        for(int i = 0; i < 7; i++)
          k[i] = unsignedByteToInt(keyData[offset + i]);
    
        desKeyData[0] = (byte)(k[0] >>> 1);
        desKeyData[1] = (byte)(((k[0] & 0x01) << 6) | (k[1] >>> 2));
        desKeyData[2] = (byte)(((k[1] & 0x03) << 5) | (k[2] >>> 3));
        desKeyData[3] = (byte)(((k[2] & 0x07) << 4) | (k[3] >>> 4));
        desKeyData[4] = (byte)(((k[3] & 0x0F) << 3) | (k[4] >>> 5));
        desKeyData[5] = (byte)(((k[4] & 0x1F) << 2) | (k[5] >>> 6));
        desKeyData[6] = (byte)(((k[5] & 0x3F) << 1) | (k[6] >>> 7));
        desKeyData[7] = (byte)(k[6] & 0x7F);
    
        for(int i=0; i<8; i++)
          desKeyData[i] = (byte)(unsignedByteToInt(desKeyData[i]) << 1);
    
        KeySpec desKeySpec = new DESKeySpec(desKeyData);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        return secretKey;
      }
      /**
       * Encrypts the 8-bytes plain text three times with the 3 56-bits DES keys and
       * puts the result in a 24-bytes array.
       *
       * @param keys a 21-bytes array containing 3 56-bits DES keys
       * @param plaintext a 8-bytes array to be encrypted
       *
       * @return a 24-bytes array containing the plaintext DES encrypted with the supplied keys
       *
       * @exception InvalidKeyException
       * @exception NoSuchAlgorithmException
       * @exception javax.crypto.NoSuchPaddingException
       * @exception InvalidKeySpecException
       * @exception BadPaddingException
       * @exception IllegalBlockSizeException
       * @exception ShortBufferException
       */
      protected static byte[] encrypt(byte[] keys, byte[] plaintext) throws InvalidKeyException, NoSuchAlgorithmException, javax.crypto.NoSuchPaddingException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException, ShortBufferException {
        byte[] ciphertext = new byte[24];
        Cipher c = Cipher.getInstance("DES/ECB/NoPadding");
        Key k = computeDESKey(keys, 0);
        c.init(Cipher.ENCRYPT_MODE, k);
        c.doFinal(plaintext, 0, 8, ciphertext, 0);
        k = computeDESKey(keys, 7);
        c.init(Cipher.ENCRYPT_MODE, k);
        c.doFinal(plaintext, 0, 8, ciphertext, 8);
        k = computeDESKey(keys, 14);
        c.init(Cipher.ENCRYPT_MODE, k);
        c.doFinal(plaintext, 0, 8, ciphertext, 16);
        return ciphertext;
      }
    
      /**
       * Computes the Lan Manager hashed version of a password.
       *
       * @param password the user password
       *
       * @return the Lan Manager hashed version of the password in a 16-bytes array
       *
       * @exception IllegalArgumentException if the supplied password is null
       * @exception javax.crypto.NoSuchPaddingException if there isn't any suitable padding method
       * @exception NoSuchAlgorithmException if there isn't any suitable cipher algorithm
       */
      public static byte[] computeLMPassword(String password) throws IllegalArgumentException, NoSuchPaddingException, NoSuchAlgorithmException {
        if(password == null)
          throw new IllegalArgumentException("password : null value not allowed");
        try {
          //Gets the first 14-bytes of the ASCII upper cased password
          int len = password.length();
          if(len > 14)
            len = 14;
          Cipher c = Cipher.getInstance("DES/ECB/NoPadding");
    
          byte[] lm_pw = new byte[14];
          byte[] bytes = password.toUpperCase().getBytes();
          int i;
          for(i = 0; i < len; i++)
            lm_pw[i] = bytes[i];
          for(; i < 14; i++)
            lm_pw[i] = 0;
    
          byte[] lm_hpw = new byte[16];
          //Builds a first DES key with its first 7 bytes
          Key k = computeDESKey(lm_pw, 0);
          c.init(Cipher.ENCRYPT_MODE, k);
          //Hashes the MAGIC number with this key into the first 8 bytes of the result
          c.doFinal(MAGIC, 0, 8, lm_hpw, 0);
    
          //Repeats the work with the last 7 bytes to gets the last 8 bytes of the result
          k = computeDESKey(lm_pw, 7);
          c.init(Cipher.ENCRYPT_MODE, k);
          c.doFinal(MAGIC, 0, 8, lm_hpw, 8);
    
          return lm_hpw;
        } catch(InvalidKeySpecException ex) {
          return null;
        } catch(InvalidKeyException ex) {
          return null;
        } catch(BadPaddingException ex) {
          return null;
        } catch(IllegalBlockSizeException ex) {
          return null;
        } catch(ShortBufferException ex) {
          return null;
        }
      }
    
      /**
       * Computes the NT hashed version of a password.
       *
       * @param password the user password
       *
       * @return the NT hashed version of the password in a 16-bytes array
       *
       * @exception IllegalArgumentException if the supplied password is null
       * @exception NoSuchAlgorithmException if there isn't any suitable cipher algorithm
       */
      public static String computeNTPassword(String password) {
        if(password == null)return null;
        //Gets the first 14-bytes of the UNICODE password
        int len = password.length();
    //    if(len > 14)
    //      len = 14;
        byte[] nt_pw = new byte[2 * len];
        for(int i = 0; i < len; i++) {
            char ch = password.charAt(i);
            nt_pw[2 * i] = getLoByte(ch);
            nt_pw[2 * i + 1] = getHiByte(ch);
        }
        
        try {
    		return MD4Coder.encodeMD4Hex(nt_pw);
    	} catch (Exception e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}  
        return null;
        //Return its MD4 digest as the hashed version
    //    MessageDigest md = MessageDigest.getInstance("MD4");
    //    return md.digest(nt_pw);
        
        
    //    Security.addProvider(new BouncyCastleProvider());  
    //    //初始化MessageDigest  
    //    MessageDigest md=MessageDigest.getInstance("MD4");  
    //      
    //    return md.digest(nt_pw);  
      }
      /**
       * <p>
       * Computes the NTLM response to the nonce based on the supplied hashed passwords.
       * </p>
       * <p>
       * If the hashed password are not available they can be computed from the cleartext password
       * by the means of {@link #computeLMPassword(String) computeLMPassword} and
       * {@link #computeNTPassword(String) computeNTPassword} methods.
       * </p>
       *
       * @param lmPassword a 16-bytes array containing the Lan Manager hashed password
       * @param ntPassword a 16-bytes array containing the Lan Manager hashed password
       * @param nonce a 8-bytes array representing the server's nonce
       * @param lmResponse a 24-bytes array that will contain the Lan Manager response after the method invocation
       * @param ntResponse a 24-bytes array that will contain the NT response after the method invocation
       *
       * @exception IllegalArgumentException if a parameter has an illegal size
       * @exception javax.crypto.NoSuchPaddingException if there isn't any suitable padding method
       * @exception NoSuchAlgorithmException if there isn't any suitable cipher algorithm
       */
      public static void computeNTLMResponse(byte[] lmPassword, byte[] ntPassword, byte[] nonce, byte[] lmResponse, byte[] ntResponse) throws IllegalArgumentException, NoSuchPaddingException, NoSuchAlgorithmException {
        if(lmPassword.length != 16)
          throw new IllegalArgumentException("lmPassword : illegal size");
        if(ntPassword.length != 16)
          throw new IllegalArgumentException("ntPassword : illegal size");
        if(nonce.length != 8)
          throw new IllegalArgumentException("nonce : illegal size");
        if(lmResponse.length != 24)
          throw new IllegalArgumentException("lmResponse : illegal size");
        if(ntResponse.length != 24)
          throw new IllegalArgumentException("ntResponse : illegal size");
        try {
          //Puts the hashed passwords into 21-bytes arrays with trailing 0s
          byte[] lmHPw = new byte[21];
          byte[] ntHPw = new byte[21];
          System.arraycopy(lmPassword, 0, lmHPw, 0, 16);
          System.arraycopy(ntPassword, 0, ntHPw, 0, 16);
          for(int i = 16; i < 21; i++) {
            lmHPw[i] = 0;
            ntHPw[i] = 0;
          }
          //Encrypts the nonce with the padded hashed passwords to compute the responses
          System.arraycopy(encrypt(lmHPw, nonce), 0, lmResponse, 0, 24);
          System.arraycopy(encrypt(ntHPw, nonce), 0, ntResponse, 0, 24);
        } catch(ShortBufferException ex) {
        } catch(IllegalBlockSizeException ex) {
        } catch(BadPaddingException ex) {
        } catch(InvalidKeySpecException ex) {
        } catch(InvalidKeyException ex) {
        }
      }
    
      /**
       * <p>
       * Builds a request message for the host of the specified domain that can be send
       * to the server to start the NTLM protocol.
       * </p>
       * <p>
       * The returned message should be encoded according to protocol specific rules
       * (e.g. base 64 encoding).<br>
       * The message format is discussed <a href="http://www.innovation.ch/java/ntlm.html">here</a>.
       * </p>
       *
       * @param host the name of the host that is authenticating
       * @param hostDomain the name of the domain to which the host belongs
       *
       * @return the request message to send to server to open an authentication procedure
       *
       * @exception IOException if an error occurs during the message formatting
       *
       * @see <a href="http://www.innovation.ch/java/ntlm.html">NTLM Authentication Scheme for HTTP</a>
       *
       */
      public static byte[] formatRequest(String host, String hostDomain) throws IOException {
        hostDomain = hostDomain.toUpperCase();
        host = host.toUpperCase();
        short domainLen = (short)hostDomain.length();
        short hostLen = (short)host.length();
        short hostOff = 0x20;
        short domainOff = (short)(hostOff + hostLen);
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
        DataOutputStream dataOut = new DataOutputStream(os);
        dataOut.writeBytes("NTLMSSP\0");
        dataOut.writeByte(0x01);
        dataOut.writeByte(0x00);
        dataOut.writeByte(0x00);
        dataOut.writeByte(0x00);
        dataOut.writeShort(swapBytes((short)0xb203));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(domainLen));
        dataOut.writeShort(swapBytes(domainLen));
        dataOut.writeShort(swapBytes(domainOff));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(hostLen));
        dataOut.writeShort(swapBytes(hostLen));
        dataOut.writeShort(swapBytes(hostOff));
        dataOut.writeShort(0x0000);
        dataOut.write(host.getBytes());
        dataOut.write(hostDomain.getBytes());
        dataOut.flush();
        return os.toByteArray();
      }
    
      /**
       * <p>
       * Extracts from the server challenge response the nonce required to perform
       * the authentication.
       * </p>
       * <p>
       * The received message should be decoded according to protocol specific rules
       * (e.g. base 64 encoding).<br>
       * The message format is discussed <a href="http://www.innovation.ch/java/ntlm.html">here</a>.
       * </p>
       *
       * @param msg a byte array containing the server challenge message
       *
       * @exception IllegalArgumentException if a parameter has an illegal size
       *
       * @see <a href="http://www.innovation.ch/java/ntlm.html">NTLM Authentication Scheme for HTTP</a>
       */
      public static byte[] getNonce(byte[] msg) throws IllegalArgumentException {
        if(msg.length < 32)
          throw new IllegalArgumentException("msg : illegal size");
        byte[] nonce = new byte[8];
        System.arraycopy(msg, 24, nonce, 0, 8);
        return nonce;
      }
    
      /**
       * <p>
       * Builds the nonce response message.
       * </p>
       * <p>It requires the Lan Manager and NT hashed
       * version of user password, that can be computed from the cleartext version by
       * {@link #computeNTPassword(String) computeNTPassword} and
       * {@link #computeNTLMResponse(byte[], byte[], byte[], byte[], byte[]) computeNTLMResponse},
       * and the nonce obtained from the server by {@link #getNonce(byte[]) getNonce}.<br>
       * The returned message should be encoded according to protocol specific rules
       * (e.g. base 64 encoding).<br>
       * The message format is discussed <a href="http://www.innovation.ch/java/ntlm.html">here</a>.
       * </p>
       *
       * @param host the name of the host that is authenticating
       * @param user the name of the user
       * @param userDomain the name of the domain to which the user belongs
       * @param lmPassword a 16-bytes array containing the Lan Manager hashed password
       * @param ntPassword a 16-bytes array containing the NT hashed password
       * @param nonce a 8-byte array containing the nonce sent by server to reply to the request message
       *
       * @return the challenge response message to send to server to complete the authentication procedure
       *
       * @exception IOException if an error occurs during the message formatting
       * @exception IllegalArgumentException if a parameter has an illegal size
       * @exception javax.crypto.NoSuchPaddingException if there isn't any suitable padding method
       * @exception NoSuchAlgorithmException if there isn't any suitable cipher algorithm
       *
       * @see <a href="http://www.innovation.ch/java/ntlm.html">NTLM Authentication Scheme for HTTP</a>
       */
      public static byte[] formatResponse(String host, String user, String userDomain, byte[] lmPassword, byte[] ntPassword, byte[] nonce) throws IllegalArgumentException, IOException, NoSuchAlgorithmException, NoSuchPaddingException {
        if(host == null)
          throw new IllegalArgumentException("host : null value not allowed");
        if(user == null)
          throw new IllegalArgumentException("user : null value not allowed");
        if(userDomain == null)
          throw new IllegalArgumentException("userDomain : null value not allowed");
        if(lmPassword == null)
          throw new IllegalArgumentException("lmPassword : null value not allowed");
        if(ntPassword == null)
          throw new IllegalArgumentException("ntPassword : null value not allowed");
        if(nonce == null)
          throw new IllegalArgumentException("nonce : null value not allowed");
        if(lmPassword.length != 16)
          throw new IllegalArgumentException("lmPassword : illegal size");
        if(ntPassword.length != 16)
          throw new IllegalArgumentException("ntPassword : illegal size");
        if(nonce.length != 8)
          throw new IllegalArgumentException("nonce : illegal size");
    
        byte[] lmResponse = new byte[24];
        byte[] ntResponse = new byte[24];
    
        computeNTLMResponse(lmPassword, ntPassword, nonce, lmResponse, ntResponse);
    
        userDomain = userDomain.toUpperCase();
        host = host.toUpperCase();
        short lmRespLen = (short)0x18;
        short ntRespLen = (short)0x18;
        short domainLen = (short)(2 * userDomain.length());
        short hostLen = (short)(2 * host.length());
        short userLen = (short)(2 * user.length());
        short domainOff = (short)0x40;
        short userOff = (short)(domainOff + domainLen);
        short hostOff = (short)(userOff + userLen);
        short lmRespOff = (short)(hostOff + hostLen);
        short ntRespOff = (short)(lmRespOff + lmRespLen);
        short msgLen = (short)(ntRespOff + ntRespLen);
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
        DataOutputStream dataOut = new DataOutputStream(os);
        dataOut.writeBytes("NTLMSSP\0");
        dataOut.writeByte(0x03);
        dataOut.writeByte(0x00);
        dataOut.writeByte(0x00);
        dataOut.writeByte(0x00);
        dataOut.writeShort(swapBytes(lmRespLen));
        dataOut.writeShort(swapBytes(lmRespLen));
        dataOut.writeShort(swapBytes(lmRespOff));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(ntRespLen));
        dataOut.writeShort(swapBytes(ntRespLen));
        dataOut.writeShort(swapBytes(ntRespOff));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(domainLen));
        dataOut.writeShort(swapBytes(domainLen));
        dataOut.writeShort(swapBytes(domainOff));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(userLen));
        dataOut.writeShort(swapBytes(userLen));
        dataOut.writeShort(swapBytes(userOff));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(swapBytes(hostLen));
        dataOut.writeShort(swapBytes(hostLen));
        dataOut.writeShort(swapBytes(hostOff));
        dataOut.writeShort(0x0000);
        dataOut.writeInt(0x00000000);
        dataOut.writeShort(swapBytes(msgLen));
        dataOut.writeShort(0x0000);
        dataOut.writeShort(0x0000);  //    dataOut.writeShort(swapBytes((short)0x8201));
        dataOut.writeShort(0x0000);
    
        for(int i = 0; i < userDomain.length(); i++)
          dataOut.writeShort(swapBytes((short)userDomain.charAt(i)));
        for(int i = 0; i < user.length(); i++)
          dataOut.writeShort(swapBytes((short)user.charAt(i)));
        for(int i = 0; i < host.length(); i++)
          dataOut.writeShort(swapBytes((short)host.charAt(i)));
        dataOut.write(lmResponse);
        dataOut.write(ntResponse);
        dataOut.flush();
        return os.toByteArray();
      }
      
      
      public static void main(String[] args) {
    	  //wangli@1q2w3e4r
    	System.out.println(NTLM.computeNTPassword("wangli@1q2w3e4r")) ;
    	
    	System.out.println(NTLM.computeNTPassword("123456")) ;
    }
    }
    


     
    
    
    
    
    


    展开全文
  • Windows NT/NTLM 加密

    2016-05-27 10:26:00
    Hash,一般翻译为 ...NTLM加密并存储了 NTLM的 hash),这时候使用 ophcrack的 NTLM表查找的就是这个 NTLM的 hash了,而不是 LM的 hash。   转载于:https://www.cnblogs.com/swyft/p/5533699.html

    Hash,一般翻译为“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

     

           一、MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢?这里简单说一下:

        (1)MD4

        MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD是 Message Digest的缩写。它适用在32位字长的处理器上用高速软件实现,它是基于 32 位操作数的位操作来实现的。

        (2) MD5

        MD5(RFC 1321)是 Rivest于1991年对MD4的改进版本。它仍以512位分组来输入,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好

        (3)SHA1 及其他

        SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

     

     

           二、Windows系统下的hash密码格式

           Windows系统下的hash密码格式为:用户名称:RID:LM-HASH值:NT-HASH值,例如:Administrator:500:C8825DB10F2590EAAAD3B435B51404EE:683020925C5D8569C23AA724774CE6CC:::表示

      用户名称为:Administrator

        RID为:500

        LM-HASH值为:C8825DB10F2590EAAAD3B435B51404EE
        NT-HASH值为:683020925C5D8569C23AA724774CE6CC

        (1)Windows下LM Hash值生成原理

        假设明文口令是“Welcome”,首先全部转换成大写“WELCOME”,再做将口令字符串大写转后后的字符串变换成二进制串: “WELCOME” -> 57454C434F4D4500000000000000

           技巧:可以将明文口令复制到UltraEdit编辑器中使用二进制方式查看即可获取口令的二进制串。

           说明:如果明文口令经过大写变换后的二进制字符串不足14字节,则需要在其后添加0x00补足14字节。然后切割成两组7字节的数据,分别经str_to_key()函数处理得到两组8字节数据:

        57454C434F4D45 -str_to_key()-> 56A25288347A348A
        00000000000000 -str_to_key()-> 0000000000000000

        这两组8字节数据将做为DESKEY对魔术字符串“KGS!@#$%”进行标准DES加密

        "KGS!@#$%" -> 4B47532140232425

        56A25288347A348A -对4B47532140232425进行标准DES加密-> C23413A8A1E7665F

        0000000000000000 -对4B47532140232425进行标准DES加密-> AAD3B435B51404EE

          将加密后的这两组数据简单拼接,就得到了最后的LM Hash

        LM Hash: C23413A8A1E7665FAAD3B435B51404EE

        (2) Windows下NTLM Hash生成原理

           从IBM设计的LM Hash算法存在几个弱点,微软在保持向后兼容性的同时提出了自己的挑战响应机制,NTLM Hash应运而生。假设明文口令是“123456”,首先转换成Unicode字符串,与LM Hash算法不同,这次不需要添加0x00补足14字节

          "123456" -> 310032003300340035003600

            从ASCII串转换成Unicode串时,使用little-endian序,微软在设计整个SMB协议时就没考虑过big-endian序,ntoh*()、hton*()函数不宜用在SMB报文解码中。0x80之前的标准ASCII码转换成Unicode码,就是简单地从0x??变成0x00??。此类标准ASCII串按little-endian序转换成Unicode串,就是简单地在原有每个字节之后添加0x00。对所获取的Unicode串进行标准MD4单向哈希,无论数据源有多少字节,MD4固定产生128-bit的哈希值,

            16字节310032003300340035003600 -进行标准MD4单向哈希-> 32ED87BDB5FDC5E9CBA88547376818D4

            就得到了最后的NTLM Hash

            NTLM Hash: 32ED87BDB5FDC5E9CBA88547376818D4

            与LM Hash算法相比,明文口令大小写敏感,无法根据NTLM Hash判断原始明文口令是否小于8字节,摆脱了魔术字符串"KGS!@#$%"。MD4是真正的单向哈希函数,穷举作为数据源出现的明文,难度较大。

     

          三、总结一下:

          两种加密算法分别是LanManager(LM)和NTLM,LM只能存储小于等于14个字符的密码hash,如果密码大于14个,windows就自动使用NTLM对其进行加密了,(这个在LC5里有两种破解方式,所以破解不出来的时候可以换种思路,基本是NTLM的)一般情况下使用PwDump或其他一些hash导出工具(如Cain)导出的hash都有对应的LM和NTLM值,也就是说这个密码位数<=14,如果大于14位那么就只有对应的NTLM hash可用了,这时LM也会有值,但对我们来说没用,不能靠他来查LM彩虹表。 
          操作系统:对于XP、win2k和win2k3来说,系统默认使用LM进行加密(也可人为设置成NTLM),之后的win2008、win7和Vista禁用了LM,默认使用NTLM,所以不要拿着LM生成的rainbow table去找NTLM的hash值,但是反过来却可以,因为使用LM方式的加密往往会存在一个对应的NTLM hash(如果密码位数<=14的话,系统同时对这个密码使用NTLM加密并存储了NTLM的hash),这时候使用ophcrack的NTLM表查找的就是这个NTLM的hash了,而不是LM的hash。 

    转载于:https://www.cnblogs.com/swyft/p/5533699.html

    展开全文
  • 如题,请教NTLM加密算法NTLM 密码加密算法NTLM 密码加密算法NTLM 密码加密算法
  • Windows LM/NTLM HASH加密及获取工具

    万次阅读 2013-06-22 16:07:20
    ,LM只能存储小于等于14个字符的密码hash,如果密码大于14个,windows就自动使用NTLM对其进行加密了, ( 这个在 LC5 里有两种破解方式,所以破解不出来的时候可以换种思路,基本是 NTLM 的 ) 一般情况下使用 PwDump ...
    Hash,一般翻译为 散列 ,也有直接音译为 哈希 的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。


           MD5  SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢?这里简单说一下:

        (1)MD4

        MD4(RFC 1320) MIT  Ronald L. Rivest  1990 年设计的,MD Message Digest的缩写。它适用在32位字长的处理器上用高速软件实现,它是基于 32 位操作数的位操作来实现的。

        (2) MD5

        MD5(RFC 1321) Rivest1991年对MD4的改进版本。它仍以512位分组来输入,其输出是432位字的级联,与 MD4 相同。MD5MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好

        (3)SHA1 及其他

        SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

     

    Windows系统下的hash密码格式

           Windows系统下的hash密码格式为:用户名称:RID:LM-HASH:NT-HASH值,例如:Administrator:500:C8825DB10F2590EAAAD3B435B51404EE:683020925C5D8569C23AA724774CE6CC:::表示

      用户名称为:Administrator

        RID为:500

        LM-HASH值为:C8825DB10F2590EAAAD3B435B51404EE
        NT-HASH值为:683020925C5D8569C23AA724774CE6CC

        (1)Windows下LM Hash值生成原理

        假设明文口令是“Welcome”,首先全部转换成大写“WELCOME”,再做将口令字符串大写转后后的字符串变换成二进制串: “WELCOME” -> 57454C434F4D4500000000000000

           技巧:可以将明文口令复制到UltraEdit编辑器中使用二进制方式查看即可获取口令的二进制串。

           说明:如果明文口令经过大写变换后的二进制字符串不足14字节,则需要在其后添加0x00补足14字节。然后切割成两组7字节的数据,分别经str_to_key()函数处理得到两组8字节数据:

        57454C434F4D45 -str_to_key()-> 56A25288347A348A
        00000000000000 -str_to_key()-> 0000000000000000

        这两组8字节数据将做为DESKEY对魔术字符串“KGS!@#$%”进行标准DES加密

        "KGS!@#$%" -> 4B47532140232425

        56A25288347A348A -4B47532140232425进行标准DES加密-> C23413A8A1E7665F

        0000000000000000 -4B47532140232425进行标准DES加密-> AAD3B435B51404EE

          将加密后的这两组数据简单拼接,就得到了最后的LM Hash

        LM Hash: C23413A8A1E7665FAAD3B435B51404EE

        (2) Windows下NTLM Hash生成原理

           IBM设计的LM Hash算法存在几个弱点,微软在保持向后兼容性的同时提出了自己的挑战响应机制,NTLM Hash应运而生。假设明文口令是“123456”,首先转换成Unicode字符串,与LM Hash算法不同,这次不需要添加0x00补足14字节

          "123456" -> 310032003300340035003600

            ASCII串转换成Unicode串时,使用little-endian序,微软在设计整个SMB协议时就没考虑过big-endian序,ntoh*()hton*()函数不宜用在SMB报文解码中。0x80之前的标准ASCII码转换成Unicode码,就是简单地从0x??变成0x00??。此类标准ASCII串按little-endian序转换成Unicode串,就是简单地在原有每个字节之后添加0x00。对所获取的Unicode串进行标准MD4单向哈希,无论数据源有多少字节,MD4固定产生128-bit的哈希值,

            16字节310032003300340035003600 -进行标准MD4单向哈希-> 32ED87BDB5FDC5E9CBA88547376818D4

            就得到了最后的NTLM Hash

            NTLM Hash: 32ED87BDB5FDC5E9CBA88547376818D4

            LM Hash算法相比,明文口令大小写敏感,无法根据NTLM Hash判断原始明文口令是否小于8字节,摆脱了魔术字符串"KGS!@#$%"MD4是真正的单向哈希函数,穷举作为数据源出现的明文,难度较大。


    获取Windows LM/NTLM HASH值的工具:

               1.SAMInside:它能从SAM注册文件中提取用户名以及密码(SAM 是Windows系统中存放系统用户及密码的一种文件,用Syskey(系统密钥)加密保护。)

     2.PwDump

     3.ophcrack(附带pwdump)

     4.GetHashes(适用于xp)


    总结一下:

          两种加密算法分别是LanManager(LM)NTLM,LM只能存储小于等于14个字符的密码hash,如果密码大于14个,windows就自动使用NTLM对其进行加密了,(这个在LC5里有两种破解方式,所以破解不出来的时候可以换种思路,基本是NTLM)一般情况下使用PwDump或其他一些hash导出工具(Cain)导出的hash都有对应的LMNTLM值,也就是说这个密码位数<=14,这时LM也会有值,如果大于14位那么就只有对应的NTLM hash可用了,在LM-Password中会以全0显示,在老版本中以AA3D开头显示的也表示密码位数超过14位,对我们来说没用,不能靠他来查LM彩虹表。 (最近遇到新的情况LM:aad3b435b51404eeaad3b435b51404ee不一定是空密码或者大于14位密码,也可以是人为的设置,这时只能用NTLM了)
          操作系统:对于XPwin2kwin2k3来说,系统默认使用LM进行加密(也可人为设置成NTLM),之后的win2008win7Vista禁用了LM,默认使用NTLM,所以不要拿着LM生成的rainbow table去找NTLMhash,但是反过来却可以,因为使用LM方式的加密往往会存在一个对应的NTLM hash(如果密码位数<=14的话,系统同时对这个密码使用NTLM加密并存储了NTLMhash),这时候使用ophcrackNTLM表查找的就是这个NTLMhash了,而不是LMhash 

    展开全文
  • NTLM

    2017-08-01 10:54:36
    Windows挑战/响应(NTLM)是在运行Windows操作系统和独立系统的系统的网络上使用的身份验证协议。 Microsoft Kerberos 安全软件包比NTLM增加了对网络上的系统的安全性。虽然Microsoft Kerberos是协议的选择,...

    Windows挑战/响应(NTLM)是在运行Windows操作系统和独立系统的系统的网络上使用的身份验证协议。

    Microsoft Kerberos 安全软件包比NTLM增加了对网络上的系统的安全性。虽然Microsoft Kerberos是协议的选择,但NTLM仍然得到支持。NTLM还必须用于独立系统上的登录身份验证。有关Kerberos的详细信息,请参阅Microsoft Kerberos

    NTLM凭证基于在交互式登录过程中获得的数据,并由用户密码的域名,用户名和单向散列组成。NTLM使用加密的质询/响应协议来认证用户,而不会通过电线发送用户的密码。相反,请求身份验证的系统必须执行证明其可以访问受保护的NTLM凭据的计算。

    通过网络的交互式NTLM认证通常涉及两个系统:用户正在请求认证的客户端系统以及与用户密码有关的信息的域控制器。可能需要允许已登录用户访问资源(如服务器应用程序)的非交互式身份验证通常涉及三个系统:客户端,服务器和代表服务器进行身份验证计算的域控制器。

    以下步骤介绍了NTLM非交互式身份验证。第一步提供用户的NTLM凭据,仅作为交互式身份验证(登录)过程的一部分。

    1. (仅限交互式身份验证)用户访问客户端计算机并提供域名,用户名和密码。客户端计算密码的加密散列,并丢弃实际密码。
    2. 客户端将用户名发送到服务器(以明文形式)。
    3. 服务器生成一个16字节随机数,称为挑战随机数,并将其发送给客户端。
    4. 客户端使用用户密码的散列加密了此挑战,并将结果返回给服务器。这被称为响应
    5. 服务器将以下三个项目发送到域控制器:

      • 用户名
      • 挑战发送给客户端
      • 来自客户的回复
    6. 域控制器使用用户名从安全帐户管理器数据库中检索用户密码的散列。它使用此密码哈希来加密挑战。
    7. 域控制器将其计算的加密挑战(在步骤6中)与由客户端计算的响应进行比较(步骤4)。如果它们相同,则验证成功。

    您的应用程序不应直接访问NTLM 安全包 ; 相反,它应该使用协商安全包。协商允许您的应用程序利用更高级的安全协议(如果身份验证中涉及的系统支持)。目前,Negotiate安全包在Kerberos和NTLM 之间进行选择。协商选择Kerberos,除非认证中涉及的系统之一不能使用它

    展开全文
  • 创建时间:2003-05-28文章属性:原创文章提交:flashsky (flashsky1_at_sina.com)NTLM挑战模式散列认证加密协议过程,算法实现与一些想法转摘请注明作者和安全焦点作者:FLASHSKYSITE:http://www.xfocus.net/,...
  • NTLM认证

    2012-10-11 16:36:37
    NTLM 默认设置(NTLM 协议)基于一种“提问 - 答复”机制来进行客户端验证。NTLM是NT LAN Manager的缩写,这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议,...1、客户端首先在本地加密当前用户的密
  • c++实现LM和NTLM哈希

    2021-06-24 01:30:17
    在vs2008下实现NTLM和LM哈希加密,包含MD4加密和DES加密函数 在vs2008下实现NTLM和LM哈希加密,包含MD4加密和DES加密函数
  • NTLM 协议

    千次阅读 2014-02-10 21:12:41
    微软提出了WindowsNT挑战/响应验证机制,称之为NTLM。 现在已经有了更新的NTLMv2以及Kerberos验证体系。NTLM是windows早期安全协议,因向后兼容性而保留下来。NTLM是NT LAN Manager的缩写,即NT LAN管理器。 ...
  • 实战NTLM

    千次阅读 2012-05-25 10:53:35
    实战NTLM 项目描述:2个域,A和B A的域服务器连接外网,同时装有isa2004防火墙,开web代理,信任域B 需要域B的一台机器上穿透代理连接外网服务器(不是http服务器) 完成代穿透后,卡在isa上;使用443意外端口...
  • NTLM 了解

    2014-05-03 19:29:00
    NTLM 是 Windows NT 早期版本的标准安全协议,Windows 2000 支持 NTLM 是为了保持向后兼容。Windows 2000内置三种基本安全协议之一。   1 早期SMB协议在网络上传输明文口令。后来出现 LAN Manager ...
  • 关于NTLM

    千次阅读 2004-08-25 19:43:00
    早期的SMB协议在网络上明文传输口令,后来出现了"LAN Manager Challenge/Response"验证机制,...NTLM工作流程是这样的:1、客户端首先在本地加密当前用户的密码成为密码散列2、客户端向服务器发送自己的帐号,这个帐
  • NTLM认证协议及SSPI的NTLM实现

    千次阅读 2018-09-05 19:43:22
    没错,NTLM就是你听说过的那个NTLM。是微软应用最广泛的认证协议之一。 NTLM是NT LAN Manager的缩写,这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议。Windows 2000内置三种基本安全协议之一。 ...
  • NTLM认证过程

    2020-07-30 00:20:30
    NTLM 步骤说明: 客户端缓存密码的哈希值,丢弃原始密码 客户端向服务器发送明文形式的用户名 服务器端生成一个16位的随机数,作为challenge发送给客户端 客户端使用密码的哈希值加密challenge,并将结果...
  • 2021年7月19日,法国安全研究人员Gilles Lionel披露了一种新型的NTLM Relay攻击利用手法——PetitPotam。该漏洞利用了微软加密文件系统远程协议(MS-EFSRPC,MicroSoftEncrypting File System Remote Protocol)。MS...
  • 以及着重介绍ntlm两大安全问题–PTH和ntlm_relay。 ntlm篇分为四篇文章 第1篇文章也是本文,这篇文章主要简单介绍一些基础概念以及引进一些相关的漏洞,比如Pass The Hash以及ntlm_relay。 其余三篇文章的内容...
  • NTLM身份验证

    千次阅读 2008-05-31 20:56:00
    NTLM工作流程是这样的: 1、客户端首先在本地加密当前用户的密码成为密码散列 2、客户端向服务器发送自己的帐号,这个帐号是没有经过加密的,明文直接传输 3、服务器产生一个16位的随机数字发送给客户端,作为一个 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,474
精华内容 2,589
关键字:

ntlm加密