Skip to content

Instantly share code, notes, and snippets.

@i-sync
Last active January 21, 2021 17:08
Show Gist options
  • Select an option

  • Save i-sync/2dc65b8acacfc3a99080b22ef5c877ba to your computer and use it in GitHub Desktop.

Select an option

Save i-sync/2dc65b8acacfc3a99080b22ef5c877ba to your computer and use it in GitHub Desktop.
iHuman Android application API signature parameter algorithm - ihuman.apk.2.0.1
package com.ihuman.hpfutility.net.d;
import android.text.TextUtils;
import android.util.Pair;
import cn.jiguang.net.HttpUtils;
import com.google.devtools.build.android.desugar.runtime.ThrowableExtension;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.huawei.hms.support.api.entity.pay.HwPayConstant;
import com.ihuman.hpfutility.net.e.b;
import com.ihuman.hpfutility.net.entry.ExcludeParamIfEmpty;
import com.ihuman.hpfutility.net.entry.SignId;
import com.ihuman.hpfutility.net.entry.SignParam;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import org.json.JSONObject;
public abstract class c<T> extends a<T> {
private static final Gson BZ = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().enableComplexMapKeySerialization().create();
@SerializedName("platform")
@Expose
private String Ca = "Android";
@SignId(2)
@SerializedName("deviceid")
@Expose
@ExcludeParamIfEmpty
private String Cb;
@SignId(8)
@SerializedName("timestamp")
@Expose
@ExcludeParamIfEmpty
private long time;
@SignId(16)
@SerializedName("token")
@Expose
@ExcludeParamIfEmpty
private String token;
@SignId(1)
@SerializedName("uid")
@Expose
@ExcludeParamIfEmpty
private String userId;
private static class a implements Comparator<Pair<String, ? extends Object>> {
private a() {
}
/* renamed from: a */
public int compare(Pair<String, ? extends Object> pair, Pair<String, ? extends Object> pair2) {
return ((String) pair.first).compareToIgnoreCase((String) pair2.first);
}
}
private String b(List<Pair<String, ? extends Object>> list, boolean z) {
Collections.sort(list, new a());
StringBuilder sb = new StringBuilder();
int size = list.size();
for (int i = 0; i < size; i++) {
Pair pair = (Pair) list.get(i);
if (i != 0) {
sb.append(HttpUtils.PARAMETERS_SEPARATOR);
}
sb.append((String) pair.first).append(HttpUtils.EQUAL_SIGN).append(z ? com.ihuman.hpfutility.common.b.a.URLEncode(pair.second.toString()) : pair.second);
}
return sb.toString();
}
public com.ihuman.hpfutility.net.e.a<T> a(b bVar) {
byte[] ig = bVar.ig();
if (bVar.ig() == null) {
return null;
}
try {
JSONObject jSONObject = new JSONObject(new String(ig));
int optInt = jSONObject.optInt("code", -1);
return (optInt == 0 || optInt == 2000) ? new com.ihuman.hpfutility.net.e.a<>(an(jSONObject.optString("result", "")), optInt) : new com.ihuman.hpfutility.net.e.a<>(optInt, jSONObject.optString("message", ""));
} catch (Exception e) {
return new com.ihuman.hpfutility.net.e.a<>(-1, e.getMessage());
}
}
public void am(String str) {
this.Cb = str;
}
/* access modifiers changed from: protected */
public T an(String str) {
Class cls = m1if();
Type ie = ie();
if (cls != null) {
return BZ.fromJson(str, cls);
}
if (ie != null) {
return BZ.fromJson(str, ie);
}
return null;
}
public HashMap<String, String> hZ() {
return null;
}
public HashMap<String, String> ia() {
Field[] declaredFields;
Pair pair;
HashMap<String, String> hashMap = new HashMap<>();
int id = id();
ArrayList arrayList = new ArrayList();
ArrayList<Pair> arrayList2 = new ArrayList<>();
Class cls = getClass();
while (true) {
Class cls2 = cls;
for (Field field : cls2.getDeclaredFields()) {
if (((Expose) field.getAnnotation(Expose.class)) != null) {
SignId signId = (SignId) field.getAnnotation(SignId.class);
SignParam signParam = (SignParam) field.getAnnotation(SignParam.class);
boolean z = !(signId == null || (signId.value() & id) == 0) || (signParam != null && signParam.hV());
field.getType().getName();
SerializedName serializedName = (SerializedName) field.getAnnotation(SerializedName.class);
String str = serializedName != null ? serializedName.value() : field.getName();
field.setAccessible(true);
try {
if (((ExcludeParamIfEmpty) field.getAnnotation(ExcludeParamIfEmpty.class)) == null) {
pair = new Pair(str, field.get(this));
} else {
Object obj = field.get(this);
boolean z2 = true;
if (obj == null) {
z2 = false;
} else if (obj instanceof Number) {
z2 = ((Number) obj).longValue() != 0;
} else if (obj instanceof String) {
z2 = !TextUtils.isEmpty((String) obj);
}
if (z2) {
pair = new Pair(str, obj);
}
pair = null;
}
} catch (IllegalAccessException e) {
ThrowableExtension.printStackTrace(e);
}
if (pair != null) {
arrayList2.add(pair);
if (z) {
arrayList.add(pair);
}
}
}
}
cls = cls2.getSuperclass();
if (cls == null) {
break;
}
}
for (Pair pair2 : arrayList2) {
hashMap.put(pair2.first, pair2.second == null ? "" : pair2.second.toString());
}
String ao = com.ihuman.hpfutility.net.f.a.ao(b(arrayList, false));
if (ao == null) {
throw new IllegalArgumentException("Sign data error !");
}
hashMap.put(HwPayConstant.KEY_SIGN, ao);
return hashMap;
}
public int ib() {
return 1;
}
public int id() {
return 27;
}
/* access modifiers changed from: protected */
public Type ie() {
return null;
}
/* access modifiers changed from: protected */
/* renamed from: if reason: not valid java name */
public abstract Class<T> m1if();
public void setTime(long j) {
this.time = j;
}
public void setToken(String str) {
this.token = str;
}
public void setUserId(String str) {
this.userId = str;
}
}
package com.ihuman.hpfutility.net.f;
import com.google.devtools.build.android.desugar.runtime.ThrowableExtension;
import com.umeng.analytics.pro.dm;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class a {
private static final char[] Cd = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String ao(String str) {
String ap = ap(str);
if (ap != null) {
return aq(ap);
}
return null;
}
public static String ap(String str) {
byte[] digest;
try {
byte[] bytes = str.getBytes();
MessageDigest instance = MessageDigest.getInstance("MD5");
instance.update(bytes);
char[] cArr = new char[(r4 * 2)];
int i = 0;
for (byte b : instance.digest()) {
int i2 = i + 1;
cArr[i] = (char) Cd[(b >>> 4) & 15];
i = i2 + 1;
cArr[i2] = (char) Cd[b & dm.m];
}
return new String(cArr);
} catch (Exception e) {
ThrowableExtension.printStackTrace(e);
return null;
}
}
public static String aq(String str) {
return k(str, "SHA-256");
}
private static String k(String str, String str2) {
if (str == null || str.length() <= 0) {
return null;
}
try {
MessageDigest instance = MessageDigest.getInstance(str2);
instance.update(str.getBytes());
byte[] digest = instance.digest();
StringBuffer stringBuffer = new StringBuffer();
for (byte b : digest) {
String hexString = Integer.toHexString(b & 255);
if (hexString.length() == 1) {
stringBuffer.append('0');
}
stringBuffer.append(hexString);
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
ThrowableExtension.printStackTrace(e);
return null;
}
}
}
#!/usr/bin/env python3
# _*_ coding: utf-8 _*_
import json
import os
import time
import re
import sys, getopt
import hashlib
import requests
import random
from collections import OrderedDict
#无符号右移
import ctypes
def int_overflow(val):
maxint = 2147483647
if not -maxint-1 <= val <= maxint:
val = (val + (maxint + 1)) % (2 * (maxint + 1)) - maxint - 1
return val
def unsigned_right_shitf(n,i):
# 数字小于0,则转为32位无符号uint
if n<0:
n = ctypes.c_uint32(n).value
# 正常位移位数是为正数,但是为了兼容js之类的,负数就右移变成左移好了
if i<0:
return -int_overflow(n << abs(i))
#print(n)
return int_overflow(n >> i)
def get_sign(data):
src = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
ordered_data = OrderedDict(sorted(data.items()))
ordered_data_str = '&'.join([f"{k}={ordered_data[k]}" for k in ordered_data.keys()])
print(ordered_data_str)
digest = hashlib.md5(f'{ordered_data_str}'.encode('utf-8')).digest()
r = []
for d in digest:
i = unsigned_right_shitf(d, 4) & 15
r.append(src[i])
r.append(src[d & 15])
m5 = ''.join(r)
print(m5)
s256 = str(hashlib.sha256(m5.encode('utf-8')).hexdigest())
return s256
if __name__ == "__main__":
'''
key: id value,
2.0.1 : id=27, sign params [uid, deviceid, token, timestamp] for checkin request
4.1.0 : id=10, sign params [deviceid, timestamp] for most post request. album,...
& opeator
signid |param |27 |10
1 |uid |1 |0
2 |deviceid |2 |2
8 |timestamp |8 |8
16 |token |16 |0
'''
param = {
'uid': 'userid',
#'app_version': '4.1.0',
#'device': 'phone',
'deviceid': 'deviceid',
#'platform': 'Android',
'token': 'token',
'timestamp': 'timestamp'
}
new_sign = get_sign(param)
print(new_sign)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment