[jcifs] Quick LM Hash question.

Michael B.Allen mballen at erols.com
Fri Apr 5 19:38:23 EST 2002


On Fri, 5 Apr 2002 00:33:27 -0600
Christopher R.Hertel <crh at ubiqx.mn.org> wrote:

> I am working on figuring out the authentication schemes used by Windows,
> both for my book and for a presentation I'm doing.  I've got a quick
> question.  My hope is that someone (Mike?) can point me to the specific
> place where this is handled in jCIFS.  I've been through the DES and MD4
> code, but that's at a slightly lower level.
> 
> Here's the deal.  All of the docs I've seen show the LanMan (LM) alorithm
> as:
> 
>   E(K0K1,D0D1) = E(K0,D0)E(K0,D1)E(K1,D0)E(K1,D1)
> 
> This is what Leach wrote, but it doesn't make sense.  The result of the
> above is the same as:
> 
>   E(K0K1,D0D1) = E(K0,D0D1)E(K1,D0D1)
> 
> Which just gives two concatonated strings, each the result of encrypting
> the same data with two different keys.
> 
> I *think* that what should happen is:
> 
>   E(K0K1,D0D1) = E(K1, E(K0,D0D1))
> 
> So, I'm digging through to find the code that actually does LanMan
> password hashing.
> 
> Mike: Where do I look?  NegProt?

With what object would you expect to perform encrypted
authentication? It's all right at the top of SmbSession.java:

  // KGS!@#$%
  static final byte[] S8 = {
      (byte)0x4b, (byte)0x47, (byte)0x53, (byte)0x21,
      (byte)0x40, (byte)0x23, (byte)0x24, (byte)0x25
  };
  static void E( byte[] key, byte[] data, byte[] e ) {
      byte[] key7 = new byte[7];
      byte[] e8 = new byte[8];

      for( int i = 0; i < key.length / 7; i++ ) { 
          System.arraycopy( key, i * 7, key7, 0, 7 ); 
          DES des = new DES( key7 ); 
          des.encrypt( data, e8 );
          System.arraycopy( e8, 0, e, i * 8, 8 ); 
      }
  }
  static byte[] getPreNTLMResponse( String password, byte[] challenge ) {
      byte[] p14 = new byte[14];
      byte[] p21 = new byte[21];
      byte[] p24 = new byte[24];

      System.arraycopy( password.toUpperCase().getBytes(), 0, p14, 0, password.length() );
      E( p14, S8, p21);
      E( p21, challenge, p24);
      return p24;
  }
  static byte[] getNTLMResponse( String password, byte[] challenge ) {
      byte[] uni = null;
      byte[] p21 = new byte[21];
      byte[] p24 = new byte[24];

      try {
          uni = password.getBytes( "UnicodeLittleUnmarked" );
      } catch( UnsupportedEncodingException uee ) {
          Log.printStackTrace( "password encryption exception", uee );
      }
      MD4 md4 = new MD4();
      md4.update( uni );
      System.arraycopy( md4.digest(), 0, p21, 0, 16 );
      E( p21, challenge, p24 ); 
      return p24;
  }

This sort of thing is not easy to describe in an e-mail. You just have
to follow through it carefully once and write code as you go along. Of
course you want to run your test example with a challenge and password
copied out of a real SessionSetupAndX call and then compare the
generated hashes.

Mike

-- 
May The Source be with you.





More information about the jcifs mailing list