ntlm.java
来自「这是linux下ssl vpn的实现程序」· Java 代码 · 共 496 行 · 第 1/2 页
JAVA
496 行
* Creates the type 3 message using the given server nonce. The type 3 message includes all the
* information for authentication, host, domain, username and the result of encrypting the
* nonce sent by the server using the user's password as the key.
*
* @param user The user name. This should not include the domain name.
* @param password The password.
* @param host The host that is originating the authentication request.
* @param domain The domain to authenticate within.
* @param nonce the 8 byte array the server sent.
* @return The type 3 message.
* @throws AuthenticationException If {@encrypt(byte[],byte[])} fails.
*/
public String getType3Message(String user, String password,
String host, String domain, byte[] nonce)
throws IOException {
int ntRespLen = 0;
int lmRespLen = 24;
domain = domain.toUpperCase();
host = host.toUpperCase();
user = user.toUpperCase();
byte[] domainBytes = domain.getBytes();
byte[] hostBytes = host.getBytes();
byte[] userBytes = user.getBytes();
int domainLen = domainBytes.length;
int hostLen = hostBytes.length;
int userLen = userBytes.length;
int finalLength = 64 + ntRespLen + lmRespLen + domainLen
+ userLen + hostLen;
prepareResponse(finalLength);
byte[] ntlmssp = "NTLMSSP".getBytes();
addBytes(ntlmssp);
addByte((byte) 0);
addByte((byte) 3);
addByte((byte) 0);
addByte((byte) 0);
addByte((byte) 0);
// LM Resp Length (twice)
addBytes(convertShort(24));
addBytes(convertShort(24));
// LM Resp Offset
addBytes(convertShort(finalLength - 24));
addByte((byte) 0);
addByte((byte) 0);
// NT Resp Length (twice)
addBytes(convertShort(0));
addBytes(convertShort(0));
// NT Resp Offset
addBytes(convertShort(finalLength));
addByte((byte) 0);
addByte((byte) 0);
// Domain length (twice)
addBytes(convertShort(domainLen));
addBytes(convertShort(domainLen));
// Domain offset.
addBytes(convertShort(64));
addByte((byte) 0);
addByte((byte) 0);
// User Length (twice)
addBytes(convertShort(userLen));
addBytes(convertShort(userLen));
// User offset
addBytes(convertShort(64 + domainLen));
addByte((byte) 0);
addByte((byte) 0);
// Host length (twice)
addBytes(convertShort(hostLen));
addBytes(convertShort(hostLen));
// Host offset
addBytes(convertShort(64 + domainLen + userLen));
for (int i = 0; i < 6; i++) {
addByte((byte) 0);
}
// Message length
addBytes(convertShort(finalLength));
addByte((byte) 0);
addByte((byte) 0);
// Flags
addByte((byte) 6);
addByte((byte) 82);
addByte((byte) 0);
addByte((byte) 0);
addBytes(domainBytes);
addBytes(userBytes);
addBytes(hostBytes);
addBytes(hashPassword(password, nonce));
return getResponse();
}
/**
* Creates the LANManager and NT response for the given password using the
* given nonce.
* @param password the password to create a hash for.
* @param nonce the nonce sent by the server.
* @return The response.
* @throws HttpException If {@link #encrypt(byte[],byte[])} fails.
*/
private byte[] hashPassword(String password, byte[] nonce)
throws IOException {
byte[] passw = password.toUpperCase().getBytes();
byte[] lmPw1 = new byte[7];
byte[] lmPw2 = new byte[7];
int len = passw.length;
if (len > 7) {
len = 7;
}
int idx;
for (idx = 0; idx < len; idx++) {
lmPw1[idx] = passw[idx];
}
for (; idx < 7; idx++) {
lmPw1[idx] = (byte) 0;
}
len = passw.length;
if (len > 14) {
len = 14;
}
for (idx = 7; idx < len; idx++) {
lmPw2[idx - 7] = passw[idx];
}
for (; idx < 14; idx++) {
lmPw2[idx - 7] = (byte) 0;
}
// Create LanManager hashed Password
byte[] magic = {
(byte) 0x4B, (byte) 0x47, (byte) 0x53, (byte) 0x21,
(byte) 0x40, (byte) 0x23, (byte) 0x24, (byte) 0x25
};
byte[] lmHpw1;
lmHpw1 = encrypt(lmPw1, magic);
byte[] lmHpw2 = encrypt(lmPw2, magic);
byte[] lmHpw = new byte[21];
for (int i = 0; i < lmHpw1.length; i++) {
lmHpw[i] = lmHpw1[i];
}
for (int i = 0; i < lmHpw2.length; i++) {
lmHpw[i + 8] = lmHpw2[i];
}
for (int i = 0; i < 5; i++) {
lmHpw[i + 16] = (byte) 0;
}
// Create the responses.
byte[] lmResp = new byte[24];
calcResp(lmHpw, nonce, lmResp);
return lmResp;
}
/**
* Takes a 21 byte array and treats it as 3 56-bit DES keys. The 8 byte
* plaintext is encrypted with each key and the resulting 24 bytes are
* stored in the results array.
*
* @param keys The keys.
* @param plaintext The plain text to encrypt.
* @param results Where the results are stored.
* @throws AuthenticationException If {@link #encrypt(byte[],byte[])} fails.
*/
private void calcResp(byte[] keys, byte[] plaintext, byte[] results)
throws IOException {
byte[] keys1 = new byte[7];
byte[] keys2 = new byte[7];
byte[] keys3 = new byte[7];
for (int i = 0; i < 7; i++) {
keys1[i] = keys[i];
}
for (int i = 0; i < 7; i++) {
keys2[i] = keys[i + 7];
}
for (int i = 0; i < 7; i++) {
keys3[i] = keys[i + 14];
}
byte[] results1 = encrypt(keys1, plaintext);
byte[] results2 = encrypt(keys2, plaintext);
byte[] results3 = encrypt(keys3, plaintext);
for (int i = 0; i < 8; i++) {
results[i] = results1[i];
}
for (int i = 0; i < 8; i++) {
results[i + 8] = results2[i];
}
for (int i = 0; i < 8; i++) {
results[i + 16] = results3[i];
}
}
/**
* Converts a given number to a two byte array in little endian order.
* @param num the number to convert.
* @return The byte representation of <i>num</i> in little endian order.
*/
private byte[] convertShort(int num) {
byte[] val = new byte[2];
String hex = Integer.toString(num, 16);
while (hex.length() < 4) {
hex = "0" + hex;
}
String low = hex.substring(2, 4);
String high = hex.substring(0, 2);
val[0] = (byte) Integer.parseInt(low, 16);
val[1] = (byte) Integer.parseInt(high, 16);
return val;
}
/**
* @return Returns the credentialCharset.
*/
public String getCredentialCharset() {
return credentialCharset;
}
/**
* @param credentialCharset The credentialCharset to set.
*/
public void setCredentialCharset(String credentialCharset) {
this.credentialCharset = credentialCharset;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?