package com.ruterfu.test; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import okhttp3.*; import javax.crypto.Mac; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Random; public class HuaweiWS5200AccessUtils { private String csrfParam; private String csrfToken; private String cookie; private final OkHttpClient okHttpClient = new OkHttpClient(); private static final String URL = "http://10.0.0.10"; private static final String password = "123456"; public static void main(String[] args) { HuaweiWS5200AccessUtils router = new HuaweiWS5200AccessUtils(); if(router.init() && router.login()) { // 获得主机 String data = router.accessRouter("/api/system/HostInfo"); System.out.println(data); } } public boolean login() { JSONObject data = new JSONObject(); String firstNonce = randomNonce(); data.put("username", "admin"); data.put("firstnonce", firstNonce); JSONObject loginNonce = accessRouter("/api/system/user_login_nonce", data, null); if(loginNonce != null) { try { int iterations = loginNonce.getIntValue("iterations"); String salt = loginNonce.getString("salt"); String serverNonce = loginNonce.getString("servernonce"); byte[] saltedPassword = getSaltedPassword(password, hexToByteArray(salt), iterations); byte[] clientKey = getHmac("Client Key", saltedPassword); byte[] storeKey = getStoreKey(clientKey); String authMsg = firstNonce + "," + serverNonce + "," + serverNonce; byte[] clientSignature = getHmac(authMsg, storeKey); for (int i = 0; i < clientKey.length; i++) { clientKey[i] = (byte) (clientKey[i] ^ clientSignature[i]); } String clientProof = bytesToHex(clientKey); JSONObject login = new JSONObject(); login.put("clientproof", clientProof); login.put("finalnonce", serverNonce); JSONObject loginDone = accessRouter("/api/system/user_login_proof", login, null); return loginDone.containsKey("err") && loginDone.getIntValue("err") == 0; } catch (Exception e) { e.printStackTrace(); } } return false; } private byte[] getSaltedPassword(String password, byte[] salt, int iterations) throws NoSuchAlgorithmException, InvalidKeySpecException { KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, 256); SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); return f.generateSecret(spec).getEncoded(); } private byte[] getHmac(String key, byte[] input) throws NoSuchAlgorithmException, InvalidKeyException { String hmacName = "HmacSHA256"; SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.US_ASCII), hmacName); Mac mac = Mac.getInstance(hmacName); mac.init(secretKeySpec); mac.update(input); return mac.doFinal(); } private byte[] getStoreKey(byte[] clientKey) throws NoSuchAlgorithmException { return MessageDigest.getInstance("SHA-256").digest(clientKey); } /** * from https://blog.csdn.net/qq_34763699/article/details/78650272 */ public static byte[] hexToByteArray(String inHex){ int hexLength = inHex.length(); byte[] result; if (hexLength % 2 == 1){ hexLength++; result = new byte[(hexLength / 2)]; inHex = "0" + inHex; }else { result = new byte[(hexLength / 2)]; } int j=0; for (int i = 0; i < hexLength; i += 2){ result[j]=(byte)Integer.parseInt(inHex.substring(i, i + 2),16); j++; } return result; } /** * from https://blog.csdn.net/qq_34763699/article/details/78650272 */ public static String bytesToHex(byte[] bytes) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if(hex.length() < 2){ sb.append(0); } sb.append(hex); } return sb.toString(); } public boolean init() { Request request = new Request.Builder().url(URL + "/html/index.html").get().build(); try(Response response = okHttpClient.newCall(request).execute(); ResponseBody responseBody = response.body() != null ? response.body() : null) { if(response.code() == 200) { String data = responseBody.string(); int csrfStart = data.indexOf("csrf_param"); data = data.substring(csrfStart); int csrfParamStart = data.indexOf("=\""); int csrfParamEnd = data.indexOf("\"/>"); csrfParam = data.substring(csrfParamStart + 2, csrfParamEnd).trim(); int csrfTokenStart = data.indexOf("csrf_token"); data = data.substring(csrfTokenStart); int csrfTokenParamStart = data.indexOf("=\""); int csrfTokenParamEnd = data.indexOf("\"/>"); csrfToken = data.substring(csrfTokenParamStart + 2, csrfTokenParamEnd).trim(); String cookiePath = response.header("Set-Cookie"); int cookieSplit = cookiePath.indexOf(";"); cookie = cookiePath.substring(0, cookieSplit); return true; } } catch (Exception e) { e.printStackTrace(); } return false; } private JSONObject accessRouter(String url, JSONObject data, String action) { JSONObject jsonObject = new JSONObject(); JSONObject csrf = new JSONObject(); csrf.put("csrf_param", csrfParam); csrf.put("csrf_token", csrfToken); jsonObject.put("csrf", csrf); jsonObject.put("data", data); if(action != null && action.length() > 0) { jsonObject.put("action", action); } Request request = new Request.Builder().url(URL + url).header("Cookie", cookie).post(RequestBody.create(jsonObject.toJSONString(), MediaType.parse("application/json"))).build(); try(Response response = okHttpClient.newCall(request).execute(); ResponseBody responseBody = response.body() != null ? response.body() : null) { if(response.code() == 200) { JSONObject repsJson = JSON.parseObject(responseBody.string()); if(repsJson.containsKey("csrf_token")) { this.csrfToken = repsJson.getString("csrf_token"); repsJson.remove("csrf_token"); } if(repsJson.containsKey("csrf_param")) { this.csrfParam = repsJson.getString("csrf_param"); repsJson.remove("csrf_param"); } String newHeader = response.header("Set-Cookie"); if(newHeader != null) { cookie = newHeader; } return repsJson; } } catch (Exception e) { e.printStackTrace(); } return null; } private String accessRouter(String url) { Request request = new Request.Builder().url(URL + url).header("Cookie", cookie).get().build(); try(Response response = okHttpClient.newCall(request).execute(); ResponseBody responseBody = response.body() != null ? response.body() : null) { if(response.code() == 200) { String body = responseBody.string(); String newHeader = response.header("Set-Cookie"); if(newHeader != null) { cookie = newHeader; } return body; } } catch (Exception e) { e.printStackTrace(); } return null; } private String randomNonce() { String rand = "abcdef1234567890"; Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 64; i++) { int number = random.nextInt(rand.length()); sb.append(rand.charAt(number)); } return sb.toString(); } }
https://www.ruterfu.com/2021/04/19/20210419-login-by-codes-huawei-router-WS5200/