View Javadoc
1   package org.metricshub.winrm.service.client.encryption;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * WinRM Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 - 2024 Metricshub
8    * ჻჻჻჻჻჻
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
21   */
22  
23  import java.security.MessageDigest;
24  
25  /**
26   * Cryptography support - HMACMD5 - algorithmically based on various web
27   * resources by Karl Wright
28   *
29   * Code from io.cloudsoft.winrm4j.client.ntlm.forks.httpclient.NTLMEngineImpl
30   * release 0.12.3 @link https://github.com/cloudsoft/winrm4j
31   * io.cloudsoft.winrm4j.client.ntlm.forks.httpclient is a fork of apache-httpclient 4.5.13
32   */
33  public class HMACMD5 {
34  
35  	private final byte[] ipad;
36  	private final byte[] opad;
37  	private final MessageDigest md5;
38  
39  	HMACMD5(final byte[] input) {
40  		byte[] key = input;
41  		md5 = EncryptionUtils.getMD5();
42  
43  		// Initialize the pad buffers with the key
44  		ipad = new byte[64];
45  		opad = new byte[64];
46  
47  		int keyLength = key.length;
48  		if (keyLength > 64) {
49  			// Use MD5 of the key instead, as described in RFC 2104
50  			md5.update(key);
51  			key = md5.digest();
52  			keyLength = key.length;
53  		}
54  		int i = 0;
55  		while (i < keyLength) {
56  			ipad[i] = (byte) (key[i] ^ (byte) 0x36);
57  			opad[i] = (byte) (key[i] ^ (byte) 0x5c);
58  			i++;
59  		}
60  		while (i < 64) {
61  			ipad[i] = (byte) 0x36;
62  			opad[i] = (byte) 0x5c;
63  			i++;
64  		}
65  
66  		// Very important: processChallenge the digest with the ipad buffer
67  		md5.reset();
68  		md5.update(ipad);
69  	}
70  
71  	/** Grab the current digest. This is the "answer". */
72  	byte[] getOutput() {
73  		final byte[] digest = md5.digest();
74  		md5.update(opad);
75  		return md5.digest(digest);
76  	}
77  
78  	/** Update by adding a complete array */
79  	void update(final byte[] input) {
80  		md5.update(input);
81  	}
82  }