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 }